diff --git a/DEPS b/DEPS
index 3f21ef014..ef67709 100644
--- a/DEPS
+++ b/DEPS
@@ -209,11 +209,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '54593e74241986f1ba7e22675fda6a028320ef4c',
+  'skia_revision': '8447f13c6d4b572733691c2a28a8b6999123b926',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '51238348f95a1f5e0acc321efac7942d18a687a2',
+  'v8_revision': 'e5e9fe700307fd42bc7b29ae13166cec46c796c7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -221,11 +221,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': 'a4ccd684027c44662035fea1b9177345dc83d8c4',
+  'angle_revision': '1f1e0e6c1020027b63f930361870af86a1e32f5c',
   # 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': '024bf32587e5af4c5911778dfe66ec86522d98eb',
+  'swiftshader_revision': 'cbfa971a1850adcf8453777bcbf68c2ff5cd2375',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -280,7 +280,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': '88390a179e95252699e4f04790381e7159d29997',
+  'catapult_revision': 'cde766ee8a5ae51c7096dc51da56168f602baf33',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -288,7 +288,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': 'a02517d35155691d8c0d6180a6585ac2e64741b5',
+  'devtools_frontend_revision': '10f6bd19184400b77623c0b13948754cd77d1d02',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -328,7 +328,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'aa116522075e972a18f98f8f2836e90c00a8f08d',
+  'dawn_revision': '7e5947056393202c48b5e47850b712fb4bff7f7c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -573,7 +573,7 @@
   },
 
   'src/ios/third_party/material_components_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '77961e2c808c1c0d69b10b9b5352a69732882df1',
+      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '73c27ca0f0eb6cfe4ec607d3706ef58fe10ca56b',
       'condition': 'checkout_ios',
   },
 
@@ -966,7 +966,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'f0bcfdd702019e5b54c49b847ea3fca15cbb75c4',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '6097a92db01433615e08810c2db5fa1e68fb92a7',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1635,7 +1635,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@5c8e19fcdb44b5ed8751ff62196dbab754369289',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a0ac0fff8747c4140ca563ce40d6ea6e5124c5b8',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/browser/aw_autofill_client.cc b/android_webview/browser/aw_autofill_client.cc
index faf3e3d..26172fe 100644
--- a/android_webview/browser/aw_autofill_client.cc
+++ b/android_webview/browser/aw_autofill_client.cc
@@ -16,7 +16,6 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "components/autofill/core/browser/payments/legal_message_line.h"
 #include "components/autofill/core/browser/ui/autofill_popup_delegate.h"
 #include "components/autofill/core/browser/ui/suggestion.h"
diff --git a/android_webview/browser/aw_browser_terminator.cc b/android_webview/browser/aw_browser_terminator.cc
index 5d54028b..43923eb 100644
--- a/android_webview/browser/aw_browser_terminator.cc
+++ b/android_webview/browser/aw_browser_terminator.cc
@@ -12,7 +12,6 @@
 #include "android_webview/common/aw_descriptors.h"
 #include "base/android/scoped_java_ref.h"
 #include "base/logging.h"
-#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "components/crash/content/browser/crash_metrics_reporter_android.h"
 #include "components/crash/core/app/crashpad.h"
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index ae17246..e35a48dc 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -47,7 +47,6 @@
 #include "base/files/scoped_file.h"
 #include "base/memory/ptr_util.h"
 #include "base/path_service.h"
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/thread_pool/thread_pool_instance.h"
 #include "build/build_config.h"
diff --git a/android_webview/browser/gfx/hardware_renderer_viz.cc b/android_webview/browser/gfx/hardware_renderer_viz.cc
index 6c90b09..f6743d2 100644
--- a/android_webview/browser/gfx/hardware_renderer_viz.cc
+++ b/android_webview/browser/gfx/hardware_renderer_viz.cc
@@ -25,7 +25,6 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "base/trace_event/trace_event.h"
 #include "components/viz/common/display/renderer_settings.h"
 #include "components/viz/common/features.h"
diff --git a/android_webview/common/aw_media_drm_bridge_client.cc b/android_webview/common/aw_media_drm_bridge_client.cc
index d25af215..0446e531 100644
--- a/android_webview/common/aw_media_drm_bridge_client.cc
+++ b/android_webview/common/aw_media_drm_bridge_client.cc
@@ -7,7 +7,6 @@
 #include <utility>
 
 #include "base/logging.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 81366d9..bc33865 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1013,8 +1013,6 @@
     "system/holding_space/holding_space_item_screen_capture_view.h",
     "system/holding_space/holding_space_item_view.cc",
     "system/holding_space/holding_space_item_view.h",
-    "system/holding_space/holding_space_item_view_delegate.cc",
-    "system/holding_space/holding_space_item_view_delegate.h",
     "system/holding_space/holding_space_item_views_section.cc",
     "system/holding_space/holding_space_item_views_section.h",
     "system/holding_space/holding_space_tray.cc",
@@ -1029,6 +1027,8 @@
     "system/holding_space/holding_space_tray_icon_preview.h",
     "system/holding_space/holding_space_util.cc",
     "system/holding_space/holding_space_util.h",
+    "system/holding_space/holding_space_view_delegate.cc",
+    "system/holding_space/holding_space_view_delegate.h",
     "system/holding_space/pinned_files_bubble.cc",
     "system/holding_space/pinned_files_bubble.h",
     "system/holding_space/pinned_files_section.cc",
diff --git a/ash/accelerators/accelerator_commands.cc b/ash/accelerators/accelerator_commands.cc
index fe523078..361c15c 100644
--- a/ash/accelerators/accelerator_commands.cc
+++ b/ash/accelerators/accelerator_commands.cc
@@ -8,6 +8,7 @@
 #include "ash/shell.h"
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/screen_pinning_controller.h"
+#include "ash/wm/window_cycle/window_cycle_controller.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
 #include "ash/wm/wm_event.h"
@@ -19,23 +20,18 @@
 #include "ui/display/screen.h"
 #include "ui/gfx/geometry/point.h"
 
+// Keep the functions in this file in alphabetical order.
 namespace ash {
 namespace accelerators {
 
-using ::chromeos::WindowStateType;
+void CycleBackwardMru() {
+  Shell::Get()->window_cycle_controller()->HandleCycleWindow(
+      WindowCycleController::WindowCyclingDirection::kBackward);
+}
 
-bool ZoomDisplay(bool up) {
-  if (up)
-    base::RecordAction(base::UserMetricsAction("Accel_Scale_Ui_Up"));
-  else
-    base::RecordAction(base::UserMetricsAction("Accel_Scale_Ui_Down"));
-
-  display::DisplayManager* display_manager = Shell::Get()->display_manager();
-
-  gfx::Point point = display::Screen::GetScreen()->GetCursorScreenPoint();
-  display::Display display =
-      display::Screen::GetScreen()->GetDisplayNearestPoint(point);
-  return display_manager->ZoomDisplay(display.id(), up);
+void CycleForwardMru() {
+  Shell::Get()->window_cycle_controller()->HandleCycleWindow(
+      WindowCycleController::WindowCyclingDirection::kForward);
 }
 
 void ResetDisplayZoom() {
@@ -47,58 +43,6 @@
   display_manager->ResetDisplayZoom(display.id());
 }
 
-bool ToggleMinimized() {
-  aura::Window* window = window_util::GetActiveWindow();
-  // Attempt to restore the window that would be cycled through next from
-  // the launcher when there is no active window.
-  if (!window) {
-    // Do not unminimize a window on an inactive desk, since this will cause
-    // desks to switch and that will be unintentional for the user.
-    MruWindowTracker::WindowList mru_windows(
-        Shell::Get()->mru_window_tracker()->BuildMruWindowList(kActiveDesk));
-    if (!mru_windows.empty())
-      WindowState::Get(mru_windows.front())->Activate();
-    return true;
-  }
-  WindowState* window_state = WindowState::Get(window);
-  if (!window_state->CanMinimize())
-    return false;
-  window_state->Minimize();
-  return true;
-}
-
-void ToggleMaximized() {
-  aura::Window* active_window = window_util::GetActiveWindow();
-  if (!active_window)
-    return;
-  base::RecordAction(base::UserMetricsAction("Accel_Toggle_Maximized"));
-  WMEvent event(WM_EVENT_TOGGLE_MAXIMIZE);
-  WindowState::Get(active_window)->OnWMEvent(&event);
-}
-
-void ToggleFullscreen() {
-  aura::Window* active_window = window_util::GetActiveWindow();
-  if (!active_window)
-    return;
-  const WMEvent event(WM_EVENT_TOGGLE_FULLSCREEN);
-  WindowState::Get(active_window)->OnWMEvent(&event);
-}
-
-bool CanUnpinWindow() {
-  // WindowStateType::kTrustedPinned does not allow the user to press a key to
-  // exit pinned mode.
-  WindowState* window_state = WindowState::ForActiveWindow();
-  return window_state &&
-         window_state->GetStateType() == WindowStateType::kPinned;
-}
-
-void UnpinWindow() {
-  aura::Window* pinned_window =
-      Shell::Get()->screen_pinning_controller()->pinned_window();
-  if (pinned_window)
-    WindowState::Get(pinned_window)->Restore();
-}
-
 void ShiftPrimaryDisplay() {
   display::DisplayManager* display_manager = Shell::Get()->display_manager();
 
@@ -129,5 +73,63 @@
       primary_display_iter->id(), true /* throttle */);
 }
 
+void ToggleFullscreen() {
+  aura::Window* active_window = window_util::GetActiveWindow();
+  if (!active_window)
+    return;
+  const WMEvent event(WM_EVENT_TOGGLE_FULLSCREEN);
+  WindowState::Get(active_window)->OnWMEvent(&event);
+}
+
+void ToggleMaximized() {
+  aura::Window* active_window = window_util::GetActiveWindow();
+  if (!active_window)
+    return;
+  base::RecordAction(base::UserMetricsAction("Accel_Toggle_Maximized"));
+  WMEvent event(WM_EVENT_TOGGLE_MAXIMIZE);
+  WindowState::Get(active_window)->OnWMEvent(&event);
+}
+
+bool ToggleMinimized() {
+  aura::Window* window = window_util::GetActiveWindow();
+  // Attempt to restore the window that would be cycled through next from
+  // the launcher when there is no active window.
+  if (!window) {
+    // Do not unminimize a window on an inactive desk, since this will cause
+    // desks to switch and that will be unintentional for the user.
+    MruWindowTracker::WindowList mru_windows(
+        Shell::Get()->mru_window_tracker()->BuildMruWindowList(kActiveDesk));
+    if (!mru_windows.empty())
+      WindowState::Get(mru_windows.front())->Activate();
+    return true;
+  }
+  WindowState* window_state = WindowState::Get(window);
+  if (!window_state->CanMinimize())
+    return false;
+  window_state->Minimize();
+  return true;
+}
+
+void UnpinWindow() {
+  aura::Window* pinned_window =
+      Shell::Get()->screen_pinning_controller()->pinned_window();
+  if (pinned_window)
+    WindowState::Get(pinned_window)->Restore();
+}
+
+bool ZoomDisplay(bool up) {
+  if (up)
+    base::RecordAction(base::UserMetricsAction("Accel_Scale_Ui_Up"));
+  else
+    base::RecordAction(base::UserMetricsAction("Accel_Scale_Ui_Down"));
+
+  display::DisplayManager* display_manager = Shell::Get()->display_manager();
+
+  gfx::Point point = display::Screen::GetScreen()->GetCursorScreenPoint();
+  display::Display display =
+      display::Screen::GetScreen()->GetDisplayNearestPoint(point);
+  return display_manager->ZoomDisplay(display.id(), up);
+}
+
 }  // namespace accelerators
 }  // namespace ash
diff --git a/ash/accelerators/accelerator_commands.h b/ash/accelerators/accelerator_commands.h
index 5a118f2..54e48e64 100644
--- a/ash/accelerators/accelerator_commands.h
+++ b/ash/accelerators/accelerator_commands.h
@@ -9,38 +9,42 @@
 
 // This file contains implementations of commands that are bound to keyboard
 // shortcuts in Ash or in the embedding application (e.g. Chrome).
+//
+// Keep the functions in this file in alphabetical order.
 namespace ash {
 namespace accelerators {
 
-// Change the display zooming up or down.
-ASH_EXPORT bool ZoomDisplay(bool up);
+// Cycle backwards in the MRU window list. Usually Alt-Shift-Tab.
+ASH_EXPORT void CycleBackwardMru();
+
+// Cycle forwards in the MRU window list. Usually Alt-Tab.
+ASH_EXPORT void CycleForwardMru();
 
 // Reset the display zooming to the default state.
 ASH_EXPORT void ResetDisplayZoom();
 
+// Change primary display to the secondary display next to current primary
+// display
+ASH_EXPORT void ShiftPrimaryDisplay();
+
+// Toggles the fullscreen state. The behavior can be overridden
+// by WindowStateDelegate::ToggleFullscreen().
+ASH_EXPORT void ToggleFullscreen();
+
+// Toggles the maxmized state. If the window is in fulllscreen, it exits
+// fullscreen mode.
+ASH_EXPORT void ToggleMaximized();
+
 // Minimizes the active window, if present. If no windows are active, restores
 // the first unminimized window. Returns true if a window was minimized or
 // restored.
 ASH_EXPORT bool ToggleMinimized();
 
-// Toggles the maxmized state. If the window is in fulllscreen, it exits
-// fullscreen mode.
-ASH_EXPORT void ToggleMaximized();
-
-// Toggles the fullscreen state. The behavior can be overridden
-// by WindowStateDelegate::ToggleFullscreen().
-ASH_EXPORT void ToggleFullscreen();
-
-// True if the user can press a key to exit pinned mode (aka forced
-// fullscreen).
-ASH_EXPORT bool CanUnpinWindow();
-
 // If a window is pinned (aka forced fullscreen), exit from pinned mode.
 ASH_EXPORT void UnpinWindow();
 
-// Change primary display to the secondary display next to current primary
-// display
-ASH_EXPORT void ShiftPrimaryDisplay();
+// Change the display zooming up or down.
+ASH_EXPORT bool ZoomDisplay(bool up);
 
 }  // namespace accelerators
 }  // namespace ash
diff --git a/ash/accelerators/accelerator_controller_impl.cc b/ash/accelerators/accelerator_controller_impl.cc
index 89c0d249b4..8ca271f 100644
--- a/ash/accelerators/accelerator_controller_impl.cc
+++ b/ash/accelerators/accelerator_controller_impl.cc
@@ -78,7 +78,6 @@
 #include "ash/wm/overview/overview_session.h"
 #include "ash/wm/screen_pinning_controller.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
-#include "ash/wm/window_cycle/window_cycle_controller.h"
 #include "ash/wm/window_positioning_utils.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
@@ -151,6 +150,7 @@
 namespace {
 
 using base::UserMetricsAction;
+using chromeos::WindowStateType;
 using chromeos::input_method::InputMethodManager;
 using message_center::Notification;
 using message_center::SystemNotificationWarningLevel;
@@ -356,20 +356,14 @@
                             ImeSwitchType::kModeChangeKey);
 }
 
-void HandleCycleBackwardMRU(const ui::Accelerator& accelerator) {
+void RecordCycleBackwardMru(const ui::Accelerator& accelerator) {
   if (accelerator.key_code() == ui::VKEY_TAB)
     base::RecordAction(base::UserMetricsAction("Accel_PrevWindow_Tab"));
-
-  Shell::Get()->window_cycle_controller()->HandleCycleWindow(
-      WindowCycleController::WindowCyclingDirection::kBackward);
 }
 
-void HandleCycleForwardMRU(const ui::Accelerator& accelerator) {
+void RecordCycleForwardMru(const ui::Accelerator& accelerator) {
   if (accelerator.key_code() == ui::VKEY_TAB)
     base::RecordAction(base::UserMetricsAction("Accel_NextWindow_Tab"));
-
-  Shell::Get()->window_cycle_controller()->HandleCycleWindow(
-      WindowCycleController::WindowCyclingDirection::kForward);
 }
 
 void HandleActivateDesk(const ui::Accelerator& accelerator,
@@ -1691,6 +1685,14 @@
   return RootWindowController::ForTargetRootWindow()->touch_hud_debug();
 }
 
+bool CanUnpinWindow() {
+  // WindowStateType::kTrustedPinned does not allow the user to press a key to
+  // exit pinned mode.
+  WindowState* window_state = WindowState::ForActiveWindow();
+  return window_state &&
+         window_state->GetStateType() == WindowStateType::kPinned;
+}
+
 void HandleTouchHudClear() {
   RootWindowController::ForTargetRootWindow()->touch_hud_debug()->Clear();
 }
@@ -2141,7 +2143,7 @@
     case TOUCH_HUD_MODE_CHANGE:
       return CanHandleTouchHud();
     case UNPIN:
-      return accelerators::CanUnpinWindow();
+      return CanUnpinWindow();
     case WINDOW_CYCLE_SNAP_LEFT:
     case WINDOW_CYCLE_SNAP_RIGHT:
       return CanHandleWindowSnap();
@@ -2249,10 +2251,12 @@
       break;
     }
     case CYCLE_BACKWARD_MRU:
-      HandleCycleBackwardMRU(accelerator);
+      RecordCycleBackwardMru(accelerator);
+      accelerators::CycleBackwardMru();
       break;
     case CYCLE_FORWARD_MRU:
-      HandleCycleForwardMRU(accelerator);
+      RecordCycleForwardMru(accelerator);
+      accelerators::CycleForwardMru();
       break;
     case DESKS_ACTIVATE_DESK_LEFT:
       HandleActivateDesk(accelerator, /*activate_left=*/true);
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc
index ec26327..0e42e99 100644
--- a/ash/accelerators/accelerator_controller_unittest.cc
+++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -237,6 +237,8 @@
 
 }  // namespace
 
+// Note AcceleratorControllerTest can't be in the anonymous namespace because
+// it is referenced as a friend by exit_warning_handler.h
 class AcceleratorControllerTest : public AshTestBase {
  public:
   AcceleratorControllerTest() {
@@ -388,6 +390,8 @@
   DISALLOW_COPY_AND_ASSIGN(AcceleratorControllerTest);
 };
 
+namespace {
+
 // Double press of exit shortcut => exiting
 TEST_F(AcceleratorControllerTest, ExitWarningHandlerTestDoublePress) {
   ui::Accelerator press(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN);
@@ -627,8 +631,6 @@
   EXPECT_EQ(normal_bounds.ToString(), window->bounds().ToString());
 }
 
-namespace {
-
 class AcceleratorControllerTestWithClamshellSplitView
     : public AcceleratorControllerTest {
  public:
@@ -780,8 +782,6 @@
        WindowStateType::kMaximized);
 }
 
-}  // namespace
-
 TEST_F(AcceleratorControllerTest, RotateScreen) {
   display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
   display::Display::Rotation initial_rotation =
@@ -1666,8 +1666,6 @@
              AcceleratorControllerImpl::kVolumeButtonRegionScreen,
              AcceleratorControllerImpl::kVolumeButtonSideBottom)}));
 
-namespace {
-
 // Tests the TOGGLE_CAPS_LOCK accelerator.
 TEST_F(AcceleratorControllerTest, ToggleCapsLockAccelerators) {
   ImeControllerImpl* controller = Shell::Get()->ime_controller();
@@ -1801,8 +1799,6 @@
   DISALLOW_COPY_AND_ASSIGN(PreferredReservedAcceleratorsTest);
 };
 
-}  // namespace
-
 TEST_F(PreferredReservedAcceleratorsTest, AcceleratorsWithFullscreen) {
   aura::Window* w1 = CreateTestWindowInShellWithId(0);
   aura::Window* w2 = CreateTestWindowInShellWithId(1);
@@ -2133,6 +2129,22 @@
   EXPECT_TRUE(ProcessInController(accelerator));
 }
 
+// Tests the IME mode change key.
+TEST_F(AcceleratorControllerTest, ChangeIMEMode_SwitchesInputMethod) {
+  AddTestImes();
+
+  ImeController* controller = Shell::Get()->ime_controller();
+
+  TestImeControllerClient client;
+  controller->SetClient(&client);
+
+  EXPECT_EQ(0, client.next_ime_count_);
+
+  ProcessInController(ui::Accelerator(ui::VKEY_MODECHANGE, ui::EF_NONE));
+
+  EXPECT_EQ(1, client.next_ime_count_);
+}
+
 class AcceleratorControllerInputMethodTest : public AcceleratorControllerTest {
  public:
   AcceleratorControllerInputMethodTest() = default;
@@ -2189,8 +2201,6 @@
   EXPECT_EQ(1u, mock_input_->cancel_composition_call_count);
 }
 
-namespace {
-
 // TODO(crbug.com/1179893): Remove once the feature is enabled permanently.
 class AcceleratorControllerDeprecatedTest : public AcceleratorControllerTest {
  public:
@@ -2207,8 +2217,6 @@
   base::test::ScopedFeatureList scoped_feature_list_;
 };
 
-}  // namespace
-
 // TODO(crbug.com/1179893): Remove once the feature is enabled permanently.
 TEST_F(AcceleratorControllerDeprecatedTest, DeskShortcuts_Old) {
   // The shortcuts are Search+Shift+[MINUS|PLUS], but due to event
@@ -2224,8 +2232,6 @@
       ui::VKEY_OEM_MINUS, ui::EF_COMMAND_DOWN | ui::EF_SHIFT_DOWN)));
 }
 
-namespace {
-
 // Overrides SetUp() to do nothing so that the flag can be tested in both
 // directions during setup.
 // TODO(crbug.com/1179893): Remove suite once the feature is enabled by
@@ -2273,8 +2279,6 @@
   base::test::ScopedFeatureList scoped_feature_list_;
 };
 
-}  // namespace
-
 TEST_F(AcceleratorControllerStartupNotificationTest,
        StartupNotificationShownWhenEnabled) {
   // Set up the shell and controller.
@@ -2407,8 +2411,6 @@
                                   /*reply=*/absl::nullopt);
 }
 
-namespace {
-
 // defines a class to test the behavior of deprecated accelerators.
 class DeprecatedAcceleratorTester : public AcceleratorControllerTest {
  public:
@@ -2442,8 +2444,6 @@
   DISALLOW_COPY_AND_ASSIGN(DeprecatedAcceleratorTester);
 };
 
-}  // namespace
-
 TEST_F(DeprecatedAcceleratorTester, TestDeprecatedAcceleratorsBehavior) {
   for (size_t i = 0; i < kDeprecatedAcceleratorsLength; ++i) {
     const AcceleratorData& entry = kDeprecatedAccelerators[i];
@@ -2516,8 +2516,6 @@
       NEW_INCOGNITO_WINDOW, {}));
 }
 
-namespace {
-
 constexpr char kUserEmail[] = "user@magnifier";
 
 class MagnifiersAcceleratorsTester : public AcceleratorControllerTest {
@@ -2549,8 +2547,6 @@
   DISALLOW_COPY_AND_ASSIGN(MagnifiersAcceleratorsTester);
 };
 
-}  // namespace
-
 // TODO (afakhry): Remove this class after refactoring MagnificationManager.
 // Mocked chrome/browser/ash/accessibility/magnification_manager.cc
 class FakeMagnificationManager {
@@ -2755,8 +2751,6 @@
   }
 }
 
-namespace {
-
 struct MediaSessionAcceleratorTestConfig {
   // Runs the test with the media session service enabled.
   bool service_enabled;
@@ -2777,6 +2771,8 @@
 // MediaSessionAcceleratorTest tests media key handling with media session
 // service integration. The parameter is a struct that configures different
 // settings to run the test under.
+// Note this class can't be in the anonymous namespace because it is referenced
+// as a friend by ash/media/media_controller_impl.h.
 class MediaSessionAcceleratorTest
     : public AcceleratorControllerTest,
       public testing::WithParamInterface<MediaSessionAcceleratorTestConfig> {
@@ -3132,20 +3128,4 @@
   }
 }
 
-// Tests the IME mode change key.
-TEST_F(AcceleratorControllerTest, ChangeIMEMode_SwitchesInputMethod) {
-  AddTestImes();
-
-  ImeController* controller = Shell::Get()->ime_controller();
-
-  TestImeControllerClient client;
-  controller->SetClient(&client);
-
-  EXPECT_EQ(0, client.next_ime_count_);
-
-  ProcessInController(ui::Accelerator(ui::VKEY_MODECHANGE, ui::EF_NONE));
-
-  EXPECT_EQ(1, client.next_ime_count_);
-}
-
 }  // namespace ash
diff --git a/ash/content/shimless_rma/resources/BUILD.gn b/ash/content/shimless_rma/resources/BUILD.gn
index d391da3..1342460c 100644
--- a/ash/content/shimless_rma/resources/BUILD.gn
+++ b/ash/content/shimless_rma/resources/BUILD.gn
@@ -88,12 +88,14 @@
 
 js_library("onboarding_landing_page") {
   deps = [
+    ":base_page",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
   ]
 }
 
 js_library("onboarding_update_page") {
   deps = [
+    ":base_page",
     ":mojo_interface_provider",
     ":shimless_rma_types",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
diff --git a/ash/content/shimless_rma/resources/onboarding_update_page.js b/ash/content/shimless_rma/resources/onboarding_update_page.js
index 6673ea6..9401520 100644
--- a/ash/content/shimless_rma/resources/onboarding_update_page.js
+++ b/ash/content/shimless_rma/resources/onboarding_update_page.js
@@ -4,6 +4,7 @@
 
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import './shimless_rma_shared_css.js';
+import './base_page.js';
 
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
diff --git a/ash/content/shimless_rma/resources/shimless_rma.js b/ash/content/shimless_rma/resources/shimless_rma.js
index 0c5c56b5..97bbfb0 100644
--- a/ash/content/shimless_rma/resources/shimless_rma.js
+++ b/ash/content/shimless_rma/resources/shimless_rma.js
@@ -199,8 +199,18 @@
 
   /** @protected */
   onNextBtnClicked_() {
-    // TODO(joonbug): error handling based on state.error
-    this.fetchNextState_().then((state) => this.loadState_(state.nextState));
+    const page = this.shadowRoot.querySelector(this.currentPage_.componentIs);
+    assert(page);
+
+    // Acquire promise to check whether current page is ready for next page.
+    const prepPageAdvance =
+        page.onNextBtnClick || (() => Promise.resolve(true));
+    assert(typeof prepPageAdvance === 'function');
+
+    prepPageAdvance()
+        .then((ready) => ready ? this.fetchNextState_() : Promise.reject())
+        .then((state) => this.loadState_(state.nextState))
+        .catch((err) => void 0);
   }
 
   /** @protected */
diff --git a/ash/shelf/shelf_tooltip_bubble.cc b/ash/shelf/shelf_tooltip_bubble.cc
index 7c7c781..b16588a 100644
--- a/ash/shelf/shelf_tooltip_bubble.cc
+++ b/ash/shelf/shelf_tooltip_bubble.cc
@@ -4,6 +4,7 @@
 
 #include "ash/shelf/shelf_tooltip_bubble.h"
 
+#include "ash/public/cpp/ash_features.h"
 #include "ash/style/ash_color_provider.h"
 #include "ash/system/tray/tray_constants.h"
 #include "ash/wm/collision_detection/collision_detection_utils.h"
@@ -41,10 +42,17 @@
   views::Label* label = new views::Label(text);
   label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   const auto* color_provider = AshColorProvider::Get();
-  const SkColor tooltip_background = color_provider->GetInvertedBaseLayerColor(
-      AshColorProvider::BaseLayerType::kTransparent80);
-  const SkColor tooltip_text = color_provider->GetInvertedContentLayerColor(
-      AshColorProvider::ContentLayerType::kTextColorPrimary);
+  const bool is_dark_light_mode_enabled = features::IsDarkLightModeEnabled();
+  auto background_color_type = AshColorProvider::BaseLayerType::kTransparent80;
+  auto text_color_type = AshColorProvider::ContentLayerType::kTextColorPrimary;
+  const SkColor tooltip_background =
+      is_dark_light_mode_enabled
+          ? color_provider->GetInvertedBaseLayerColor(background_color_type)
+          : color_provider->GetBaseLayerColor(background_color_type);
+  const SkColor tooltip_text =
+      is_dark_light_mode_enabled
+          ? color_provider->GetInvertedContentLayerColor(text_color_type)
+          : color_provider->GetContentLayerColor(text_color_type);
 
   set_color(tooltip_background);
   label->SetEnabledColor(tooltip_text);
diff --git a/ash/system/holding_space/downloads_section.cc b/ash/system/holding_space/downloads_section.cc
index 6f2f957..f60deba 100644
--- a/ash/system/holding_space/downloads_section.cc
+++ b/ash/system/holding_space/downloads_section.cc
@@ -126,7 +126,7 @@
 
 // DownloadsSection ------------------------------------------------------------
 
-DownloadsSection::DownloadsSection(HoldingSpaceItemViewDelegate* delegate)
+DownloadsSection::DownloadsSection(HoldingSpaceViewDelegate* delegate)
     : HoldingSpaceItemViewsSection(delegate,
                                    /*supported_types=*/
                                    {HoldingSpaceItem::Type::kArcDownload,
diff --git a/ash/system/holding_space/downloads_section.h b/ash/system/holding_space/downloads_section.h
index ae80eb0..7571c6aa5 100644
--- a/ash/system/holding_space/downloads_section.h
+++ b/ash/system/holding_space/downloads_section.h
@@ -14,7 +14,7 @@
 // Section for downloads in the `RecentFilesBubble`.
 class DownloadsSection : public HoldingSpaceItemViewsSection {
  public:
-  explicit DownloadsSection(HoldingSpaceItemViewDelegate* delegate);
+  explicit DownloadsSection(HoldingSpaceViewDelegate* delegate);
   DownloadsSection(const DownloadsSection& other) = delete;
   DownloadsSection& operator=(const DownloadsSection& other) = delete;
   ~DownloadsSection() override;
diff --git a/ash/system/holding_space/holding_space_item_chip_view.cc b/ash/system/holding_space/holding_space_item_chip_view.cc
index 5e929e1..174c981 100644
--- a/ash/system/holding_space/holding_space_item_chip_view.cc
+++ b/ash/system/holding_space/holding_space_item_chip_view.cc
@@ -11,8 +11,8 @@
 #include "ash/public/cpp/rounded_image_view.h"
 #include "ash/style/ash_color_provider.h"
 #include "ash/system/holding_space/holding_space_item_view.h"
-#include "ash/system/holding_space/holding_space_item_view_delegate.h"
 #include "ash/system/holding_space/holding_space_util.h"
+#include "ash/system/holding_space/holding_space_view_delegate.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_owner.h"
@@ -63,7 +63,7 @@
 // HoldingSpaceItemChipView ----------------------------------------------------
 
 HoldingSpaceItemChipView::HoldingSpaceItemChipView(
-    HoldingSpaceItemViewDelegate* delegate,
+    HoldingSpaceViewDelegate* delegate,
     const HoldingSpaceItem* item)
     : HoldingSpaceItemView(delegate, item) {
   auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
@@ -157,9 +157,8 @@
 void HoldingSpaceItemChipView::OnSelectionUiChanged() {
   HoldingSpaceItemView::OnSelectionUiChanged();
 
-  const bool multiselect =
-      delegate()->selection_ui() ==
-      HoldingSpaceItemViewDelegate::SelectionUi::kMultiSelect;
+  const bool multiselect = delegate()->selection_ui() ==
+                           HoldingSpaceViewDelegate::SelectionUi::kMultiSelect;
 
   image_->SetVisible(!selected() || !multiselect);
   UpdateLabel();
@@ -203,9 +202,8 @@
 }
 
 void HoldingSpaceItemChipView::UpdateLabel() {
-  const bool multiselect =
-      delegate()->selection_ui() ==
-      HoldingSpaceItemViewDelegate::SelectionUi::kMultiSelect;
+  const bool multiselect = delegate()->selection_ui() ==
+                           HoldingSpaceViewDelegate::SelectionUi::kMultiSelect;
 
   label_->SetEnabledColor(
       selected() && multiselect
diff --git a/ash/system/holding_space/holding_space_item_chip_view.h b/ash/system/holding_space/holding_space_item_chip_view.h
index 3be5a88..38cda04 100644
--- a/ash/system/holding_space/holding_space_item_chip_view.h
+++ b/ash/system/holding_space/holding_space_item_chip_view.h
@@ -17,7 +17,7 @@
 namespace ash {
 
 class HoldingSpaceItem;
-class HoldingSpaceItemViewDelegate;
+class HoldingSpaceViewDelegate;
 class RoundedImageView;
 
 // A button with an image derived from a file's thumbnail and file's name as the
@@ -26,7 +26,7 @@
  public:
   METADATA_HEADER(HoldingSpaceItemChipView);
 
-  HoldingSpaceItemChipView(HoldingSpaceItemViewDelegate* delegate,
+  HoldingSpaceItemChipView(HoldingSpaceViewDelegate* delegate,
                            const HoldingSpaceItem* item);
   HoldingSpaceItemChipView(const HoldingSpaceItemChipView&) = delete;
   HoldingSpaceItemChipView& operator=(const HoldingSpaceItemChipView&) = delete;
diff --git a/ash/system/holding_space/holding_space_item_screen_capture_view.cc b/ash/system/holding_space/holding_space_item_screen_capture_view.cc
index fddac0c..2a02c7d 100644
--- a/ash/system/holding_space/holding_space_item_screen_capture_view.cc
+++ b/ash/system/holding_space/holding_space_item_screen_capture_view.cc
@@ -29,7 +29,7 @@
 constexpr gfx::Size kPlayIconSize(32, 32);
 
 HoldingSpaceItemScreenCaptureView::HoldingSpaceItemScreenCaptureView(
-    HoldingSpaceItemViewDelegate* delegate,
+    HoldingSpaceViewDelegate* delegate,
     const HoldingSpaceItem* item)
     : HoldingSpaceItemView(delegate, item) {
   SetPreferredSize(kHoldingSpaceScreenCaptureSize);
diff --git a/ash/system/holding_space/holding_space_item_screen_capture_view.h b/ash/system/holding_space/holding_space_item_screen_capture_view.h
index 1fb1680..ea987e8 100644
--- a/ash/system/holding_space/holding_space_item_screen_capture_view.h
+++ b/ash/system/holding_space/holding_space_item_screen_capture_view.h
@@ -17,7 +17,7 @@
 namespace ash {
 
 class HoldingSpaceItem;
-class HoldingSpaceItemViewDelegate;
+class HoldingSpaceViewDelegate;
 class RoundedImageView;
 
 class ASH_EXPORT HoldingSpaceItemScreenCaptureView
@@ -25,7 +25,7 @@
  public:
   METADATA_HEADER(HoldingSpaceItemScreenCaptureView);
 
-  HoldingSpaceItemScreenCaptureView(HoldingSpaceItemViewDelegate* delegate,
+  HoldingSpaceItemScreenCaptureView(HoldingSpaceViewDelegate* delegate,
                                     const HoldingSpaceItem* item);
   HoldingSpaceItemScreenCaptureView(const HoldingSpaceItemScreenCaptureView&) =
       delete;
diff --git a/ash/system/holding_space/holding_space_item_view.cc b/ash/system/holding_space/holding_space_item_view.cc
index 48bb458..fb873fd 100644
--- a/ash/system/holding_space/holding_space_item_view.cc
+++ b/ash/system/holding_space/holding_space_item_view.cc
@@ -11,8 +11,8 @@
 #include "ash/public/cpp/shelf_config.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/style/ash_color_provider.h"
-#include "ash/system/holding_space/holding_space_item_view_delegate.h"
 #include "ash/system/holding_space/holding_space_util.h"
+#include "ash/system/holding_space/holding_space_view_delegate.h"
 #include "base/bind.h"
 #include "ui/base/class_property.h"
 #include "ui/base/dragdrop/drag_drop_types.h"
@@ -84,9 +84,8 @@
 
 // HoldingSpaceItemView --------------------------------------------------------
 
-HoldingSpaceItemView::HoldingSpaceItemView(
-    HoldingSpaceItemViewDelegate* delegate,
-    const HoldingSpaceItem* item)
+HoldingSpaceItemView::HoldingSpaceItemView(HoldingSpaceViewDelegate* delegate,
+                                           const HoldingSpaceItem* item)
     : delegate_(delegate), item_(item), item_id_(item->id()) {
   model_observer_.Observe(HoldingSpaceController::Get()->model());
 
@@ -321,7 +320,7 @@
 void HoldingSpaceItemView::OnSelectionUiChanged() {
   const bool multiselect =
       delegate_ && delegate_->selection_ui() ==
-                       HoldingSpaceItemViewDelegate::SelectionUi::kMultiSelect;
+                       HoldingSpaceViewDelegate::SelectionUi::kMultiSelect;
 
   checkmark_->SetVisible(selected() && multiselect);
 }
diff --git a/ash/system/holding_space/holding_space_item_view.h b/ash/system/holding_space/holding_space_item_view.h
index 5c55d17..e90dec00 100644
--- a/ash/system/holding_space/holding_space_item_view.h
+++ b/ash/system/holding_space/holding_space_item_view.h
@@ -23,7 +23,7 @@
 namespace ash {
 
 class HoldingSpaceItem;
-class HoldingSpaceItemViewDelegate;
+class HoldingSpaceViewDelegate;
 
 // Base class for `HoldingSpaceItemChipView` and
 // `HoldingSpaceItemScreenCaptureView`. Note that `HoldingSpaceItemView` may
@@ -34,7 +34,7 @@
  public:
   METADATA_HEADER(HoldingSpaceItemView);
 
-  HoldingSpaceItemView(HoldingSpaceItemViewDelegate*, const HoldingSpaceItem*);
+  HoldingSpaceItemView(HoldingSpaceViewDelegate*, const HoldingSpaceItem*);
   HoldingSpaceItemView(const HoldingSpaceItemView&) = delete;
   HoldingSpaceItemView& operator=(const HoldingSpaceItemView&) = delete;
   ~HoldingSpaceItemView() override;
@@ -84,7 +84,7 @@
   virtual void OnPinVisibilityChanged(bool pin_visible) {}
   virtual void OnSelectionUiChanged();
 
-  HoldingSpaceItemViewDelegate* delegate() { return delegate_; }
+  HoldingSpaceViewDelegate* delegate() { return delegate_; }
   views::ImageView* checkmark() { return checkmark_; }
   views::ToggleImageButton* pin() { return pin_; }
 
@@ -97,7 +97,7 @@
   // NOTE: This view may outlive `delegate_` and/or `item_` during destruction
   // since the widget is closed asynchronously and the model is updated prior
   // to animation completion.
-  HoldingSpaceItemViewDelegate* delegate_;
+  HoldingSpaceViewDelegate* delegate_;
   const HoldingSpaceItem* const item_;
 
   // Cache the id of the associated holding space item so that it can be
diff --git a/ash/system/holding_space/holding_space_item_views_section.cc b/ash/system/holding_space/holding_space_item_views_section.cc
index f8834358..5a415b4 100644
--- a/ash/system/holding_space/holding_space_item_views_section.cc
+++ b/ash/system/holding_space/holding_space_item_views_section.cc
@@ -8,8 +8,8 @@
 #include "ash/public/cpp/holding_space/holding_space_controller.h"
 #include "ash/public/cpp/holding_space/holding_space_model.h"
 #include "ash/system/holding_space/holding_space_item_view.h"
-#include "ash/system/holding_space/holding_space_item_view_delegate.h"
 #include "ash/system/holding_space/holding_space_util.h"
+#include "ash/system/holding_space/holding_space_view_delegate.h"
 #include "base/auto_reset.h"
 #include "base/callback_helpers.h"
 #include "base/containers/contains.h"
@@ -120,7 +120,7 @@
 // HoldingSpaceItemViewsSection ------------------------------------------------
 
 HoldingSpaceItemViewsSection::HoldingSpaceItemViewsSection(
-    HoldingSpaceItemViewDelegate* delegate,
+    HoldingSpaceViewDelegate* delegate,
     std::set<HoldingSpaceItem::Type> supported_types,
     const absl::optional<size_t>& max_count)
     : delegate_(delegate),
@@ -469,7 +469,7 @@
   // All holding space item views are going to be removed after which views will
   // be re-added for those items which still exist. A `ScopedSelectionRestore`
   // will serve to persist the current selection during this modification.
-  HoldingSpaceItemViewDelegate::ScopedSelectionRestore scoped_selection_restore(
+  HoldingSpaceViewDelegate::ScopedSelectionRestore scoped_selection_restore(
       delegate_);
 
   // Disable propagation of `PreferredSizeChanged()` while performing batch
diff --git a/ash/system/holding_space/holding_space_item_views_section.h b/ash/system/holding_space/holding_space_item_views_section.h
index dc30f8cad..de9e70f 100644
--- a/ash/system/holding_space/holding_space_item_views_section.h
+++ b/ash/system/holding_space/holding_space_item_views_section.h
@@ -26,12 +26,12 @@
 namespace ash {
 
 class HoldingSpaceItemView;
-class HoldingSpaceItemViewDelegate;
+class HoldingSpaceViewDelegate;
 
 // A section of holding space item views in a `HoldingSpaceTrayChildBubble`.
 class HoldingSpaceItemViewsSection : public views::View {
  public:
-  HoldingSpaceItemViewsSection(HoldingSpaceItemViewDelegate* delegate,
+  HoldingSpaceItemViewsSection(HoldingSpaceViewDelegate* delegate,
                                std::set<HoldingSpaceItem::Type> supported_types,
                                const absl::optional<size_t>& max_count);
   HoldingSpaceItemViewsSection(const HoldingSpaceItemViewsSection& other) =
@@ -102,7 +102,7 @@
   // Invoked to destroy `placeholder_`.
   void DestroyPlaceholder();
 
-  HoldingSpaceItemViewDelegate* delegate() { return delegate_; }
+  HoldingSpaceViewDelegate* delegate() { return delegate_; }
 
  private:
   enum AnimationState : uint32_t {
@@ -132,7 +132,7 @@
   void OnAnimateInCompleted(const ui::CallbackLayerAnimationObserver&);
   void OnAnimateOutCompleted(const ui::CallbackLayerAnimationObserver&);
 
-  HoldingSpaceItemViewDelegate* const delegate_;
+  HoldingSpaceViewDelegate* const delegate_;
   const std::set<HoldingSpaceItem::Type> supported_types_;
   const absl::optional<size_t> max_count_;
 
diff --git a/ash/system/holding_space/holding_space_tray_bubble.cc b/ash/system/holding_space/holding_space_tray_bubble.cc
index 861039b..8cf374b9 100644
--- a/ash/system/holding_space/holding_space_tray_bubble.cc
+++ b/ash/system/holding_space/holding_space_tray_bubble.cc
@@ -68,7 +68,7 @@
 class HoldingSpaceTrayBubbleEventHandler : public ui::EventHandler {
  public:
   HoldingSpaceTrayBubbleEventHandler(HoldingSpaceTrayBubble* bubble,
-                                     HoldingSpaceItemViewDelegate* delegate)
+                                     HoldingSpaceViewDelegate* delegate)
       : bubble_(bubble), delegate_(delegate) {
     aura::Env::GetInstance()->AddPreTargetHandler(
         this, ui::EventTarget::Priority::kSystem);
@@ -101,7 +101,7 @@
   }
 
   HoldingSpaceTrayBubble* const bubble_;
-  HoldingSpaceItemViewDelegate* const delegate_;
+  HoldingSpaceViewDelegate* const delegate_;
 };
 
 // ChildBubbleContainerLayout --------------------------------------------------
diff --git a/ash/system/holding_space/holding_space_tray_bubble.h b/ash/system/holding_space/holding_space_tray_bubble.h
index 394d8c4..8a0cc09 100644
--- a/ash/system/holding_space/holding_space_tray_bubble.h
+++ b/ash/system/holding_space/holding_space_tray_bubble.h
@@ -12,7 +12,7 @@
 #include "ash/public/cpp/tablet_mode_observer.h"
 #include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_observer.h"
-#include "ash/system/holding_space/holding_space_item_view_delegate.h"
+#include "ash/system/holding_space/holding_space_view_delegate.h"
 #include "ash/system/screen_layout_observer.h"
 #include "ash/system/tray/tray_bubble_wrapper.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
@@ -66,9 +66,9 @@
   // The owner of this class.
   HoldingSpaceTray* const holding_space_tray_;
 
-  // The singleton delegate for `HoldingSpaceItemView`s that implements support
+  // The singleton delegate for holding space views that implements support
   // for context menu, drag-and-drop, and multiple selection.
-  HoldingSpaceItemViewDelegate delegate_{this};
+  HoldingSpaceViewDelegate delegate_{this};
 
   // Views owned by view hierarchy.
   ChildBubbleContainer* child_bubble_container_;
diff --git a/ash/system/holding_space/holding_space_tray_child_bubble.cc b/ash/system/holding_space/holding_space_tray_child_bubble.cc
index 0dbed19..13043356c 100644
--- a/ash/system/holding_space/holding_space_tray_child_bubble.cc
+++ b/ash/system/holding_space/holding_space_tray_child_bubble.cc
@@ -8,9 +8,9 @@
 
 #include "ash/public/cpp/holding_space/holding_space_constants.h"
 #include "ash/style/ash_color_provider.h"
-#include "ash/system/holding_space/holding_space_item_view_delegate.h"
 #include "ash/system/holding_space/holding_space_item_views_section.h"
 #include "ash/system/holding_space/holding_space_util.h"
+#include "ash/system/holding_space/holding_space_view_delegate.h"
 #include "ash/system/tray/tray_constants.h"
 #include "ui/compositor/callback_layer_animation_observer.h"
 #include "ui/compositor/layer.h"
@@ -112,7 +112,7 @@
 // HoldingSpaceTrayChildBubble -------------------------------------------------
 
 HoldingSpaceTrayChildBubble::HoldingSpaceTrayChildBubble(
-    HoldingSpaceItemViewDelegate* delegate)
+    HoldingSpaceViewDelegate* delegate)
     : delegate_(delegate) {
   controller_observer_.Observe(HoldingSpaceController::Get());
   if (HoldingSpaceController::Get()->model())
diff --git a/ash/system/holding_space/holding_space_tray_child_bubble.h b/ash/system/holding_space/holding_space_tray_child_bubble.h
index d7bd2529..5cec82b 100644
--- a/ash/system/holding_space/holding_space_tray_child_bubble.h
+++ b/ash/system/holding_space/holding_space_tray_child_bubble.h
@@ -22,15 +22,15 @@
 namespace ash {
 
 class HoldingSpaceItemView;
-class HoldingSpaceItemViewDelegate;
 class HoldingSpaceItemViewsSection;
+class HoldingSpaceViewDelegate;
 
 // Child bubble of the `HoldingSpaceTrayBubble`.
 class HoldingSpaceTrayChildBubble : public views::View,
                                     public HoldingSpaceControllerObserver,
                                     public HoldingSpaceModelObserver {
  public:
-  explicit HoldingSpaceTrayChildBubble(HoldingSpaceItemViewDelegate* delegate);
+  explicit HoldingSpaceTrayChildBubble(HoldingSpaceViewDelegate* delegate);
   HoldingSpaceTrayChildBubble(const HoldingSpaceTrayChildBubble& other) =
       delete;
   HoldingSpaceTrayChildBubble& operator=(
@@ -65,7 +65,7 @@
   virtual std::vector<std::unique_ptr<HoldingSpaceItemViewsSection>>
   CreateSections() = 0;
 
-  HoldingSpaceItemViewDelegate* delegate() { return delegate_; }
+  HoldingSpaceViewDelegate* delegate() { return delegate_; }
 
  private:
   // views::View:
@@ -91,7 +91,7 @@
   void OnAnimateInCompleted(bool aborted);
   void OnAnimateOutCompleted(bool aborted);
 
-  HoldingSpaceItemViewDelegate* const delegate_;
+  HoldingSpaceViewDelegate* const delegate_;
 
   // Views owned by view hierarchy.
   std::vector<HoldingSpaceItemViewsSection*> sections_;
diff --git a/ash/system/holding_space/holding_space_item_view_delegate.cc b/ash/system/holding_space/holding_space_view_delegate.cc
similarity index 89%
rename from ash/system/holding_space/holding_space_item_view_delegate.cc
rename to ash/system/holding_space/holding_space_view_delegate.cc
index a2354697..19f16999 100644
--- a/ash/system/holding_space/holding_space_item_view_delegate.cc
+++ b/ash/system/holding_space/holding_space_view_delegate.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/system/holding_space/holding_space_item_view_delegate.h"
+#include "ash/system/holding_space/holding_space_view_delegate.h"
 
 #include "ash/public/cpp/holding_space/holding_space_client.h"
 #include "ash/public/cpp/holding_space/holding_space_constants.h"
@@ -35,10 +35,10 @@
 
 namespace {
 
-// It is expected that all `HoldingSpaceItemView`s share the same delegate in
-// order to support multiple selections. We cache the singleton `instance` in
-// order to enforce this requirement.
-HoldingSpaceItemViewDelegate* instance = nullptr;
+// It is expected that all holding space views share the same delegate in order
+// to support multiple selections which requires a shared state. We cache the
+// singleton `instance` in order to enforce this requirement.
+HoldingSpaceViewDelegate* instance = nullptr;
 
 // Helpers ---------------------------------------------------------------------
 
@@ -88,10 +88,10 @@
 
 }  // namespace
 
-// HoldingSpaceItemViewDelegate::ScopedSelectionRestore ------------------------
+// HoldingSpaceViewDelegate::ScopedSelectionRestore ----------------------------
 
-HoldingSpaceItemViewDelegate::ScopedSelectionRestore::ScopedSelectionRestore(
-    HoldingSpaceItemViewDelegate* delegate)
+HoldingSpaceViewDelegate::ScopedSelectionRestore::ScopedSelectionRestore(
+    HoldingSpaceViewDelegate* delegate)
     : delegate_(delegate) {
   // Save selection.
   for (const HoldingSpaceItemView* view : delegate_->GetSelection())
@@ -106,8 +106,7 @@
     selected_range_end_item_id_ = delegate_->selected_range_end_->item_id();
 }
 
-HoldingSpaceItemViewDelegate::ScopedSelectionRestore::
-    ~ScopedSelectionRestore() {
+HoldingSpaceViewDelegate::ScopedSelectionRestore::~ScopedSelectionRestore() {
   // Restore selection.
   delegate_->SetSelection(selected_item_ids_);
 
@@ -137,9 +136,9 @@
   }
 }
 
-// HoldingSpaceItemViewDelegate ------------------------------------------------
+// HoldingSpaceViewDelegate ----------------------------------------------------
 
-HoldingSpaceItemViewDelegate::HoldingSpaceItemViewDelegate(
+HoldingSpaceViewDelegate::HoldingSpaceViewDelegate(
     HoldingSpaceTrayBubble* bubble)
     : bubble_(bubble) {
   DCHECK_EQ(nullptr, instance);
@@ -154,12 +153,12 @@
   tablet_mode_observer_.Observe(TabletMode::Get());
 }
 
-HoldingSpaceItemViewDelegate::~HoldingSpaceItemViewDelegate() {
+HoldingSpaceViewDelegate::~HoldingSpaceViewDelegate() {
   DCHECK_EQ(instance, this);
   instance = nullptr;
 }
 
-void HoldingSpaceItemViewDelegate::OnHoldingSpaceItemViewCreated(
+void HoldingSpaceViewDelegate::OnHoldingSpaceItemViewCreated(
     HoldingSpaceItemView* view) {
   if (view->selected()) {
     ++selection_size_;
@@ -167,7 +166,7 @@
   }
 }
 
-void HoldingSpaceItemViewDelegate::OnHoldingSpaceItemViewDestroying(
+void HoldingSpaceViewDelegate::OnHoldingSpaceItemViewDestroying(
     HoldingSpaceItemView* view) {
   // If either endpoint of the selected range is destroyed, clear the cache so
   // that the next range-based selection attempt will start from scratch.
@@ -182,7 +181,7 @@
   }
 }
 
-bool HoldingSpaceItemViewDelegate::OnHoldingSpaceItemViewAccessibleAction(
+bool HoldingSpaceViewDelegate::OnHoldingSpaceItemViewAccessibleAction(
     HoldingSpaceItemView* view,
     const ui::AXActionData& action_data) {
   // When performing the default accessible action (e.g. Search + Space), open
@@ -206,7 +205,7 @@
   return false;
 }
 
-bool HoldingSpaceItemViewDelegate::OnHoldingSpaceItemViewGestureEvent(
+bool HoldingSpaceViewDelegate::OnHoldingSpaceItemViewGestureEvent(
     HoldingSpaceItemView* view,
     const ui::GestureEvent& event) {
   // The user may alternate between using mouse and touch inputs. Treat gesture
@@ -254,7 +253,7 @@
   return true;
 }
 
-bool HoldingSpaceItemViewDelegate::OnHoldingSpaceItemViewKeyPressed(
+bool HoldingSpaceViewDelegate::OnHoldingSpaceItemViewKeyPressed(
     HoldingSpaceItemView* view,
     const ui::KeyEvent& event) {
   // The ENTER key should open all selected holding space items. If `view` isn't
@@ -268,7 +267,7 @@
   return false;
 }
 
-bool HoldingSpaceItemViewDelegate::OnHoldingSpaceItemViewMousePressed(
+bool HoldingSpaceViewDelegate::OnHoldingSpaceItemViewMousePressed(
     HoldingSpaceItemView* view,
     const ui::MouseEvent& event) {
   // Since we are starting a new mouse pressed/released sequence, we need to
@@ -329,7 +328,7 @@
   return true;
 }
 
-void HoldingSpaceItemViewDelegate::OnHoldingSpaceItemViewMouseReleased(
+void HoldingSpaceViewDelegate::OnHoldingSpaceItemViewMouseReleased(
     HoldingSpaceItemView* view,
     const ui::MouseEvent& event) {
   // We should always clear `ignore_mouse_released_` since that property should
@@ -369,13 +368,13 @@
   SetSelection(view);
 }
 
-void HoldingSpaceItemViewDelegate::OnHoldingSpaceItemViewSelectedChanged(
+void HoldingSpaceViewDelegate::OnHoldingSpaceItemViewSelectedChanged(
     HoldingSpaceItemView* view) {
   selection_size_ += view->selected() ? 1 : -1;
   UpdateSelectionUi();
 }
 
-bool HoldingSpaceItemViewDelegate::OnHoldingSpaceTrayBubbleKeyPressed(
+bool HoldingSpaceViewDelegate::OnHoldingSpaceTrayBubbleKeyPressed(
     const ui::KeyEvent& event) {
   // The ENTER key should open all selected holding space items.
   if (event.key_code() == ui::KeyboardCode::VKEY_RETURN) {
@@ -387,28 +386,28 @@
   return false;
 }
 
-void HoldingSpaceItemViewDelegate::OnHoldingSpaceTrayChildBubbleGestureEvent(
+void HoldingSpaceViewDelegate::OnHoldingSpaceTrayChildBubbleGestureEvent(
     const ui::GestureEvent& event) {
   if (event.type() == ui::ET_GESTURE_TAP)
     ClearSelection();
 }
 
-void HoldingSpaceItemViewDelegate::OnHoldingSpaceTrayChildBubbleMousePressed(
+void HoldingSpaceViewDelegate::OnHoldingSpaceTrayChildBubbleMousePressed(
     const ui::MouseEvent& event) {
   ClearSelection();
 }
 
 base::RepeatingClosureList::Subscription
-HoldingSpaceItemViewDelegate::AddSelectionUiChangedCallback(
+HoldingSpaceViewDelegate::AddSelectionUiChangedCallback(
     base::RepeatingClosureList::CallbackType callback) {
   return selection_ui_changed_callbacks_.Add(std::move(callback));
 }
 
-void HoldingSpaceItemViewDelegate::UpdateTrayVisibility() {
+void HoldingSpaceViewDelegate::UpdateTrayVisibility() {
   bubble_->tray()->UpdateVisibility();
 }
 
-void HoldingSpaceItemViewDelegate::ShowContextMenuForViewImpl(
+void HoldingSpaceViewDelegate::ShowContextMenuForViewImpl(
     views::View* source,
     const gfx::Point& point,
     ui::MenuSourceType source_type) {
@@ -441,7 +440,7 @@
       source_type);
 }
 
-bool HoldingSpaceItemViewDelegate::CanStartDragForView(
+bool HoldingSpaceViewDelegate::CanStartDragForView(
     views::View* sender,
     const gfx::Point& press_pt,
     const gfx::Point& current_pt) {
@@ -449,16 +448,15 @@
   return views::View::ExceededDragThreshold(delta);
 }
 
-int HoldingSpaceItemViewDelegate::GetDragOperationsForView(
+int HoldingSpaceViewDelegate::GetDragOperationsForView(
     views::View* sender,
     const gfx::Point& press_pt) {
   return ui::DragDropTypes::DRAG_COPY;
 }
 
-void HoldingSpaceItemViewDelegate::WriteDragDataForView(
-    views::View* sender,
-    const gfx::Point& press_pt,
-    ui::OSExchangeData* data) {
+void HoldingSpaceViewDelegate::WriteDragDataForView(views::View* sender,
+                                                    const gfx::Point& press_pt,
+                                                    ui::OSExchangeData* data) {
   std::vector<const HoldingSpaceItemView*> selection = GetSelection();
   DCHECK_GE(selection.size(), 1u);
 
@@ -480,8 +478,7 @@
   data->SetFilenames(filenames);
 }
 
-void HoldingSpaceItemViewDelegate::ExecuteCommand(int command_id,
-                                                  int event_flags) {
+void HoldingSpaceViewDelegate::ExecuteCommand(int command_id, int event_flags) {
   std::vector<const HoldingSpaceItemView*> selection = GetSelection();
   DCHECK_GE(selection.size(), 1u);
 
@@ -525,15 +522,15 @@
   }
 }
 
-void HoldingSpaceItemViewDelegate::OnTabletModeStarted() {
+void HoldingSpaceViewDelegate::OnTabletModeStarted() {
   UpdateSelectionUi();
 }
 
-void HoldingSpaceItemViewDelegate::OnTabletModeEnded() {
+void HoldingSpaceViewDelegate::OnTabletModeEnded() {
   UpdateSelectionUi();
 }
 
-ui::SimpleMenuModel* HoldingSpaceItemViewDelegate::BuildMenuModel() {
+ui::SimpleMenuModel* HoldingSpaceViewDelegate::BuildMenuModel() {
   context_menu_model_ = std::make_unique<ui::SimpleMenuModel>(this);
 
   std::vector<const HoldingSpaceItemView*> selection = GetSelection();
@@ -609,7 +606,7 @@
 }
 
 std::vector<const HoldingSpaceItemView*>
-HoldingSpaceItemViewDelegate::GetSelection() {
+HoldingSpaceViewDelegate::GetSelection() {
   std::vector<const HoldingSpaceItemView*> selection;
   for (const HoldingSpaceItemView* view : bubble_->GetHoldingSpaceItemViews()) {
     if (view->selected())
@@ -619,16 +616,15 @@
   return selection;
 }
 
-void HoldingSpaceItemViewDelegate::ClearSelection() {
+void HoldingSpaceViewDelegate::ClearSelection() {
   SetSelection(std::vector<std::string>());
 }
 
-void HoldingSpaceItemViewDelegate::SetSelection(
-    HoldingSpaceItemView* selection) {
+void HoldingSpaceViewDelegate::SetSelection(HoldingSpaceItemView* selection) {
   SetSelection({selection->item_id()});
 }
 
-void HoldingSpaceItemViewDelegate::SetSelection(
+void HoldingSpaceViewDelegate::SetSelection(
     const std::vector<std::string>& item_ids) {
   std::vector<HoldingSpaceItemView*> selection;
 
@@ -647,8 +643,8 @@
   }
 }
 
-void HoldingSpaceItemViewDelegate::SetSelectedRange(HoldingSpaceItemView* start,
-                                                    HoldingSpaceItemView* end) {
+void HoldingSpaceViewDelegate::SetSelectedRange(HoldingSpaceItemView* start,
+                                                HoldingSpaceItemView* end) {
   const std::vector<HoldingSpaceItemView*> views =
       bubble_->GetHoldingSpaceItemViews();
 
@@ -666,7 +662,7 @@
   }
 }
 
-void HoldingSpaceItemViewDelegate::UpdateSelectionUi() {
+void HoldingSpaceViewDelegate::UpdateSelectionUi() {
   const SelectionUi selection_ui =
       TabletMode::Get()->InTabletMode() || selection_size_ > 1u
           ? SelectionUi::kMultiSelect
diff --git a/ash/system/holding_space/holding_space_item_view_delegate.h b/ash/system/holding_space/holding_space_view_delegate.h
similarity index 88%
rename from ash/system/holding_space/holding_space_item_view_delegate.h
rename to ash/system/holding_space/holding_space_view_delegate.h
index 43b85cb..a7badb1 100644
--- a/ash/system/holding_space/holding_space_item_view_delegate.h
+++ b/ash/system/holding_space/holding_space_view_delegate.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 ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEW_DELEGATE_H_
-#define ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEW_DELEGATE_H_
+#ifndef ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_VIEW_DELEGATE_H_
+#define ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_VIEW_DELEGATE_H_
 
 #include <memory>
 #include <string>
@@ -35,12 +35,11 @@
 class HoldingSpaceItemView;
 class HoldingSpaceTrayBubble;
 
-// TODO(crbug.com/1208036): Rename to `HoldingSpaceViewDelegate`.
-// A delegate for `HoldingSpaceItemView`s which implements context menu,
-// drag-and-drop, and selection functionality. In order to support multiple
-// selections at a time, all `HoldingSpaceItemView`s must share the same
-// `HoldingSpaceItemViewDelegate` instance.
-class ASH_EXPORT HoldingSpaceItemViewDelegate
+// A delegate for holding space views which implements context menu,
+// drag-and-drop, and selection functionality. Only a single delegate instance
+// exists at a time and is shared by all existing holding space views in order
+// to support multiselection which requires a shared state.
+class ASH_EXPORT HoldingSpaceViewDelegate
     : public views::ContextMenuController,
       public views::DragController,
       public ui::SimpleMenuModel::Delegate,
@@ -50,23 +49,22 @@
   // creation and restores that selection on destruction.
   class ScopedSelectionRestore {
    public:
-    explicit ScopedSelectionRestore(HoldingSpaceItemViewDelegate* delegate);
+    explicit ScopedSelectionRestore(HoldingSpaceViewDelegate* delegate);
     ScopedSelectionRestore(const ScopedSelectionRestore&) = delete;
     ScopedSelectionRestore& operator=(const ScopedSelectionRestore&) = delete;
     ~ScopedSelectionRestore();
 
    private:
-    HoldingSpaceItemViewDelegate* const delegate_;
+    HoldingSpaceViewDelegate* const delegate_;
     std::vector<std::string> selected_item_ids_;
     absl::optional<std::string> selected_range_start_item_id_;
     absl::optional<std::string> selected_range_end_item_id_;
   };
 
-  explicit HoldingSpaceItemViewDelegate(HoldingSpaceTrayBubble* bubble);
-  HoldingSpaceItemViewDelegate(const HoldingSpaceItemViewDelegate&) = delete;
-  HoldingSpaceItemViewDelegate& operator=(const HoldingSpaceItemViewDelegate&) =
-      delete;
-  ~HoldingSpaceItemViewDelegate() override;
+  explicit HoldingSpaceViewDelegate(HoldingSpaceTrayBubble* bubble);
+  HoldingSpaceViewDelegate(const HoldingSpaceViewDelegate&) = delete;
+  HoldingSpaceViewDelegate& operator=(const HoldingSpaceViewDelegate&) = delete;
+  ~HoldingSpaceViewDelegate() override;
 
   // Invoked when `view` has been created.
   void OnHoldingSpaceItemViewCreated(HoldingSpaceItemView* view);
@@ -208,4 +206,4 @@
 
 }  // namespace ash
 
-#endif  // ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEW_DELEGATE_H_
+#endif  // ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_VIEW_DELEGATE_H_
diff --git a/ash/system/holding_space/pinned_files_bubble.cc b/ash/system/holding_space/pinned_files_bubble.cc
index 59c9ac8..25e486a 100644
--- a/ash/system/holding_space/pinned_files_bubble.cc
+++ b/ash/system/holding_space/pinned_files_bubble.cc
@@ -9,7 +9,7 @@
 
 namespace ash {
 
-PinnedFilesBubble::PinnedFilesBubble(HoldingSpaceItemViewDelegate* delegate)
+PinnedFilesBubble::PinnedFilesBubble(HoldingSpaceViewDelegate* delegate)
     : HoldingSpaceTrayChildBubble(delegate) {
   SetID(kHoldingSpacePinnedFilesBubbleId);
 }
diff --git a/ash/system/holding_space/pinned_files_bubble.h b/ash/system/holding_space/pinned_files_bubble.h
index 0ed3e8766..61609761 100644
--- a/ash/system/holding_space/pinned_files_bubble.h
+++ b/ash/system/holding_space/pinned_files_bubble.h
@@ -15,7 +15,7 @@
 // Child bubble of `HoldingSpaceTrayBubble` for pinned files.
 class PinnedFilesBubble : public HoldingSpaceTrayChildBubble {
  public:
-  explicit PinnedFilesBubble(HoldingSpaceItemViewDelegate* delegate);
+  explicit PinnedFilesBubble(HoldingSpaceViewDelegate* delegate);
   PinnedFilesBubble(const PinnedFilesBubble& other) = delete;
   PinnedFilesBubble& operator=(const PinnedFilesBubble& other) = delete;
   ~PinnedFilesBubble() override;
diff --git a/ash/system/holding_space/pinned_files_section.cc b/ash/system/holding_space/pinned_files_section.cc
index 44bfec6..c43f338 100644
--- a/ash/system/holding_space/pinned_files_section.cc
+++ b/ash/system/holding_space/pinned_files_section.cc
@@ -17,8 +17,8 @@
 #include "ash/style/ash_color_provider.h"
 #include "ash/system/holding_space/holding_space_item_chip_view.h"
 #include "ash/system/holding_space/holding_space_item_chips_container.h"
-#include "ash/system/holding_space/holding_space_item_view_delegate.h"
 #include "ash/system/holding_space/holding_space_util.h"
+#include "ash/system/holding_space/holding_space_view_delegate.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -124,7 +124,7 @@
 
 // PinnedFilesSection ----------------------------------------------------------
 
-PinnedFilesSection::PinnedFilesSection(HoldingSpaceItemViewDelegate* delegate)
+PinnedFilesSection::PinnedFilesSection(HoldingSpaceViewDelegate* delegate)
     : HoldingSpaceItemViewsSection(delegate,
                                    /*supported_types=*/
                                    {HoldingSpaceItem::Type::kPinnedFile},
diff --git a/ash/system/holding_space/pinned_files_section.h b/ash/system/holding_space/pinned_files_section.h
index 81745f0..72e8b00 100644
--- a/ash/system/holding_space/pinned_files_section.h
+++ b/ash/system/holding_space/pinned_files_section.h
@@ -16,7 +16,7 @@
 // Section for pinned files in the `PinnedFilesBubble`.
 class PinnedFilesSection : public HoldingSpaceItemViewsSection {
  public:
-  explicit PinnedFilesSection(HoldingSpaceItemViewDelegate* delegate);
+  explicit PinnedFilesSection(HoldingSpaceViewDelegate* delegate);
   PinnedFilesSection(const PinnedFilesSection& other) = delete;
   PinnedFilesSection& operator=(const PinnedFilesSection& other) = delete;
   ~PinnedFilesSection() override;
diff --git a/ash/system/holding_space/recent_files_bubble.cc b/ash/system/holding_space/recent_files_bubble.cc
index 9b2c78839..fe3258b 100644
--- a/ash/system/holding_space/recent_files_bubble.cc
+++ b/ash/system/holding_space/recent_files_bubble.cc
@@ -10,7 +10,7 @@
 
 namespace ash {
 
-RecentFilesBubble::RecentFilesBubble(HoldingSpaceItemViewDelegate* delegate)
+RecentFilesBubble::RecentFilesBubble(HoldingSpaceViewDelegate* delegate)
     : HoldingSpaceTrayChildBubble(delegate) {
   SetID(kHoldingSpaceRecentFilesBubbleId);
 }
diff --git a/ash/system/holding_space/recent_files_bubble.h b/ash/system/holding_space/recent_files_bubble.h
index 5496abf..f83b8bf0 100644
--- a/ash/system/holding_space/recent_files_bubble.h
+++ b/ash/system/holding_space/recent_files_bubble.h
@@ -15,7 +15,7 @@
 // Child bubble of `HoldingSpaceTrayBubble` for recent files.
 class RecentFilesBubble : public HoldingSpaceTrayChildBubble {
  public:
-  explicit RecentFilesBubble(HoldingSpaceItemViewDelegate* delegate);
+  explicit RecentFilesBubble(HoldingSpaceViewDelegate* delegate);
   RecentFilesBubble(const RecentFilesBubble& other) = delete;
   RecentFilesBubble& operator=(const RecentFilesBubble& other) = delete;
   ~RecentFilesBubble() override;
diff --git a/ash/system/holding_space/screen_captures_section.cc b/ash/system/holding_space/screen_captures_section.cc
index fa1c597..559e949 100644
--- a/ash/system/holding_space/screen_captures_section.cc
+++ b/ash/system/holding_space/screen_captures_section.cc
@@ -21,8 +21,7 @@
 // Appearance.
 constexpr int kChildSpacing = 8;
 
-ScreenCapturesSection::ScreenCapturesSection(
-    HoldingSpaceItemViewDelegate* delegate)
+ScreenCapturesSection::ScreenCapturesSection(HoldingSpaceViewDelegate* delegate)
     : HoldingSpaceItemViewsSection(delegate,
                                    /*supported_types=*/
                                    {HoldingSpaceItem::Type::kScreenshot,
diff --git a/ash/system/holding_space/screen_captures_section.h b/ash/system/holding_space/screen_captures_section.h
index f0c0485..44d9d1c 100644
--- a/ash/system/holding_space/screen_captures_section.h
+++ b/ash/system/holding_space/screen_captures_section.h
@@ -14,7 +14,7 @@
 // Section for screen captures in the `RecentFilesBubble`.
 class ScreenCapturesSection : public HoldingSpaceItemViewsSection {
  public:
-  explicit ScreenCapturesSection(HoldingSpaceItemViewDelegate* delegate);
+  explicit ScreenCapturesSection(HoldingSpaceViewDelegate* delegate);
   ScreenCapturesSection(const ScreenCapturesSection& other) = delete;
   ScreenCapturesSection& operator=(const ScreenCapturesSection& other) = delete;
   ~ScreenCapturesSection() override;
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 94e13a9d..548c633c 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -516,7 +516,6 @@
     "observer_list_types.h",
     "one_shot_event.cc",
     "one_shot_event.h",
-    "optional.h",
     "os_compat_nacl.cc",
     "os_compat_nacl.h",
     "parameter_pack.h",
@@ -3969,6 +3968,8 @@
       "android/java/src/org/chromium/base/library_loader/ModernLinker.java",
       "android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java",
       "android/java/src/org/chromium/base/library_loader/ProcessInitException.java",
+      "android/java/src/org/chromium/base/lifetime/DestroyChecker.java",
+      "android/java/src/org/chromium/base/lifetime/Destroyable.java",
       "android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java",
       "android/java/src/org/chromium/base/memory/MemoryPressureCallback.java",
       "android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java",
diff --git a/base/android/java/src/org/chromium/base/ThreadUtils.java b/base/android/java/src/org/chromium/base/ThreadUtils.java
index 3bdf56dd..88243f2 100644
--- a/base/android/java/src/org/chromium/base/ThreadUtils.java
+++ b/base/android/java/src/org/chromium/base/ThreadUtils.java
@@ -65,7 +65,6 @@
      */
     public static class ThreadChecker {
         private final long mThreadId = Process.myTid();
-        private boolean mDestroyed;
 
         /**
          * Asserts that the current thread is the same as the one the ThreadChecker was constructed
@@ -75,26 +74,6 @@
             assert sThreadAssertsDisabled
                     || mThreadId == Process.myTid() : "Must only be used on a single thread.";
         }
-
-        /**
-         * Asserts that the current thread is the same as the one the ThreadChecker was constructed
-         * on and that the ThreadChecker has not been marked as destroyed.
-         */
-        public void assertOnValidThreadAndState() {
-            assertOnValidThread();
-            if (mDestroyed) {
-                throw new IllegalStateException("Operation is not allowed after destroy().");
-            }
-        }
-
-        /**
-         * Marks the ThreadChecker as destroyed, leading to all future calls to
-         * {@link #assertOnValidThreadAndState} to throw an IllegalStateException.
-         */
-        public void destroy() {
-            assertOnValidThreadAndState();
-            mDestroyed = true;
-        }
     }
 
     public static void setWillOverrideUiThread(boolean willOverrideUiThread) {
diff --git a/base/android/java/src/org/chromium/base/UnownedUserDataHost.java b/base/android/java/src/org/chromium/base/UnownedUserDataHost.java
index 7a9e437..df74907 100644
--- a/base/android/java/src/org/chromium/base/UnownedUserDataHost.java
+++ b/base/android/java/src/org/chromium/base/UnownedUserDataHost.java
@@ -11,6 +11,8 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
+import org.chromium.base.lifetime.DestroyChecker;
+
 import java.lang.ref.WeakReference;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -147,6 +149,7 @@
     }
 
     private final ThreadUtils.ThreadChecker mThreadChecker = new ThreadUtils.ThreadChecker();
+    private final DestroyChecker mDestroyChecker = new DestroyChecker();
 
     /**
      * Handler to use to post {@link UnownedUserData#onDetachedFromHost(UnownedUserDataHost)}
@@ -180,7 +183,7 @@
      */
     /* package */<T extends UnownedUserData> void set(
             @NonNull UnownedUserDataKey<T> key, @NonNull T newValue) {
-        mThreadChecker.assertOnValidThreadAndState();
+        checkState();
 
         // If we already have data, we might want to detach that first.
         if (mUnownedUserDataMap.containsKey(key)) {
@@ -201,7 +204,7 @@
      */
     @Nullable
     /* package */<T extends UnownedUserData> T get(@NonNull UnownedUserDataKey<T> key) {
-        mThreadChecker.assertOnValidThreadAndState();
+        checkState();
 
         WeakReference<? extends UnownedUserData> valueWeakRef = mUnownedUserDataMap.get(key);
         if (valueWeakRef == null) return null;
@@ -221,7 +224,7 @@
      * @param <T> the type of {@link UnownedUserData}.
      */
     /* package */<T extends UnownedUserData> void remove(@NonNull UnownedUserDataKey<T> key) {
-        mThreadChecker.assertOnValidThreadAndState();
+        checkState();
 
         WeakReference<? extends UnownedUserData> valueWeakRef = mUnownedUserDataMap.remove(key);
         if (valueWeakRef == null) return;
@@ -248,10 +251,8 @@
     public void destroy() {
         mThreadChecker.assertOnValidThread();
 
-        if (isDestroyed()) {
-            // Protect against potential races.
-            return;
-        }
+        // Protect against potential races.
+        if (mDestroyChecker.isDestroyed()) return;
 
         // Create a shallow copy of all keys to ensure each held object can safely remove itself
         // from the map while iterating over their keys.
@@ -263,17 +264,22 @@
 
         // Need to wait until the end to destroy the ThreadChecker to ensure that the
         // detachFromHost(...) invocations above are allowed to invoke remove(...).
-        mThreadChecker.destroy();
+        mDestroyChecker.destroy();
     }
 
     @VisibleForTesting(otherwise = VisibleForTesting.NONE)
     /* package */ int getMapSize() {
-        mThreadChecker.assertOnValidThreadAndState();
+        checkState();
 
         return mUnownedUserDataMap.size();
     }
 
     /* package */ boolean isDestroyed() {
-        return mUnownedUserDataMap == null;
+        return mDestroyChecker.isDestroyed();
+    }
+
+    private void checkState() {
+        mThreadChecker.assertOnValidThread();
+        mDestroyChecker.checkNotDestroyed();
     }
 }
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java b/base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java
index 53e426a2..5c77f90 100644
--- a/base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java
@@ -17,6 +17,7 @@
 import org.chromium.base.ApplicationStatus.ActivityStateListener;
 import org.chromium.base.ThreadUtils.ThreadChecker;
 import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.base.lifetime.DestroyChecker;
 
 import java.lang.ref.WeakReference;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -40,6 +41,7 @@
     private final JankMetricMeasurement mMeasurement;
     private final AtomicBoolean mIsMetricReporterLooping = new AtomicBoolean(false);
     private final ThreadChecker mThreadChecker = new ThreadChecker();
+    private final DestroyChecker mDestroyChecker = new DestroyChecker();
 
     private final Runnable mMetricReporter = new Runnable() {
         @Override
@@ -70,7 +72,8 @@
     }
 
     void initialize() {
-        mThreadChecker.assertOnValidThreadAndState();
+        mThreadChecker.assertOnValidThread();
+        mDestroyChecker.checkNotDestroyed();
         Activity activity = mActivityReference.get();
         if (activity != null) {
             ApplicationStatus.registerStateListenerForActivity(this, activity);
@@ -83,7 +86,8 @@
     }
 
     void destroy() {
-        mThreadChecker.assertOnValidThreadAndState();
+        mThreadChecker.assertOnValidThread();
+        mDestroyChecker.destroy();
         ApplicationStatus.unregisterActivityStateListener(this);
         stopMetricRecording();
         stopReportingTimer();
@@ -91,10 +95,11 @@
         if (activity != null) {
             activity.getWindow().removeOnFrameMetricsAvailableListener(mFrameMetricsListener);
         }
-        mThreadChecker.destroy();
     }
 
     protected Handler getOrCreateHandler() {
+        // TODO(salg): Sort out whether thread assertion should be happening here as well.
+        mDestroyChecker.checkNotDestroyed();
         if (mHandler == null) {
             mHandlerThread = new HandlerThread("Jank-Tracker");
             mHandlerThread.start();
@@ -104,7 +109,6 @@
     }
 
     private void startReportingTimer() {
-        mThreadChecker.assertOnValidThreadAndState();
         // If mIsMetricReporterLooping was already true then there's no need to post another task.
         if (mIsMetricReporterLooping.getAndSet(true)) {
             return;
@@ -113,7 +117,6 @@
     }
 
     private void stopReportingTimer() {
-        mThreadChecker.assertOnValidThreadAndState();
         if (!mIsMetricReporterLooping.get()) {
             return;
         }
@@ -126,17 +129,17 @@
     }
 
     private void startMetricRecording() {
-        mThreadChecker.assertOnValidThreadAndState();
         mFrameMetricsListener.setIsListenerRecording(true);
     }
 
     private void stopMetricRecording() {
-        mThreadChecker.assertOnValidThreadAndState();
         mFrameMetricsListener.setIsListenerRecording(false);
     }
 
     @Override
     public void onActivityStateChange(Activity activity, @ActivityState int newState) {
+        mThreadChecker.assertOnValidThread();
+        mDestroyChecker.checkNotDestroyed();
         switch (newState) {
             case ActivityState.STARTED: // Intentional fallthrough.
             case ActivityState.RESUMED:
@@ -155,4 +158,4 @@
                 break;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/base/android/java/src/org/chromium/base/lifetime/DestroyChecker.java b/base/android/java/src/org/chromium/base/lifetime/DestroyChecker.java
new file mode 100644
index 0000000..fd096eb8
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/lifetime/DestroyChecker.java
@@ -0,0 +1,41 @@
+// Copyright 2021 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.base.lifetime;
+
+/**
+ * Utility class that help ensure destruction of objects happens only once.
+ *
+ * This class does not guarantee thread safety. When thread safety is desired, please use
+ * {@see org.chromium.base.ThreadUtils.ThreadChecker}.
+ *
+ * To use:
+ *   1. In constructor of an instance a DestroyChecker field should be initialized with a new
+ *      DestroyChecker.
+ *   2. All of the methods that need to ensure that the object is used safely, should call
+ *      {@link #checkNotDestroyed()} to make sure that DestroyChecker hasn't been destroyed.
+ *   3. When the guarded object is destroyed, it should be enough to call {@link #destroy()} on the
+ *      DestroyChecker. That operation is not idempotent, and it asserts the state of the checker.
+ *      It is therefore not necessary to call {@link #checkNotDestroyed()} in that case. It is also
+ *      not allowed to call {@link #destroy()} more than once.
+ */
+public class DestroyChecker implements Destroyable {
+    private boolean mIsDestroyed;
+
+    @Override
+    public void destroy() {
+        checkNotDestroyed();
+        mIsDestroyed = true;
+    }
+
+    /** Returns whether the checker is already destroyed. */
+    public boolean isDestroyed() {
+        return mIsDestroyed;
+    }
+
+    /** Checks whether the object is already destroyed and asserts if it is. */
+    public void checkNotDestroyed() {
+        assert !mIsDestroyed : "Object is already destroyed.";
+    }
+}
diff --git a/base/android/java/src/org/chromium/base/lifetime/Destroyable.java b/base/android/java/src/org/chromium/base/lifetime/Destroyable.java
new file mode 100644
index 0000000..8d19ce2
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/lifetime/Destroyable.java
@@ -0,0 +1,11 @@
+// Copyright 2021 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.base.lifetime;
+
+/** Interface for items that require a controlled clean up. */
+public interface Destroyable {
+    /** Cleans up resources held by the implementing object. */
+    void destroy();
+}
diff --git a/base/android/java/src/org/chromium/base/supplier/DestroyableObservableSupplier.java b/base/android/java/src/org/chromium/base/supplier/DestroyableObservableSupplier.java
index 2d1f05af..2f99c06 100644
--- a/base/android/java/src/org/chromium/base/supplier/DestroyableObservableSupplier.java
+++ b/base/android/java/src/org/chromium/base/supplier/DestroyableObservableSupplier.java
@@ -4,6 +4,8 @@
 
 package org.chromium.base.supplier;
 
+import org.chromium.base.lifetime.Destroyable;
+
 /**
  * An {@link ObservableSupplier} that may be destroyed by anyone with a reference to the object.
  * This is useful if the class that constructs the object implementing this interface is not
@@ -12,9 +14,4 @@
  *
  * @param <E> The type of the wrapped object.
  */
-public interface DestroyableObservableSupplier<E> extends ObservableSupplier<E> {
-    /**
-     * Destroy the supplier and the object it holds.
-     */
-    void destroy();
-}
+public interface DestroyableObservableSupplier<E> extends ObservableSupplier<E>, Destroyable {}
diff --git a/base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java b/base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java
index e2d2e134..4db5345 100644
--- a/base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java
+++ b/base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java
@@ -4,11 +4,14 @@
 
 package org.chromium.base.supplier;
 
+import androidx.annotation.CallSuper;
 import androidx.annotation.NonNull;
 
 import org.chromium.base.UnownedUserData;
 import org.chromium.base.UnownedUserDataHost;
 import org.chromium.base.UnownedUserDataKey;
+import org.chromium.base.lifetime.DestroyChecker;
+import org.chromium.base.lifetime.Destroyable;
 
 /**
  * UnownedUserDataSupplier handles the combined lifecycle management for {@link UnownedUserData}
@@ -42,10 +45,10 @@
  * @see UnownedUserDataKey for information about the type of key that is required.
  * @see UnownedUserData for the marker interface used for this type of data.
  */
-public abstract class UnownedUserDataSupplier<E> extends ObservableSupplierImpl<E>
-        implements DestroyableObservableSupplier<E>, UnownedUserData {
+public abstract class UnownedUserDataSupplier<E>
+        extends ObservableSupplierImpl<E> implements Destroyable, UnownedUserData {
     private final UnownedUserDataKey<UnownedUserDataSupplier<E>> mUudKey;
-    private boolean mIsDestroyed;
+    private final DestroyChecker mDestroyChecker = new DestroyChecker();
 
     /**
      * Constructs an UnownedUserDataSupplier.
@@ -54,7 +57,6 @@
     protected UnownedUserDataSupplier(
             @NonNull UnownedUserDataKey<? extends UnownedUserDataSupplier<E>> uudKey) {
         mUudKey = (UnownedUserDataKey<UnownedUserDataSupplier<E>>) uudKey;
-        mIsDestroyed = false;
     }
 
     /**
@@ -62,13 +64,14 @@
      * @param host The host to attach the supplier to.
      */
     public void attach(@NonNull UnownedUserDataHost host) {
+        mDestroyChecker.checkNotDestroyed();
         mUudKey.attachToHost(host, this);
     }
 
     @Override
+    @CallSuper
     public void destroy() {
-        assert !mIsDestroyed;
+        mDestroyChecker.destroy();
         mUudKey.detachFromAllHosts(this);
-        mIsDestroyed = true;
     }
-}
\ No newline at end of file
+}
diff --git a/base/android/junit/src/org/chromium/base/UnownedUserDataKeyTest.java b/base/android/junit/src/org/chromium/base/UnownedUserDataKeyTest.java
index 2044f73..0b8c67d 100644
--- a/base/android/junit/src/org/chromium/base/UnownedUserDataKeyTest.java
+++ b/base/android/junit/src/org/chromium/base/UnownedUserDataKeyTest.java
@@ -867,7 +867,7 @@
         mFoo.assertDetachedHostsMatch(mHost1);
         assertTrue(mHost1.isDestroyed());
 
-        assertThrows(IllegalStateException.class, () -> Foo.KEY.attachToHost(mHost1, mFoo));
+        assertThrows(AssertionError.class, () -> Foo.KEY.attachToHost(mHost1, mFoo));
 
         // The following operation gracefully returns null.
         assertNull(Foo.KEY.retrieveDataFromHost(mHost1));
@@ -905,12 +905,11 @@
         Foo.KEY.detachFromAllHosts(mFoo);
     }
 
-    private <E extends RuntimeException> void assertThrows(
-            Class<E> exceptionType, Runnable runnable) {
-        RuntimeException actualException = null;
+    private <E extends Throwable> void assertThrows(Class<E> exceptionType, Runnable runnable) {
+        Throwable actualException = null;
         try {
             runnable.run();
-        } catch (RuntimeException e) {
+        } catch (Throwable e) {
             actualException = e;
         }
         assertNotNull("Exception not thrown", actualException);
diff --git a/base/containers/span.h b/base/containers/span.h
index 1f88dee..6082f4f9 100644
--- a/base/containers/span.h
+++ b/base/containers/span.h
@@ -263,7 +263,27 @@
   template <typename It,
             typename = internal::EnableIfCompatibleContiguousIterator<It, T>>
   constexpr span(It first, size_t count) noexcept
-      : ExtentStorage(count), data_(base::to_address(first)) {
+      : ExtentStorage(count),
+        // The use of to_address() here is to handle the case where the iterator
+        // `first` is pointing to the container's `end()`. In that case we can
+        // not use the address returned from the iterator, or dereference it
+        // through the iterator's `operator*`, but we can store it. We must assume
+        // in this case that `count` is 0, since the iterator does not point to
+        // valid data. Future hardening of iterators may disallow pulling the
+        // address from `end()`, as demonstrated by asserts() in libstdc++:
+        // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93960.
+        //
+        // The span API dictates that the `data()` is accessible when size is 0,
+        // since the pointer may be valid, so we cannot prevent storing and
+        // giving out an invalid pointer here without breaking API compatibility
+        // and our unit tests. Thus protecting against this can likely only be
+        // successful from inside iterators themselves, where the context about
+        // the pointer is known.
+        //
+        // We can not protect here generally against an invalid iterator/count
+        // being passed in, since we have no context to determine if the
+        // iterator or count are valid.
+        data_(base::to_address(first)) {
     CHECK(Extent == dynamic_extent || Extent == count);
   }
 
diff --git a/base/optional.h b/base/optional.h
deleted file mode 100644
index bdbbf9c2..0000000
--- a/base/optional.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_OPTIONAL_H_
-#define BASE_OPTIONAL_H_
-
-#include "third_party/abseil-cpp/absl/types/optional.h"
-
-namespace base {
-
-// These aliases are deprecated. Use abseil directly instead.
-
-template <typename T>
-using Optional [[deprecated]] = absl::optional<T>;
-
-using absl::make_optional;
-using absl::nullopt;
-using absl::nullopt_t;
-
-}  // namespace base
-
-#endif  // BASE_OPTIONAL_H_
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 8a99fbf1..ae989e2 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-4.20210517.5.1
+4.20210521.2.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 8a99fbf1..ae989e2 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-4.20210517.5.1
+4.20210521.2.1
diff --git a/build/fuchsia/qemu_target.py b/build/fuchsia/qemu_target.py
index 236c41d..e17a73d 100644
--- a/build/fuchsia/qemu_target.py
+++ b/build/fuchsia/qemu_target.py
@@ -174,6 +174,15 @@
     # Don't 'reboot' the emulator if the kernel crashes
     kernel_args.append('kernel.halt-on-panic=true')
 
+    # Prevent Zircon CPU lockup watchdogs from crashing the system
+    # due to scheduling starvation on heavily loaded VM hosts.
+    # TODO(crbug.com/1211461): Consider removing these lines once the
+    # issue is root caused and resolved.
+    kernel_args.append(
+        'kernel.lockup-detector.critical-section-fatal-threshold-ms=0')
+    kernel_args.append(
+        'kernel.lockup-detector.heartbeat-age-fatal-threshold-ms=0')
+
     emu_command.extend(['-append', ' '.join(kernel_args)])
 
     return emu_command
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h
index aafee12..3bec7598 100644
--- a/cc/paint/paint_op_buffer.h
+++ b/cc/paint/paint_op_buffer.h
@@ -28,6 +28,7 @@
 #include "cc/paint/paint_flags.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkPath.h"
 #include "third_party/skia/include/core/SkRect.h"
 #include "third_party/skia/include/core/SkScalar.h"
 #include "ui/gfx/geometry/rect.h"
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index ec09d08..661a62a 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -175,9 +175,11 @@
         ":chrome_dll",
         ":chrome_exe_version",
         ":copy_first_run",
+        ":packed_resources_integrity",
         ":visual_elements_resources",
         "//base",
         "//build:branding_buildflags",
+        "//chrome/app:chrome_exe_main_exports",
         "//chrome/app/version_assembly:chrome_exe_manifest",
         "//chrome/browser:active_use_util",
         "//chrome/browser:chrome_process_finder",
@@ -212,6 +214,8 @@
         "//chrome/notification_helper",
       ]
 
+      defines += [ "CHROME_EXE_MAIN" ]
+
       if (win_console_app) {
         defines += [ "WIN_CONSOLE_APP" ]
       } else {
@@ -1549,14 +1553,12 @@
       public_deps = [ ":preinstalled_apps" ]
     }
 
-    if (enable_pak_file_integrity_checks) {
-      files_to_hash = [
-        "resources.pak",
-        "chrome_100_percent.pak",
-      ]
-      if (enable_hidpi) {
-        files_to_hash += [ "chrome_200_percent.pak" ]
-      }
+    files_to_hash = [
+      "resources.pak",
+      "chrome_100_percent.pak",
+    ]
+    if (enable_hidpi) {
+      files_to_hash += [ "chrome_200_percent.pak" ]
     }
   }
 }
diff --git a/chrome/android/DEPS b/chrome/android/DEPS
index 8123fbd5..79b2c53 100644
--- a/chrome/android/DEPS
+++ b/chrome/android/DEPS
@@ -86,12 +86,6 @@
 
   # Exceptions to the Chrome*Activity dependency restriction. These will all eventually be removed
   # new code should rely on acceptable dependency aquisition patterns.
-  "AssistantCoordinator\.java": [
-    "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
-  ],
-  "AssistantRootViewContainer\.java": [
-    "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
-  ],
   "AutofillAssistantUiController\.java": [
     "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
   ],
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java
index 11cb8c6..067809f 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java
@@ -14,6 +14,7 @@
 import android.widget.LinearLayout;
 import android.widget.ScrollView;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import org.chromium.base.Callback;
@@ -33,6 +34,7 @@
 import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayCoordinator;
 import org.chromium.chrome.browser.autofill_assistant.user_data.AssistantCollectUserDataCoordinator;
 import org.chromium.chrome.browser.autofill_assistant.user_data.AssistantCollectUserDataModel;
+import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.image_fetcher.ImageFetcherConfig;
 import org.chromium.chrome.browser.image_fetcher.ImageFetcherFactory;
 import org.chromium.chrome.browser.ui.TabObscuringHandler;
@@ -104,7 +106,8 @@
     AssistantBottomBarCoordinator(Activity activity, AssistantModel model,
             AssistantOverlayCoordinator overlayCoordinator, BottomSheetController controller,
             ApplicationViewportInsetSupplier applicationViewportInsetSupplier,
-            TabObscuringHandler tabObscuringHandler) {
+            TabObscuringHandler tabObscuringHandler,
+            @NonNull BrowserControlsStateProvider browserControlsStateProvider) {
         mModel = model;
         mOverlayCoordinator = overlayCoordinator;
         mBottomSheetController = controller;
@@ -125,6 +128,7 @@
         mRootViewContainer =
                 (AssistantRootViewContainer) LayoutUtils.createInflater(activity).inflate(
                         R.layout.autofill_assistant_bottom_sheet_content, /* root= */ null);
+        mRootViewContainer.initialize(browserControlsStateProvider);
         mScrollableContent = mRootViewContainer.findViewById(R.id.scrollable_content);
         ViewGroup scrollableContentContainer =
                 mScrollableContent.findViewById(R.id.scrollable_content_container);
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java
index 7baf3e65..d8e53ec 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java
@@ -4,16 +4,24 @@
 
 package org.chromium.chrome.browser.autofill_assistant;
 
+import android.app.Activity;
+
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
-import org.chromium.chrome.browser.app.ChromeActivity;
+import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayCoordinator;
+import org.chromium.chrome.browser.compositor.CompositorViewHolder;
 import org.chromium.chrome.browser.feedback.HelpAndFeedbackLauncherImpl;
 import org.chromium.chrome.browser.feedback.ScreenshotMode;
+import org.chromium.chrome.browser.fullscreen.BrowserControlsManager;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.ui.TabObscuringHandler;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.SheetState;
+import org.chromium.ui.base.ActivityKeyboardVisibilityDelegate;
+import org.chromium.ui.base.ApplicationViewportInsetSupplier;
 
 /**
  * The main coordinator for the Autofill Assistant, responsible for instantiating all other
@@ -23,37 +31,41 @@
     public static final String FEEDBACK_CATEGORY_TAG =
             "com.android.chrome.USER_INITIATED_FEEDBACK_REPORT_AUTOFILL_ASSISTANT";
 
-    private final ChromeActivity mActivity;
+    private final Activity mActivity;
 
     private final AssistantModel mModel;
     private AssistantBottomBarCoordinator mBottomBarCoordinator;
     private final AssistantKeyboardCoordinator mKeyboardCoordinator;
     private final AssistantOverlayCoordinator mOverlayCoordinator;
+    private final Supplier<Tab> mCurrentTabSupplier;
 
-    AssistantCoordinator(ChromeActivity activity, BottomSheetController controller,
+    AssistantCoordinator(Activity activity, BottomSheetController controller,
             TabObscuringHandler tabObscuringHandler,
             @Nullable AssistantOverlayCoordinator overlayCoordinator,
-            AssistantKeyboardCoordinator.Delegate keyboardCoordinatorDelegate) {
+            AssistantKeyboardCoordinator.Delegate keyboardCoordinatorDelegate,
+            @NonNull ActivityKeyboardVisibilityDelegate keyboardDelegate,
+            @NonNull CompositorViewHolder compositorViewHolder,
+            @NonNull Supplier<Tab> currentTabSupplier,
+            @NonNull BrowserControlsManager browserControlsManager,
+            @NonNull ApplicationViewportInsetSupplier applicationBottomInsetProvider) {
         mActivity = activity;
+        mCurrentTabSupplier = currentTabSupplier;
 
         if (overlayCoordinator != null) {
             mModel = new AssistantModel(overlayCoordinator.getModel());
             mOverlayCoordinator = overlayCoordinator;
         } else {
             mModel = new AssistantModel();
-            mOverlayCoordinator = new AssistantOverlayCoordinator(activity,
-                    activity.getBrowserControlsManager(), activity.getCompositorViewHolder(),
-                    controller.getScrimCoordinator(), mModel.getOverlayModel());
+            mOverlayCoordinator = new AssistantOverlayCoordinator(activity, browserControlsManager,
+                    compositorViewHolder, controller.getScrimCoordinator(),
+                    mModel.getOverlayModel());
         }
 
-        mBottomBarCoordinator =
-                new AssistantBottomBarCoordinator(activity, mModel, mOverlayCoordinator, controller,
-                        activity.getWindowAndroid().getApplicationBottomInsetProvider(),
-                        tabObscuringHandler);
-        mKeyboardCoordinator = new AssistantKeyboardCoordinator(activity,
-                activity.getWindowAndroid().getKeyboardDelegate(),
-                activity.getCompositorViewHolder(), mModel, keyboardCoordinatorDelegate,
-                controller);
+        mBottomBarCoordinator = new AssistantBottomBarCoordinator(activity, mModel,
+                mOverlayCoordinator, controller, applicationBottomInsetProvider,
+                tabObscuringHandler, browserControlsManager);
+        mKeyboardCoordinator = new AssistantKeyboardCoordinator(activity, keyboardDelegate,
+                compositorViewHolder, mModel, keyboardCoordinatorDelegate, controller);
     }
 
     /** Detaches and destroys the view. */
@@ -86,12 +98,12 @@
      * Show the Chrome feedback form.
      */
     public void showFeedback(String debugContext, @ScreenshotMode int screenshotMode) {
-        Profile profile =
-                Profile.fromWebContents(mActivity.getActivityTabProvider().get().getWebContents());
+        Tab currentTab = mCurrentTabSupplier.get();
+        if (currentTab == null) return;
+        Profile profile = Profile.fromWebContents(currentTab.getWebContents());
 
         HelpAndFeedbackLauncherImpl.getInstance().showFeedback(mActivity, profile,
-                mActivity.getActivityTab().getUrlString(), FEEDBACK_CATEGORY_TAG, screenshotMode,
-                debugContext);
+                currentTab.getUrlString(), FEEDBACK_CATEGORY_TAG, screenshotMode, debugContext);
     }
 
     public void show() {
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantRootViewContainer.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantRootViewContainer.java
index b54fcb8..08b8f69 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantRootViewContainer.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantRootViewContainer.java
@@ -10,10 +10,10 @@
 import android.util.AttributeSet;
 import android.widget.LinearLayout;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import org.chromium.base.ContextUtils;
-import org.chromium.chrome.browser.app.ChromeActivity;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.util.ChromeAccessibilityUtil;
 
@@ -23,18 +23,20 @@
  */
 public class AssistantRootViewContainer
         extends LinearLayout implements BrowserControlsStateProvider.Observer {
-    private final ChromeActivity mActivity;
-    private final BrowserControlsStateProvider mBrowserControlsStateProvider;
+    private final Activity mActivity;
+    private BrowserControlsStateProvider mBrowserControlsStateProvider;
     private Rect mVisibleViewportRect = new Rect();
     private float mTalkbackSheetSizeFraction;
     private boolean mTalkbackResizingDisabled;
 
     public AssistantRootViewContainer(Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
-        Activity activity = ContextUtils.activityFromContext(context);
-        assert activity instanceof ChromeActivity;
-        mActivity = (ChromeActivity) activity;
-        mBrowserControlsStateProvider = mActivity.getBrowserControlsManager();
+        mActivity = ContextUtils.activityFromContext(context);
+    }
+
+    /** Initializes the object with the given {@link BrowserControlsStateProvider}. */
+    public void initialize(@NonNull BrowserControlsStateProvider browserControlsStateProvider) {
+        mBrowserControlsStateProvider = browserControlsStateProvider;
         mBrowserControlsStateProvider.addObserver(this);
     }
 
@@ -59,16 +61,20 @@
     }
 
     void destroy() {
-        mBrowserControlsStateProvider.removeObserver(this);
+        if (mBrowserControlsStateProvider != null) {
+            mBrowserControlsStateProvider.removeObserver(this);
+        }
     }
 
     @Override
     public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         mActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(mVisibleViewportRect);
-        int availableHeight = mVisibleViewportRect.height()
-                - mBrowserControlsStateProvider.getContentOffset()
-                - mBrowserControlsStateProvider.getBottomControlsHeight()
-                - mBrowserControlsStateProvider.getBottomControlOffset();
+        int availableHeight = mVisibleViewportRect.height();
+        int browserControlsOffset = mBrowserControlsStateProvider == null
+                ? 0
+                : -mBrowserControlsStateProvider.getContentOffset()
+                        - mBrowserControlsStateProvider.getBottomControlsHeight()
+                        - mBrowserControlsStateProvider.getBottomControlOffset();
 
         int targetHeight;
         int mode;
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
index b2300b7..dee9b82 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
@@ -134,7 +134,11 @@
         mNativeUiController = nativeUiController;
         mActivity = activity;
         mCoordinator = new AssistantCoordinator(activity, controller, tabObscuringHandler,
-                overlayCoordinator, this::safeNativeOnKeyboardVisibilityChanged);
+                overlayCoordinator, this::safeNativeOnKeyboardVisibilityChanged,
+                activity.getWindowAndroid().getKeyboardDelegate(),
+                activity.getCompositorViewHolder(), activity.getActivityTabProvider(),
+                activity.getBrowserControlsManager(),
+                activity.getWindowAndroid().getApplicationBottomInsetProvider());
         mActivityTabObserver =
                 new ActivityTabProvider.ActivityTabTabObserver(
                         activity.getActivityTabProvider(), /* shouldTrigger = */ true) {
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java
index 1c2f676..23491cc 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java
@@ -103,27 +103,31 @@
         return AutofillAssistantUiTestUtil.getBottomSheetController(getActivity());
     }
 
+    private AssistantCoordinator createAndShowAssistantCoordinator() {
+        return TestThreadUtils.runOnUiThreadBlockingNoException(() -> {
+            AssistantCoordinator coordinator = new AssistantCoordinator(getActivity(),
+                    initializeBottomSheet(), getActivity().getTabObscuringHandler(),
+                    /* overlayCoordinator= */ null,
+                    /* keyboardCoordinatorDelegate= */ null,
+                    getActivity().getWindowAndroid().getKeyboardDelegate(),
+                    getActivity().getCompositorViewHolder(), getActivity().getActivityTabProvider(),
+                    getActivity().getBrowserControlsManager(),
+                    getActivity().getWindowAndroid().getApplicationBottomInsetProvider());
+            coordinator.show();
+            return coordinator;
+        });
+    }
 
     // TODO(crbug.com/806868): Add more UI details test and check, like payment request UI,
     // highlight chips and so on.
     @Test
     @MediumTest
-    public void testStartAndAccept() throws Exception {
+    public void testStartAndAccept() {
         InOrder inOrder = inOrder(mRunnableMock);
-
         mCustomTabActivityTestRule.startCustomTabActivityWithIntent(
                 CustomTabsTestUtils.createMinimalCustomTabIntent(
                         InstrumentationRegistry.getTargetContext(), mTestPage));
-        BottomSheetController bottomSheetController =
-                TestThreadUtils.runOnUiThreadBlocking(this::initializeBottomSheet);
-        AssistantCoordinator assistantCoordinator = TestThreadUtils.runOnUiThreadBlocking(() -> {
-            AssistantCoordinator coordinator = new AssistantCoordinator(getActivity(),
-                    bottomSheetController, getActivity().getTabObscuringHandler(),
-                    /* overlayCoordinator= */ null,
-                    /* keyboardCoordinatorDelegate= */ null);
-            coordinator.show();
-            return coordinator;
-        });
+        AssistantCoordinator assistantCoordinator = createAndShowAssistantCoordinator();
 
         // Bottom sheet is shown in the BottomSheet when creating the AssistantCoordinator.
         View contentView = AutofillAssistantUiTestUtil.getBottomSheetController(getActivity())
@@ -245,22 +249,13 @@
 
     @Test
     @MediumTest
-    public void testTooltipBubble() throws Exception {
+    public void testTooltipBubble() {
         InOrder inOrder = inOrder(mRunnableMock);
 
         mCustomTabActivityTestRule.startCustomTabActivityWithIntent(
                 CustomTabsTestUtils.createMinimalCustomTabIntent(
                         InstrumentationRegistry.getTargetContext(), mTestPage));
-        BottomSheetController bottomSheetController =
-                TestThreadUtils.runOnUiThreadBlocking(this::initializeBottomSheet);
-        AssistantCoordinator assistantCoordinator = TestThreadUtils.runOnUiThreadBlocking(() -> {
-            AssistantCoordinator coordinator = new AssistantCoordinator(getActivity(),
-                    bottomSheetController, getActivity().getTabObscuringHandler(),
-                    /* overlayCoordinator= */ null,
-                    /* keyboardCoordinatorDelegate= */ null);
-            coordinator.show();
-            return coordinator;
-        });
+        AssistantCoordinator assistantCoordinator = createAndShowAssistantCoordinator();
 
         // Bottom sheet is shown in the BottomSheet when creating the AssistantCoordinator.
         View contentView = AutofillAssistantUiTestUtil.getBottomSheetController(getActivity())
diff --git a/chrome/android/features/cablev2_authenticator/BUILD.gn b/chrome/android/features/cablev2_authenticator/BUILD.gn
index 1ed3714..4054801b 100644
--- a/chrome/android/features/cablev2_authenticator/BUILD.gn
+++ b/chrome/android/features/cablev2_authenticator/BUILD.gn
@@ -62,15 +62,19 @@
     "java/res/anim/circle_loader_ellipse_path_3_animation.xml",
     "java/res/anim/circle_loader_ellipse_path_4_animation.xml",
     "java/res/anim/circle_loader_ellipse_path_5_animation.xml",
+    "java/res/drawable-night/ble.xml",
     "java/res/drawable-night/error_icon.xml",
+    "java/res/drawable/ble.xml",
     "java/res/drawable/circle_loader.xml",
     "java/res/drawable/circle_loader_animation.xml",
     "java/res/drawable/error_icon.xml",
     "java/res/drawable/header.xml",
     "java/res/drawable/ic_lock_googblue_48dp.xml",
     "java/res/drawable/usb_conn_disconnect.xml",
+    "java/res/layout-sw600dp/cablev2_ble_enable.xml",
     "java/res/layout-sw600dp/cablev2_error.xml",
     "java/res/layout-sw600dp/cablev2_serverlink.xml",
+    "java/res/layout/cablev2_ble_enable.xml",
     "java/res/layout/cablev2_error.xml",
     "java/res/layout/cablev2_qr_dialog.xml",
     "java/res/layout/cablev2_qr_scan.xml",
diff --git a/chrome/android/features/cablev2_authenticator/java/res/drawable-night/ble.xml b/chrome/android/features/cablev2_authenticator/java/res/drawable-night/ble.xml
new file mode 100644
index 0000000..6721dd9
--- /dev/null
+++ b/chrome/android/features/cablev2_authenticator/java/res/drawable-night/ble.xml
@@ -0,0 +1,24 @@
+<vector a:height='200dp' a:viewportHeight='110'
+    a:viewportWidth='90' a:width='163.63dp' xmlns:a='http://schemas.android.com/apk/res/android'>
+    <path a:fillColor='#414447' a:fillType='evenOdd'
+        a:pathData='M11.986,6C8.685,6 6,8.616 6,11.832L6,98.168C6,101.384 8.685,104 11.986,104L49.015,104C52.316,104 55,101.384 55,98.168L55,11.832C55,8.616 52.316,6 49.015,6L11.986,6Z'
+        a:strokeColor='#5F6368' a:strokeWidth='1'/>
+    <path a:fillColor='#5F6368' a:fillType='nonZero'
+        a:pathData='M48.792,1.5C54.606,1.5 59.342,6.036 59.496,11.693L59.5,11.977L59.5,84C59.5,84.276 59.276,84.5 59,84.5C58.755,84.5 58.55,84.323 58.508,84.09L58.5,84L58.5,11.977C58.5,6.836 54.304,2.647 49.068,2.504L48.792,2.5L45,2.5C44.724,2.5 44.5,2.276 44.5,2C44.5,1.755 44.677,1.55 44.91,1.508L45,1.5L48.792,1.5Z'
+        a:strokeColor='#00000000' a:strokeWidth='1'/>
+    <path a:fillColor='#F7BB2A' a:fillType='nonZero'
+        a:pathData='M44.999,33.5C44.999,21.626 54.626,12 66.499,12C78.374,12 88,21.626 88,33.5C88,45.374 78.374,55 66.499,55C54.626,55 44.999,45.374 44.999,33.5'
+        a:strokeColor='#00000000' a:strokeWidth='1'/>
+    <path a:fillColor='#E8AF25' a:fillType='nonZero'
+        a:pathData='M45,33.5C45,25.856 48.989,19.144 54.999,15.331L54.999,51.669C48.989,47.856 45,41.144 45,33.5Z'
+        a:strokeColor='#00000000' a:strokeWidth='1'/>
+    <path a:fillColor='#FFFFFF' a:fillType='nonZero'
+        a:pathData='M71.324,37.607L66.686,42.245L65.873,42.245L65.873,36.08L62.145,39.808L61,38.663L65.54,34.122L61,29.582L62.145,28.437L65.873,32.165L65.873,26L66.686,26L71.324,30.638L67.831,34.122L71.324,37.607ZM67.498,39.134L69.025,37.607L67.498,36.08L67.498,39.134ZM69.025,30.638L67.498,29.111L67.498,32.165L69.025,30.638L69.025,30.638Z'
+        a:strokeColor='#F7BB2A' a:strokeWidth='0.6'/>
+    <path a:fillColor='#8AB4F8' a:fillType='nonZero'
+        a:pathData='M59,91.5C59.245,91.5 59.45,91.677 59.492,91.91L59.5,92L59.5,98.006C59.5,103.708 54.888,108.346 49.145,108.496L48.857,108.5L41,108.5C40.724,108.5 40.5,108.276 40.5,108C40.5,107.755 40.677,107.55 40.91,107.508L41,107.5L48.857,107.5C54.093,107.5 58.351,103.393 58.496,98.276L58.5,98.006L58.5,92C58.5,91.724 58.724,91.5 59,91.5Z'
+        a:strokeColor='#00000000' a:strokeWidth='1'/>
+    <path a:fillColor='#5F6368' a:fillType='nonZero'
+        a:pathData='M34,1.5C34.276,1.5 34.5,1.724 34.5,2C34.5,2.245 34.323,2.45 34.09,2.492L34,2.5L11.909,2.5C6.803,2.5 2.646,6.607 2.504,11.729L2.5,12L2.5,98C2.5,103.157 6.569,107.353 11.641,107.496L11.909,107.5L31.251,107.5C31.528,107.5 31.751,107.724 31.751,108C31.751,108.245 31.574,108.45 31.341,108.492L31.251,108.5L11.909,108.5C6.253,108.5 1.653,103.951 1.504,98.284L1.5,98L1.5,12C1.5,6.297 6.008,1.654 11.627,1.504L11.909,1.5L34,1.5Z'
+        a:strokeColor='#00000000' a:strokeWidth='1'/>
+</vector>
diff --git a/chrome/android/features/cablev2_authenticator/java/res/drawable/ble.xml b/chrome/android/features/cablev2_authenticator/java/res/drawable/ble.xml
new file mode 100644
index 0000000..b64622d
--- /dev/null
+++ b/chrome/android/features/cablev2_authenticator/java/res/drawable/ble.xml
@@ -0,0 +1,24 @@
+<vector a:height='200dp' a:viewportHeight='110'
+    a:viewportWidth='90' a:width='163.63dp' xmlns:a='http://schemas.android.com/apk/res/android'>
+    <path a:fillColor='#FFFFFF' a:fillType='evenOdd'
+        a:pathData='M11.986,6C8.685,6 6,8.616 6,11.832L6,98.168C6,101.384 8.685,104 11.986,104L49.015,104C52.316,104 55,101.384 55,98.168L55,11.832C55,8.616 52.316,6 49.015,6L11.986,6Z'
+        a:strokeColor='#E8E9EB' a:strokeWidth='1'/>
+    <path a:fillColor='#BDC0C5' a:fillType='nonZero'
+        a:pathData='M48.792,1.5C54.606,1.5 59.342,6.036 59.496,11.693L59.5,11.977L59.5,84C59.5,84.276 59.276,84.5 59,84.5C58.755,84.5 58.55,84.323 58.508,84.09L58.5,84L58.5,11.977C58.5,6.836 54.304,2.647 49.068,2.504L48.792,2.5L45,2.5C44.724,2.5 44.5,2.276 44.5,2C44.5,1.755 44.677,1.55 44.91,1.508L45,1.5L48.792,1.5Z'
+        a:strokeColor='#00000000' a:strokeWidth='1'/>
+    <path a:fillColor='#F7BB2A' a:fillType='nonZero'
+        a:pathData='M44.999,33.5C44.999,21.626 54.626,12 66.499,12C78.374,12 88,21.626 88,33.5C88,45.374 78.374,55 66.499,55C54.626,55 44.999,45.374 44.999,33.5'
+        a:strokeColor='#00000000' a:strokeWidth='1'/>
+    <path a:fillColor='#E8AF25' a:fillType='nonZero'
+        a:pathData='M45,33.5C45,25.856 48.989,19.144 54.999,15.331L54.999,51.669C48.989,47.856 45,41.144 45,33.5Z'
+        a:strokeColor='#00000000' a:strokeWidth='1'/>
+    <path a:fillColor='#FFFFFF' a:fillType='nonZero'
+        a:pathData='M71.324,37.607L66.686,42.245L65.873,42.245L65.873,36.08L62.145,39.808L61,38.663L65.54,34.122L61,29.582L62.145,28.437L65.873,32.165L65.873,26L66.686,26L71.324,30.638L67.831,34.122L71.324,37.607ZM67.498,39.134L69.025,37.607L67.498,36.08L67.498,39.134ZM69.025,30.638L67.498,29.111L67.498,32.165L69.025,30.638L69.025,30.638Z'
+        a:strokeColor='#F7BB2A' a:strokeWidth='0.6'/>
+    <path a:fillColor='#4285F4' a:fillType='nonZero'
+        a:pathData='M59,91.5C59.245,91.5 59.45,91.677 59.492,91.91L59.5,92L59.5,98.006C59.5,103.708 54.888,108.346 49.145,108.496L48.857,108.5L41,108.5C40.724,108.5 40.5,108.276 40.5,108C40.5,107.755 40.677,107.55 40.91,107.508L41,107.5L48.857,107.5C54.093,107.5 58.351,103.393 58.496,98.276L58.5,98.006L58.5,92C58.5,91.724 58.724,91.5 59,91.5Z'
+        a:strokeColor='#00000000' a:strokeWidth='1'/>
+    <path a:fillColor='#BDC0C5' a:fillType='nonZero'
+        a:pathData='M34,1.5C34.276,1.5 34.5,1.724 34.5,2C34.5,2.245 34.323,2.45 34.09,2.492L34,2.5L11.909,2.5C6.803,2.5 2.646,6.607 2.504,11.729L2.5,12L2.5,98C2.5,103.157 6.569,107.353 11.641,107.496L11.909,107.5L31.251,107.5C31.528,107.5 31.751,107.724 31.751,108C31.751,108.245 31.574,108.45 31.341,108.492L31.251,108.5L11.909,108.5C6.253,108.5 1.653,103.951 1.504,98.284L1.5,98L1.5,12C1.5,6.297 6.008,1.654 11.627,1.504L11.909,1.5L34,1.5Z'
+        a:strokeColor='#00000000' a:strokeWidth='1'/>
+</vector>
diff --git a/chrome/android/features/cablev2_authenticator/java/res/layout-sw600dp/cablev2_ble_enable.xml b/chrome/android/features/cablev2_authenticator/java/res/layout-sw600dp/cablev2_ble_enable.xml
new file mode 100644
index 0000000..355820ff
--- /dev/null
+++ b/chrome/android/features/cablev2_authenticator/java/res/layout-sw600dp/cablev2_ble_enable.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2020 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. -->
+
+<LinearLayout
+    xmlns:a="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    a:layout_width="match_parent"
+    a:layout_height="match_parent"
+    a:orientation="vertical"
+    a:gravity="center">
+
+  <TextView
+      a:layout_width="match_parent"
+      a:layout_height="wrap_content"
+      a:layout_marginTop="-104dp"
+      a:layout_marginLeft="24dp"
+      a:layout_marginRight="24dp"
+      a:gravity="center_horizontal"
+      a:text="@string/cablev2_ble_enable_title"
+      a:textSize="36sp" />
+
+  <!-- This is a semantically-meaningless picture of a phone and BLE icon that
+  screen readers can ignore. Thus contentDescription is null.
+
+  The visual center of this image isn't the pixel-center, and thus a left margin
+  is used to tweak the horizontal centering. The tooling thinks that's an RTL
+  issue, but RTL mode doesn't reflect images so the padding still needs to
+  be on the left. tools:ignore is used to skip this warning. -->
+  <ImageView
+      a:layout_width="match_parent"
+      a:layout_height="212dp"
+      a:layout_marginTop="52dp"
+      a:layout_marginLeft="40dp"
+      a:layout_marginBottom="35dp"
+      a:contentDescription="@null"
+      a:gravity="center_horizontal"
+      a:src="@drawable/ble"
+      tools:ignore="RtlHardcoded"/>
+
+  <TextView
+      a:layout_width="wrap_content"
+      a:layout_height="wrap_content"
+      a:layout_marginTop="4dp"
+      a:layout_gravity="center_horizontal"
+      a:padding="0px"
+      a:textSize="24sp"
+      a:text="@string/cablev2_ble_enable_body" />
+
+</LinearLayout>
diff --git a/chrome/android/features/cablev2_authenticator/java/res/layout/cablev2_ble_enable.xml b/chrome/android/features/cablev2_authenticator/java/res/layout/cablev2_ble_enable.xml
new file mode 100644
index 0000000..51a393d
--- /dev/null
+++ b/chrome/android/features/cablev2_authenticator/java/res/layout/cablev2_ble_enable.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2021 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. -->
+
+<LinearLayout
+    xmlns:a="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    a:layout_width="match_parent"
+    a:layout_height="match_parent"
+    a:orientation="vertical">
+
+  <TextView
+      style="@style/TextAppearance.Headline.Primary"
+      a:layout_width="match_parent"
+      a:layout_height="wrap_content"
+      a:layout_marginTop="104dp"
+      a:gravity="center_horizontal"
+      a:text="@string/cablev2_ble_enable_title"/>
+
+  <!-- This is a semantically-meaningless picture of a phone and BLE icon that
+  screen readers can ignore. Thus contentDescription is null.
+
+  The visual center of this image isn't the pixel-center, and thus a left margin
+  is used to tweak the horizontal centering. The tooling thinks that's an RTL
+  issue, but RTL mode doesn't reflect images so the padding still needs to
+  be on the left. tools:ignore is used to skip this warning. -->
+  <ImageView
+      a:layout_width="match_parent"
+      a:layout_height="212dp"
+      a:layout_marginTop="52dp"
+      a:layout_marginLeft="40dp"
+      a:layout_marginBottom="35dp"
+      a:contentDescription="@null"
+      a:gravity="center_horizontal"
+      a:src="@drawable/ble"
+      tools:ignore="RtlHardcoded"/>
+
+  <TextView
+      style="@style/TextAppearance.TextMedium.Secondary"
+      a:layout_marginTop="4dp"
+      a:layout_marginLeft="40dp"
+      a:layout_marginRight="40dp"
+      a:layout_width="match_parent"
+      a:layout_height="wrap_content"
+      a:gravity="center_horizontal"
+      a:text="@string/cablev2_ble_enable_body"/>
+
+</LinearLayout>
diff --git a/chrome/android/features/cablev2_authenticator/java/src/org/chromium/chrome/browser/webauth/authenticator/CableAuthenticator.java b/chrome/android/features/cablev2_authenticator/java/src/org/chromium/chrome/browser/webauth/authenticator/CableAuthenticator.java
index efd6ca7..b3fa758 100644
--- a/chrome/android/features/cablev2_authenticator/java/src/org/chromium/chrome/browser/webauth/authenticator/CableAuthenticator.java
+++ b/chrome/android/features/cablev2_authenticator/java/src/org/chromium/chrome/browser/webauth/authenticator/CableAuthenticator.java
@@ -63,6 +63,13 @@
     private static final int CTAP2_ERR_UNSUPPORTED_OPTION = 0x2D;
     private static final int CTAP2_ERR_OTHER = 0x7F;
 
+    // sOwnBluetooth is true if this class owns the fact that Bluetooth is enabled and needs to
+    // disable it once complete.
+    private static boolean sOwnBluetooth;
+    // sInstanceCount is the number of instances of this class that have been created and not
+    // closed.
+    private static int sInstanceCount;
+
     private final Context mContext;
     private final CableAuthenticatorUI mUi;
     private final SingleThreadTaskRunner mTaskRunner;
@@ -87,6 +94,8 @@
     public CableAuthenticator(Context context, CableAuthenticatorUI ui, long networkContext,
             long registration, byte[] secret, boolean isFcmNotification, UsbAccessory accessory,
             byte[] serverLink) {
+        sInstanceCount++;
+
         mContext = context;
         mUi = ui;
 
@@ -423,9 +432,12 @@
 
     /**
      * Called to indicate that Bluetooth is now enabled and a cloud message can be processed.
+     *
+     * @param needToDisable true if BLE needs to be disabled afterwards
      */
-    void onBluetoothReadyForCloudMessage() {
+    void onBluetoothReadyForCloudMessage(boolean needToDisable) {
         assert mTaskRunner.belongsToCurrentThread();
+        sOwnBluetooth |= needToDisable;
         mHandle = CableAuthenticatorJni.get().startCloudMessage(this);
     }
 
@@ -437,6 +449,22 @@
     void close() {
         assert mTaskRunner.belongsToCurrentThread();
         CableAuthenticatorJni.get().stop(mHandle);
+
+        // If Bluetooth was enabled by CableAuthenticatorUI then |sOwnBluetooth| will be true.
+        // However, if another instance has already been created (because the user pressed another
+        // notification while this was still outstanding) then don't disable it yet.
+        sInstanceCount--;
+        if (sOwnBluetooth) {
+            if (sInstanceCount == 0) {
+                Log.i(TAG, "disabling Bluetooth");
+                BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+                adapter.disable();
+
+                sOwnBluetooth = false;
+            } else {
+                Log.i(TAG, "not disabling Bluetooth yet because other instances exist");
+            }
+        }
     }
 
     static String getName() {
diff --git a/chrome/android/features/cablev2_authenticator/java/src/org/chromium/chrome/browser/webauth/authenticator/CableAuthenticatorUI.java b/chrome/android/features/cablev2_authenticator/java/src/org/chromium/chrome/browser/webauth/authenticator/CableAuthenticatorUI.java
index 954d9e9..2854bf50 100644
--- a/chrome/android/features/cablev2_authenticator/java/src/org/chromium/chrome/browser/webauth/authenticator/CableAuthenticatorUI.java
+++ b/chrome/android/features/cablev2_authenticator/java/src/org/chromium/chrome/browser/webauth/authenticator/CableAuthenticatorUI.java
@@ -42,9 +42,11 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.task.PostTask;
 import org.chromium.chrome.browser.notifications.NotificationConstants;
 import org.chromium.chrome.browser.notifications.NotificationWrapperBuilderFactory;
 import org.chromium.chrome.browser.notifications.channels.ChromeChannelDefinitions;
+import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.ui.base.ActivityAndroidPermissionDelegate;
 import org.chromium.ui.base.AndroidPermissionDelegate;
 import org.chromium.ui.widget.Toast;
@@ -62,6 +64,11 @@
     // to a request to enable Bluetooth. (Request codes can only be 16-bit.)
     private static final int ENABLE_BLUETOOTH_REQUEST_CODE = 64907;
 
+    // BLE_SCREEN_DELAY_SECS is the number of seconds that the screen for BLE
+    // enabling will show before the request to actually enable BLE (which
+    // causes Android to draw on top of it) is made.
+    private static final int BLE_SCREEN_DELAY_SECS = 2;
+
     // USB_PROMPT_TIMEOUT_SECS is the number of seconds the spinner will show
     // for before being replaced with a prompt to connect via USB cable.
     private static final int USB_PROMPT_TIMEOUT_SECS = 20;
@@ -108,6 +115,7 @@
     private TextView mStatusText;
     private View mErrorView;
     private View mErrorCloseButton;
+    private View mSpinnerView;
 
     // mErrorCode contains a value of the authenticator::Platform::Error
     // enumeration when |mMode| is |ERROR|.
@@ -178,7 +186,7 @@
         if (mMode == Mode.FCM) {
             BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
             if (adapter.isEnabled()) {
-                mAuthenticator.onBluetoothReadyForCloudMessage();
+                mAuthenticator.onBluetoothReadyForCloudMessage(/*needToDisable=*/false);
             } else {
                 mNeedToSignalBluetoothReady = true;
             }
@@ -192,6 +200,28 @@
         return km.isDeviceSecure();
     }
 
+    private View createSpinnerScreen(LayoutInflater inflater, ViewGroup container) {
+        View v = inflater.inflate(R.layout.cablev2_serverlink, container, false);
+        mStatusText = v.findViewById(R.id.status_text);
+
+        final AnimatedVectorDrawableCompat anim = AnimatedVectorDrawableCompat.create(
+                getContext(), R.drawable.circle_loader_animation);
+        // There is no way to make an animation loop. Instead it must be
+        // manually started each time it completes.
+        anim.registerAnimationCallback(new Animatable2Compat.AnimationCallback() {
+            @Override
+            public void onAnimationEnd(Drawable drawable) {
+                if (drawable != null) {
+                    anim.start();
+                }
+            }
+        });
+        ((ImageView) v.findViewById(R.id.spinner)).setImageDrawable(anim);
+        anim.start();
+
+        return v;
+    }
+
     @Override
     public View onCreateView(
             LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -202,54 +232,43 @@
         mErrorView = inflater.inflate(R.layout.cablev2_error, container, false);
 
         View v = null;
-        switch (mMode) {
-            case USB:
-                v = inflater.inflate(R.layout.cablev2_usb_attached, container, false);
-                break;
 
-            case FCM:
-            case SERVER_LINK:
-                v = inflater.inflate(R.layout.cablev2_serverlink, container, false);
-                mStatusText = v.findViewById(R.id.status_text);
+        if (mNeedToSignalBluetoothReady) {
+            v = inflater.inflate(R.layout.cablev2_ble_enable, container, false);
+            mSpinnerView = createSpinnerScreen(inflater, container);
+        } else {
+            switch (mMode) {
+                case USB:
+                    v = inflater.inflate(R.layout.cablev2_usb_attached, container, false);
+                    break;
 
-                ImageView spinner = (ImageView) v.findViewById(R.id.spinner);
-                final AnimatedVectorDrawableCompat anim = AnimatedVectorDrawableCompat.create(
-                        getContext(), R.drawable.circle_loader_animation);
-                // There is no way to make an animation loop. Instead it must be
-                // manually started each time it completes.
-                anim.registerAnimationCallback(new Animatable2Compat.AnimationCallback() {
-                    @Override
-                    public void onAnimationEnd(Drawable drawable) {
-                        if (drawable != null && drawable.isVisible()) {
-                            anim.start();
-                        }
-                    }
-                });
-                spinner.setImageDrawable(anim);
-                anim.start();
-                break;
+                case FCM:
+                case SERVER_LINK:
+                    v = createSpinnerScreen(inflater, container);
+                    break;
 
-            case QR:
-                // TODO: should check FEATURE_BLUETOOTH with
-                // https://developer.android.com/reference/android/content/pm/PackageManager.html#hasSystemFeature(java.lang.String)
-                // TODO: strings should be translated but this will be replaced during
-                // the UI process.
+                case QR:
+                    // TODO: should check FEATURE_BLUETOOTH with
+                    // https://developer.android.com/reference/android/content/pm/PackageManager.html#hasSystemFeature(java.lang.String)
+                    // TODO: strings should be translated but this will be replaced during
+                    // the UI process.
 
-                v = inflater.inflate(R.layout.cablev2_qr_scan, container, false);
-                mQRButton = v.findViewById(R.id.qr_scan);
-                mQRButton.setOnClickListener(this);
+                    v = inflater.inflate(R.layout.cablev2_qr_scan, container, false);
+                    mQRButton = v.findViewById(R.id.qr_scan);
+                    mQRButton.setOnClickListener(this);
 
-                mHeader = v.findViewById(R.id.qr_image);
-                setHeader(R.style.idle);
+                    mHeader = v.findViewById(R.id.qr_image);
+                    setHeader(R.style.idle);
 
-                mUnlinkButton = v.findViewById(R.id.unlink);
-                mUnlinkButton.setOnClickListener(this);
-                break;
+                    mUnlinkButton = v.findViewById(R.id.unlink);
+                    mUnlinkButton.setOnClickListener(this);
+                    break;
 
-            case ERROR:
-                fillOutErrorUI(mErrorCode);
-                v = mErrorView;
-                break;
+                case ERROR:
+                    fillOutErrorUI(mErrorCode);
+                    v = mErrorView;
+                    break;
+            }
         }
 
         top.addView(v);
@@ -259,12 +278,17 @@
     @Override
     public void onResume() {
         super.onResume();
-
-        if (mNeedToSignalBluetoothReady) {
-            mNeedToSignalBluetoothReady = false;
-            startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE),
-                    ENABLE_BLUETOOTH_REQUEST_CODE);
+        if (!mNeedToSignalBluetoothReady) {
+            return;
         }
+
+        mNeedToSignalBluetoothReady = false;
+        PostTask.postDelayedTask(UiThreadTaskTraits.DEFAULT, () -> {
+            if (mAuthenticator != null) {
+                startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE),
+                        ENABLE_BLUETOOTH_REQUEST_CODE);
+            }
+        }, BLE_SCREEN_DELAY_SECS * 1000);
     }
 
     /**
@@ -417,12 +441,18 @@
         // a lock-screen notification.
         if (mAuthenticator != null) {
             mAuthenticator.close();
+            mAuthenticator = null;
         }
     }
 
     @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
+
+        if (mAuthenticator == null) {
+            return;
+        }
+
         if (requestCode != ENABLE_BLUETOOTH_REQUEST_CODE) {
             mAuthenticator.onActivityResult(requestCode, resultCode, data);
             return;
@@ -441,7 +471,11 @@
                 break;
 
             case FCM:
-                mAuthenticator.onBluetoothReadyForCloudMessage();
+                ViewGroup top = (ViewGroup) getView();
+                top.removeAllViews();
+                top.addView(mSpinnerView);
+
+                mAuthenticator.onBluetoothReadyForCloudMessage(/*needToDisable=*/true);
                 break;
 
             default:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ActivityTabProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/ActivityTabProvider.java
index 2ea7330..6dd4b3a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ActivityTabProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ActivityTabProvider.java
@@ -8,6 +8,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.Callback;
+import org.chromium.base.lifetime.Destroyable;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.chrome.browser.layouts.LayoutStateProvider;
 import org.chromium.chrome.browser.layouts.LayoutStateProvider.LayoutStateObserver;
@@ -23,7 +24,7 @@
 /**
  * A class that provides the current {@link Tab} for various states of the browser's activity.
  */
-public class ActivityTabProvider extends ObservableSupplierImpl<Tab> {
+public class ActivityTabProvider extends ObservableSupplierImpl<Tab> implements Destroyable {
     /**
      * A utility class for observing the activity tab via {@link TabObserver}. When the activity
      * tab changes, the observer is switched to that tab.
@@ -214,6 +215,7 @@
     }
 
     /** Clean up and detach any observers this object created. */
+    @Override
     public void destroy() {
         if (mLayoutStateProvider != null) mLayoutStateProvider.removeObserver(mLayoutStateObserver);
         mLayoutStateProvider = null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/DEPS
index ede1301..bf2e713e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/DEPS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/DEPS
@@ -92,18 +92,9 @@
   "NativePageFactory\.java": [
     "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
   ],
-  "OfflinePageTabObserver\.java": [
-    "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
-  ],
   "OfflineIndicatorController\.java": [
     "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
   ],
-  "TopSnackbarManager\.java": [
-    "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
-  ],
-  "TopSnackbarView\.java": [
-    "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
-  ],
   "UpdateInfoBarController\.java": [
     "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
   ],
@@ -128,9 +119,6 @@
   "PaymentHandlerMediator\.java": [
     "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
   ],
-  "SafeBrowsingPasswordReuseDialogBridge\.java": [
-    "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
-  ],
   "SendTabToSelfShareActivity\.java": [
     "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
   ],
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
index a4fba1ce..16b5b44 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -354,6 +354,9 @@
     protected RootUiCoordinator mRootUiCoordinator;
 
     @Nullable
+    private BottomContainer mBottomContainer;
+
+    @Nullable
     private StartupTabPreloader mStartupTabPreloader;
 
     private LaunchCauseMetrics mLaunchCauseMetrics;
@@ -528,10 +531,10 @@
                 getLaunchCauseMetrics().onReceivedIntent();
             }
 
-            BottomContainer bottomContainer = (BottomContainer) findViewById(R.id.bottom_container);
+            mBottomContainer = (BottomContainer) findViewById(R.id.bottom_container);
 
             // TODO(crbug.com/1199776): Move this to the RootUiCoordinator.
-            mSnackbarManager = new SnackbarManager(this, bottomContainer, getWindowAndroid());
+            mSnackbarManager = new SnackbarManager(this, mBottomContainer, getWindowAndroid());
             SnackbarManagerProvider.attach(getWindowAndroid(), mSnackbarManager);
 
             // Make the activity listen to policy change events
@@ -556,10 +559,9 @@
                         getControlContainerHeightResource());
             }
 
-            bottomContainer.initialize(getBrowserControlsManager(),
+            mBottomContainer.initialize(getBrowserControlsManager(),
                     getWindowAndroid().getApplicationBottomInsetProvider(),
                     mManualFillingComponentSupplier.get().getBottomInsetSupplier());
-            getLifecycleDispatcher().register(bottomContainer);
 
             // Should be called after TabModels are initialized.
             ShareDelegate shareDelegate =
@@ -1467,6 +1469,11 @@
             mTabModelSelectorSupplier.destroy();
         }
 
+        if (mBottomContainer != null) {
+            mBottomContainer.destroy();
+            mBottomContainer = null;
+        }
+
         if (mDisplayAndroidObserver != null) {
             getWindowAndroid().getDisplay().removeObserver(mDisplayAndroidObserver);
             mDisplayAndroidObserver = null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/BrowserControlsManagerSupplier.java b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/BrowserControlsManagerSupplier.java
index c7f9fe9d..c75de84 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/BrowserControlsManagerSupplier.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/BrowserControlsManagerSupplier.java
@@ -21,15 +21,20 @@
             new UnownedUserDataKey<BrowserControlsManagerSupplier>(
                     BrowserControlsManagerSupplier.class);
 
+    /** Return {@link TabModelSelector} supplier associated with the given {@link WindowAndroid}. */
+    public static ObservableSupplier<BrowserControlsManager> from(
+            @Nullable WindowAndroid windowAndroid) {
+        if (windowAndroid == null) return null;
+        return KEY.retrieveDataFromHost(windowAndroid.getUnownedUserDataHost());
+    }
+
     /**
      * Retrieves an {@link ObservableSupplier} from the given host. Real implementations should
      * use {@link WindowAndroid}.
      */
     public static @Nullable BrowserControlsManager getValueOrNullFrom(
             @Nullable WindowAndroid windowAndroid) {
-        if (windowAndroid == null) return null;
-        BrowserControlsManagerSupplier supplier =
-                KEY.retrieveDataFromHost(windowAndroid.getUnownedUserDataHost());
+        ObservableSupplier<BrowserControlsManager> supplier = from(windowAndroid);
         return supplier == null ? null : supplier.get();
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserver.java
index aecf0bbf..40ed345 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserver.java
@@ -13,17 +13,19 @@
 import org.chromium.base.ApplicationStatus.ActivityStateListener;
 import org.chromium.base.Log;
 import org.chromium.base.metrics.RecordUserAction;
-import org.chromium.chrome.browser.app.ChromeActivity;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabHidingType;
 import org.chromium.chrome.browser.tab.TabSelectionType;
 import org.chromium.chrome.browser.tabmodel.TabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tabmodel.TabModelSelectorSupplier;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager.SnackbarController;
+import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManagerProvider;
 import org.chromium.net.NetworkChangeNotifier;
+import org.chromium.ui.base.WindowAndroid;
 import org.chromium.url.GURL;
 
 import java.util.HashMap;
@@ -75,13 +77,15 @@
     /** Current tab, kept track of for the network change notification. */
     private Tab mCurrentTab;
 
-    static OfflinePageTabObserver getObserverForActivity(ChromeActivity activity) {
+    private static OfflinePageTabObserver getObserverForWindowAndroid(WindowAndroid windowAndroid) {
         ensureObserverMapInitialized();
+        Activity activity = windowAndroid.getActivity().get();
         OfflinePageTabObserver observer = sObservers.get(activity);
         if (observer == null) {
-            observer = new OfflinePageTabObserver(activity.getTabModelSelector(),
-                    activity.getSnackbarManager(),
-                    createReloadSnackbarController(activity.getTabModelSelector()));
+            TabModelSelector tabModelSelector = TabModelSelectorSupplier.from(windowAndroid).get();
+            observer = new OfflinePageTabObserver(tabModelSelector,
+                    SnackbarManagerProvider.from(windowAndroid),
+                    createReloadSnackbarController(tabModelSelector));
             sObservers.put(activity, observer);
         }
         return observer;
@@ -112,8 +116,7 @@
      * @param tab The tab we are adding an observer for.
      */
     public static void addObserverForTab(Tab tab) {
-        OfflinePageTabObserver observer =
-                getObserverForActivity((ChromeActivity) tab.getWindowAndroid().getActivity().get());
+        OfflinePageTabObserver observer = getObserverForWindowAndroid(tab.getWindowAndroid());
         observer.startObservingTab(tab);
         observer.maybeShowReloadSnackbar(tab, false);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorController.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorController.java
index ca68f61..d7f266f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorController.java
@@ -22,6 +22,7 @@
 import org.chromium.chrome.browser.download.DownloadOpenSource;
 import org.chromium.chrome.browser.download.DownloadUtils;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.fullscreen.BrowserControlsManagerSupplier;
 import org.chromium.chrome.browser.net.connectivitydetector.ConnectivityDetector;
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
@@ -261,7 +262,8 @@
                                            R.string.offline_indicator_view_offline_content),
                                 null);
         if (isUsingTopSnackbar()) {
-            mTopSnackbarManager.show(snackbar, chromeActivity);
+            mTopSnackbarManager.show(snackbar, chromeActivity, chromeActivity.getWindowAndroid(),
+                    BrowserControlsManagerSupplier.from(chromeActivity.getWindowAndroid()));
         } else {
             // Show a bottom snackbar via SnackbarManager.
             SnackbarManager snackbarManager = chromeActivity.getSnackbarManager();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/TopSnackbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/TopSnackbarManager.java
index f9021a5..ac0f2669 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/TopSnackbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/TopSnackbarManager.java
@@ -9,12 +9,14 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.ActivityState;
 import org.chromium.base.ApplicationStatus;
-import org.chromium.chrome.browser.app.ChromeActivity;
+import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
+import org.chromium.chrome.browser.fullscreen.BrowserControlsManager;
 import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
 import org.chromium.ui.base.WindowAndroid;
 
@@ -34,6 +36,7 @@
     private Activity mActivity;
     private Snackbar mSnackbar;
     private TopSnackbarView mSnackbarView;
+    private BrowserControlsManager mBrowserControlsManager;
 
     public TopSnackbarManager() {
         mDismissSnackbarHandler = new Handler();
@@ -67,8 +70,10 @@
     /**
      * Shows a snackbar at the top of the given activity.
      */
-    public void show(Snackbar snackbar, Activity activity) {
+    public void show(Snackbar snackbar, Activity activity, WindowAndroid windowAndroid,
+            @Nullable Supplier<BrowserControlsManager> browserControlsManagerSupplier) {
         if (mSnackbar != null) return;
+
         @ActivityState
         int state = ApplicationStatus.getStateForActivity(activity);
         if (state != ActivityState.STARTED && state != ActivityState.RESUMED) return;
@@ -76,19 +81,16 @@
         mActivity = activity;
         mSnackbar = snackbar;
 
-        WindowAndroid windowAndroid = null;
-        if (activity instanceof ChromeActivity) {
-            windowAndroid = ((ChromeActivity) activity).getWindowAndroid();
-        }
-        mSnackbarView = new TopSnackbarView(activity, this, mSnackbar, windowAndroid);
+        mSnackbarView = new TopSnackbarView(
+                activity, this, mSnackbar, windowAndroid, browserControlsManagerSupplier);
         mSnackbarView.show();
         mSnackbarView.announceforAccessibility();
         mDismissSnackbarHandler.removeCallbacks(mDismissSnackbarRunnable);
         mDismissSnackbarHandler.postDelayed(mDismissSnackbarRunnable, mSnackbar.getDuration());
 
-        if (activity instanceof ChromeActivity) {
-            ChromeActivity chromeActivity = (ChromeActivity) activity;
-            chromeActivity.getBrowserControlsManager().addObserver(this);
+        if (browserControlsManagerSupplier != null && browserControlsManagerSupplier.hasValue()) {
+            mBrowserControlsManager = browserControlsManagerSupplier.get();
+            mBrowserControlsManager.addObserver(this);
         }
 
         ApplicationStatus.registerStateListenerForActivity(this, activity);
@@ -112,9 +114,9 @@
 
         ApplicationStatus.unregisterActivityStateListener(this);
 
-        if (mActivity instanceof ChromeActivity) {
-            ChromeActivity chromeActivity = (ChromeActivity) mActivity;
-            chromeActivity.getBrowserControlsManager().removeObserver(this);
+        if (mBrowserControlsManager != null) {
+            mBrowserControlsManager.removeObserver(this);
+            mBrowserControlsManager = null;
         }
 
         mDismissSnackbarHandler.removeCallbacks(mDismissSnackbarRunnable);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/TopSnackbarView.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/TopSnackbarView.java
index 31f30af..65a129b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/TopSnackbarView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/TopSnackbarView.java
@@ -10,8 +10,9 @@
 
 import androidx.annotation.Nullable;
 
+import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.app.ChromeActivity;
+import org.chromium.chrome.browser.fullscreen.BrowserControlsManager;
 import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarView;
 import org.chromium.ui.base.WindowAndroid;
@@ -21,6 +22,7 @@
  */
 public class TopSnackbarView extends SnackbarView {
     private final Activity mActivity;
+    private final Supplier<BrowserControlsManager> mBrowserControlsManagerSupplier;
 
     /**
      * Creates an instance of the {@link SnackbarView}.
@@ -32,10 +34,12 @@
      *                   will determine where to attach the snackbar.
      */
     public TopSnackbarView(Activity activity, OnClickListener listener, Snackbar snackbar,
-            @Nullable WindowAndroid windowAndroid) {
+            @Nullable WindowAndroid windowAndroid,
+            @Nullable Supplier<BrowserControlsManager> browserControlsManagerSupplier) {
         super(activity, listener, snackbar, (ViewGroup) activity.findViewById(android.R.id.content),
                 windowAndroid);
         mActivity = activity;
+        mBrowserControlsManagerSupplier = browserControlsManagerSupplier;
     }
 
     @Override
@@ -55,12 +59,12 @@
     }
 
     private int getOffsetFromTop() {
-        if (!(mActivity instanceof ChromeActivity)) return 0;
+        if (mBrowserControlsManagerSupplier == null
+                || !mBrowserControlsManagerSupplier.hasValue()) {
+            return 0;
+        }
+        if (mBrowserControlsManagerSupplier.get().getContentOffset() == 0) return 0;
 
-        ChromeActivity chromeActivity = (ChromeActivity) mActivity;
-
-        if (chromeActivity.getBrowserControlsManager().getContentOffset() == 0) return 0;
-
-        return chromeActivity.getBrowserControlsManager().getTopControlsHeight();
+        return mBrowserControlsManagerSupplier.get().getTopControlsHeight();
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingPasswordReuseDialogBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingPasswordReuseDialogBridge.java
index 66a0c879..88ae325 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingPasswordReuseDialogBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingPasswordReuseDialogBridge.java
@@ -7,7 +7,7 @@
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.app.ChromeActivity;
+import org.chromium.chrome.browser.fullscreen.BrowserControlsManagerSupplier;
 import org.chromium.chrome.browser.password_manager.PasswordManagerDialogContents;
 import org.chromium.chrome.browser.password_manager.PasswordManagerDialogCoordinator;
 import org.chromium.ui.base.WindowAndroid;
@@ -24,15 +24,16 @@
     // objects.
     private final PasswordManagerDialogCoordinator mDialogCoordinator;
     // Used to initialize the custom view of the dialog.
-    private final WeakReference<ChromeActivity> mActivity;
+    private final WindowAndroid mWindowAndroid;
 
     private SafeBrowsingPasswordReuseDialogBridge(
             WindowAndroid windowAndroid, long nativePasswordReuseDialogViewAndroid) {
         mNativePasswordReuseDialogViewAndroid = nativePasswordReuseDialogViewAndroid;
-        ChromeActivity activity = (ChromeActivity) windowAndroid.getActivity().get();
-        mActivity = new WeakReference<>(activity);
-        mDialogCoordinator = new PasswordManagerDialogCoordinator(activity.getModalDialogManager(),
-                activity.findViewById(android.R.id.content), activity.getBrowserControlsManager());
+        mWindowAndroid = windowAndroid;
+        mDialogCoordinator =
+                new PasswordManagerDialogCoordinator(mWindowAndroid.getModalDialogManager(),
+                        mWindowAndroid.getActivity().get().findViewById(android.R.id.content),
+                        BrowserControlsManagerSupplier.getValueOrNullFrom(mWindowAndroid));
     }
 
     @CalledByNative
@@ -44,13 +45,13 @@
     @CalledByNative
     public void showDialog(String dialogTitle, String dialogDetails, String buttonText,
             int[] boldStartRanges, int[] boldEndRanges) {
-        if (mActivity.get() == null) return;
+        if (mWindowAndroid.getActivity().get() == null) return;
 
         PasswordManagerDialogContents contents =
                 createDialogContents(dialogTitle, dialogDetails, buttonText);
         contents.setBoldRanges(boldStartRanges, boldEndRanges);
 
-        mDialogCoordinator.initialize(mActivity.get(), contents);
+        mDialogCoordinator.initialize(mWindowAndroid.getActivity().get(), contents);
         mDialogCoordinator.showDialog();
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorProfileSupplier.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorProfileSupplier.java
index ab95a56..a8dcc48 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorProfileSupplier.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorProfileSupplier.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.tabmodel;
 
+import org.chromium.base.lifetime.Destroyable;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -16,7 +17,7 @@
  * accessed from a single thread.
  */
 public class TabModelSelectorProfileSupplier
-        extends ObservableSupplierImpl<Profile> implements TabModelSelectorObserver {
+        extends ObservableSupplierImpl<Profile> implements TabModelSelectorObserver, Destroyable {
     private TabModelSelector mSelector;
     private boolean mIsTabStateInitialized;
 
@@ -56,10 +57,11 @@
         set(profile);
     }
 
+    @Override
     public void destroy() {
         if (mSelector != null) {
             mSelector.removeObserver(this);
             mSelector = null;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/BottomContainer.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/BottomContainer.java
index 4bfa2e6..8a837852 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ui/BottomContainer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/BottomContainer.java
@@ -8,10 +8,12 @@
 import android.util.AttributeSet;
 import android.widget.FrameLayout;
 
+import androidx.annotation.CallSuper;
+
 import org.chromium.base.Callback;
+import org.chromium.base.lifetime.Destroyable;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
-import org.chromium.chrome.browser.lifecycle.DestroyObserver;
 import org.chromium.ui.base.ApplicationViewportInsetSupplier;
 
 /**
@@ -19,7 +21,7 @@
  * bottom controls' offset changes.
  */
 public class BottomContainer
-        extends FrameLayout implements DestroyObserver, BrowserControlsStateProvider.Observer {
+        extends FrameLayout implements Destroyable, BrowserControlsStateProvider.Observer {
     /** An observer of the viewport insets to change this container's position. */
     private final Callback<Integer> mInsetObserver;
 
@@ -34,17 +36,13 @@
     /** The desired Y offset if unaffected by other UI. */
     private float mBaseYOffset;
 
-    /**
-     * Constructor for XML inflation.
-     */
+    /** Constructor for XML inflation. */
     public BottomContainer(Context context, AttributeSet attrs) {
         super(context, attrs);
         mInsetObserver = (inset) -> setTranslationY(mBaseYOffset);
     }
 
-    /**
-     * Initializes this container.
-     */
+    /** Initializes this container. */
     public void initialize(BrowserControlsStateProvider browserControlsStateProvider,
             ApplicationViewportInsetSupplier viewportInsetSupplier,
             ObservableSupplier<Integer> autofillUiBottomInsetSupplier) {
@@ -84,8 +82,9 @@
         setTranslationY(mBaseYOffset);
     }
 
+    @CallSuper
     @Override
-    public void onDestroy() {
+    public void destroy() {
         mBrowserControlsStateProvider.removeObserver(this);
         mViewportInsetSupplier.removeObserver(mInsetObserver);
         mAutofillUiBottomInsetSupplier.removeObserver(mInsetObserver);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorProfileSupplierTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorProfileSupplierTest.java
index 1a862f4..5b3cb79 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorProfileSupplierTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorProfileSupplierTest.java
@@ -105,13 +105,16 @@
     }
 
     @Test
-    public void testDestroy() {
+    public void testDestroyPreInitialization() {
         mSupplier.destroy();
         // There's nothing to tear down before the tab model selector is initialized.
         verify(mTabModelSelector, never()).removeObserver(mSupplier);
+    }
 
+    @Test
+    public void testDestroyPostInitialization() {
         mTabModelSelectorSupplier.set(mTabModelSelector);
         mSupplier.destroy();
         verify(mTabModelSelector).removeObserver(mSupplier);
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerActivityTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerActivityTest.java
index 97140ec..c79d7b1 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerActivityTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerActivityTest.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.toolbar.adaptive;
 
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
@@ -25,7 +26,6 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
-import org.robolectric.annotation.Resetter;
 
 import org.chromium.base.CommandLine;
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -68,8 +68,7 @@
         private static MockTabModelSelector sTabModelSelector;
         private static boolean sIsNTP;
 
-        @Resetter
-        public void reset() {
+        protected static void reset() {
             sTabModelSelector = null;
             sTabCreatorManager = null;
             sIsNTP = false;
@@ -110,6 +109,8 @@
                     doReturn(Mockito.mock(WebContents.class)).when(tab).getWebContents();
                     return tab;
                 });
+        assertNull(ShadowDelegate.sTabModelSelector);
+        assertNull(ShadowDelegate.sTabCreatorManager);
         ShadowDelegate.sTabModelSelector = tabModelSelector;
         ShadowDelegate.sTabCreatorManager = new MockTabCreatorManager(tabModelSelector);
         mTab = tabModelSelector.getCurrentTab();
@@ -127,6 +128,7 @@
     }
 
     private static void resetStaticState() {
+        ShadowDelegate.reset();
         // DisplayAndroidManager will reuse the Display between tests. This can cause
         // AsyncInitializationActivity#applyOverrides to set incorrect smallestWidth.
         DisplayAndroidManager.resetInstanceForTesting();
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn
index 5bc23068..ba75492 100644
--- a/chrome/app/BUILD.gn
+++ b/chrome/app/BUILD.gn
@@ -58,6 +58,12 @@
   }
 }
 
+if (is_win) {
+  source_set("chrome_exe_main_exports") {
+    sources = [ "chrome_exe_main_win.h" ]
+  }
+}
+
 if (is_android) {
   import("//build/config/android/rules.gni")
   android_generated_java_resources =
diff --git a/chrome/app/chrome_exe_main_win.cc b/chrome/app/chrome_exe_main_win.cc
index 18f6d330..63325a5 100644
--- a/chrome/app/chrome_exe_main_win.cc
+++ b/chrome/app/chrome_exe_main_win.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/app/chrome_exe_main_win.h"
+
 #include <windows.h>
 #include <malloc.h>
 #include <stddef.h>
@@ -33,6 +35,7 @@
 #include "base/win/windows_version.h"
 #include "build/build_config.h"
 #include "chrome/app/main_dll_loader_win.h"
+#include "chrome/app/packed_resources_integrity.h"
 #include "chrome/browser/policy/policy_path_parser.h"
 #include "chrome/browser/win/chrome_process_finder.h"
 #include "chrome/chrome_elf/chrome_elf_main.h"
@@ -217,6 +220,15 @@
 
 }  // namespace
 
+__declspec(dllexport) __cdecl void GetPakFileHashes(
+    const uint8_t** resources_pak,
+    const uint8_t** chrome_100_pak,
+    const uint8_t** chrome_200_pak) {
+  *resources_pak = kSha256_resources_pak.data();
+  *chrome_100_pak = kSha256_chrome_100_percent_pak.data();
+  *chrome_200_pak = kSha256_chrome_200_percent_pak.data();
+}
+
 #if !defined(WIN_CONSOLE_APP)
 int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prev, wchar_t*, int) {
 #else   // !defined(WIN_CONSOLE_APP)
diff --git a/chrome/app/chrome_exe_main_win.h b/chrome/app/chrome_exe_main_win.h
new file mode 100644
index 0000000..1edeae3
--- /dev/null
+++ b/chrome/app/chrome_exe_main_win.h
@@ -0,0 +1,28 @@
+// Copyright 2021 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_APP_CHROME_EXE_MAIN_WIN_H_
+#define CHROME_APP_CHROME_EXE_MAIN_WIN_H_
+
+#include <stdint.h>
+
+extern "C" {
+
+#if defined(CHROME_EXE_MAIN)
+#define CHROME_EXE_MAIN_EXPORT __declspec(dllexport)
+#else
+#define CHROME_EXE_MAIN_EXPORT
+#endif
+
+// Returns the SHA-256 hashes of the specified .pak files.
+CHROME_EXE_MAIN_EXPORT __cdecl void GetPakFileHashes(
+    const uint8_t** resources_pak,
+    const uint8_t** chrome_100_pak,
+    const uint8_t** chrome_200_pak);
+
+#undef CHROME_EXE_MAIN_EXPORT
+
+}  // extern "C"
+
+#endif  // CHROME_APP_CHROME_EXE_MAIN_WIN_H_
diff --git a/chrome/app/theme/default_100_percent/common/save_card.png b/chrome/app/theme/default_100_percent/common/save_card.png
new file mode 100644
index 0000000..e3fd0a1
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/save_card.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/save_card_dark.png b/chrome/app/theme/default_100_percent/common/save_card_dark.png
new file mode 100644
index 0000000..1a08b1cb
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/save_card_dark.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/save_password.png b/chrome/app/theme/default_100_percent/common/save_password.png
new file mode 100644
index 0000000..a6f8313d
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/save_password.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/save_password_dark.png b/chrome/app/theme/default_100_percent/common/save_password_dark.png
new file mode 100644
index 0000000..cabbcf7
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/save_password_dark.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/save_password_one_device.png b/chrome/app/theme/default_100_percent/common/save_password_one_device.png
index b9bd324..d604894d 100644
--- a/chrome/app/theme/default_100_percent/common/save_password_one_device.png
+++ b/chrome/app/theme/default_100_percent/common/save_password_one_device.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/save_password_one_device_dark.png b/chrome/app/theme/default_100_percent/common/save_password_one_device_dark.png
index cc338df0..66229e6 100644
--- a/chrome/app/theme/default_100_percent/common/save_password_one_device_dark.png
+++ b/chrome/app/theme/default_100_percent/common/save_password_one_device_dark.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/save_card.png b/chrome/app/theme/default_200_percent/common/save_card.png
new file mode 100644
index 0000000..b962d17
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/save_card.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/save_card_dark.png b/chrome/app/theme/default_200_percent/common/save_card_dark.png
new file mode 100644
index 0000000..3680855
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/save_card_dark.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/save_password.png b/chrome/app/theme/default_200_percent/common/save_password.png
new file mode 100644
index 0000000..4f592ee
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/save_password.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/save_password_dark.png b/chrome/app/theme/default_200_percent/common/save_password_dark.png
new file mode 100644
index 0000000..70630c3
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/save_password_dark.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/save_password_one_device.png b/chrome/app/theme/default_200_percent/common/save_password_one_device.png
index 8735a59..bf0aaf4 100644
--- a/chrome/app/theme/default_200_percent/common/save_password_one_device.png
+++ b/chrome/app/theme/default_200_percent/common/save_password_one_device.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/save_password_one_device_dark.png b/chrome/app/theme/default_200_percent/common/save_password_one_device_dark.png
index 8562411..69812f87 100644
--- a/chrome/app/theme/default_200_percent/common/save_password_one_device_dark.png
+++ b/chrome/app/theme/default_200_percent/common/save_password_one_device_dark.png
Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index 13bece8..561111bb 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -263,6 +263,10 @@
         <structure type="chrome_scaled_image" name="IDR_SAVE_PASSWORD_MULTI_DEVICE_DARK" file="common/save_password_multi_device_dark.png" />
         <structure type="chrome_scaled_image" name="IDR_SAVE_PASSWORD_ONE_DEVICE" file="common/save_password_one_device.png" />
         <structure type="chrome_scaled_image" name="IDR_SAVE_PASSWORD_ONE_DEVICE_DARK" file="common/save_password_one_device_dark.png" />
+        <structure type="chrome_scaled_image" name="IDR_SAVE_PASSWORD" file="common/save_password.png" />
+        <structure type="chrome_scaled_image" name="IDR_SAVE_PASSWORD_DARK" file="common/save_password_dark.png" />
+        <structure type="chrome_scaled_image" name="IDR_SAVE_CARD" file="common/save_card.png" />
+        <structure type="chrome_scaled_image" name="IDR_SAVE_CARD_DARK" file="common/save_card_dark.png" />
       </if>
       <structure type="chrome_scaled_image" name="IDR_SCREEN_CAPTURE_NOTIFICATION_GRIP" file="screen_capture_notification_grip.png" />
       <if expr="chromeos">
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 581da60d..cf3f149c 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -96,7 +96,6 @@
     "ENABLE_CHROMIUM_UPDATER=$enable_chromium_updater",
     "ENABLE_APP_SESSION_SERVICE=$enable_app_session_service",
     "USE_THIN_LTO=$use_thin_lto",
-    "ENABLE_PAK_FILE_INTEGRITY_CHECKS=$enable_pak_file_integrity_checks",
   ]
   if (is_win) {
     flags += [ "ENABLE_SEGMENT_HEAP=$enable_segment_heap" ]
@@ -4294,7 +4293,9 @@
       ]
     }
 
-    if (enable_pak_file_integrity_checks) {
+    # On Windows, the hashes are embedded in //chrome:chrome_initial rather
+    # than here in :chrome_dll.
+    if (!is_win) {
       deps += [ "//chrome:packed_resources_integrity" ]
     }
 
@@ -4965,6 +4966,7 @@
     deps += [
       ":chrome_process_finder",
       "//base/win:base_win_buildflags",
+      "//chrome/app:chrome_exe_main_exports",
       "//chrome/app/theme:chrome_unscaled_resources_grit",
       "//chrome/browser/safe_browsing/chrome_cleaner",
       "//chrome/browser/safe_browsing/chrome_cleaner:public",
diff --git a/chrome/browser/ash/crosapi/automation_ash.cc b/chrome/browser/ash/crosapi/automation_ash.cc
index e1af6d0..1657d3e 100644
--- a/chrome/browser/ash/crosapi/automation_ash.cc
+++ b/chrome/browser/ash/crosapi/automation_ash.cc
@@ -4,8 +4,6 @@
 
 #include "chrome/browser/ash/crosapi/automation_ash.h"
 
-#include "chrome/common/channel_info.h"
-#include "components/version_info/channel.h"
 #include "extensions/browser/api/automation_internal/automation_event_router.h"
 
 namespace crosapi {
@@ -47,22 +45,12 @@
     const std::vector<ui::AXTreeUpdate>& updates,
     const gfx::Point& mouse_location,
     const std::vector<ui::AXEvent>& events) {
-  // This prototype method is only implemented on developer builds of Chrome. We
-  // check for this by checking that the build of Chrome is unbranded.
-  if (chrome::GetChannel() != version_info::Channel::UNKNOWN)
-    return;
-
   extensions::AutomationEventRouter::GetInstance()->DispatchAccessibilityEvents(
       ui::AXTreeID::FromToken(tree_id), updates, mouse_location, events);
 }
 
 void AutomationAsh::DispatchTreeDestroyedEvent(
     const base::UnguessableToken& tree_id) {
-  // This prototype method is only implemented on developer builds of Chrome. We
-  // check for this by checking that the build of Chrome is unbranded.
-  if (chrome::GetChannel() != version_info::Channel::UNKNOWN)
-    return;
-
   extensions::AutomationEventRouter::GetInstance()->DispatchTreeDestroyedEvent(
       ui::AXTreeID::FromToken(tree_id), nullptr);
 }
@@ -70,11 +58,6 @@
 void AutomationAsh::DispatchActionResult(
     const ui::AXActionData& already_handled_action_data,
     bool result) {
-  // This prototype method is only implemented on developer builds of Chrome. We
-  // check for this by checking that the build of Chrome is unbranded.
-  if (chrome::GetChannel() != version_info::Channel::UNKNOWN)
-    return;
-
   extensions::AutomationEventRouter::GetInstance()->DispatchActionResult(
       already_handled_action_data, result);
 }
@@ -86,11 +69,6 @@
                                   const std::string& action_type,
                                   int32_t request_id,
                                   const base::DictionaryValue& optional_args) {
-  // This prototype method is only implemented on developer builds of Chrome. We
-  // check for this by checking that the build of Chrome is unbranded.
-  if (chrome::GetChannel() != version_info::Channel::UNKNOWN)
-    return;
-
   if (!tree_id.token().has_value())
     return;
   for (auto& client : automation_client_remotes_) {
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc
index 7a1e638..b325812 100644
--- a/chrome/browser/autofill/autofill_interactive_uitest.cc
+++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -78,7 +78,6 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/switches.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/events/keycodes/dom_us_layout_data.h"
@@ -269,9 +268,7 @@
 class AutofillInteractiveTestBase : public AutofillUiTest {
  protected:
   AutofillInteractiveTestBase()
-      : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {
-    feature_list_.InitAndEnableFeature(blink::features::kAutofillShadowDOM);
-  }
+      : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
 
  public:
   AutofillInteractiveTestBase(const AutofillInteractiveTestBase&) = delete;
@@ -706,10 +703,7 @@
 
   void TriggerFormFill(const std::string& field_name) {
     FocusFieldByName(field_name);
-    TriggerFormFillAlreadyFocused();
-  }
 
-  void TriggerFormFillAlreadyFocused() {
     // Start filling the first name field with "M" and wait for the popup to be
     // shown.
     SendKeyToPageAndWait(ui::DomKey::FromCharacter('M'), ui::DomCode::US_M,
@@ -776,8 +770,6 @@
 
   // The response to return for queries to |kTestUrlPath|
   std::string test_url_content_;
-
-  base::test::ScopedFeatureList feature_list_;
 };
 
 const char AutofillInteractiveTestBase::kTestUrlPath[] =
@@ -3517,61 +3509,6 @@
   ExpectFieldValue("phone", "15125551234");
 }
 
-IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, ShadowDOM) {
-  CreateTestProfile();
-
-  GURL url =
-      embedded_test_server()->GetURL("a.com", "/autofill/shadowdom.html");
-  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), url));
-
-  bool result = false;
-  ASSERT_TRUE(
-      content::ExecuteScriptAndExtractBool(GetWebContents(),
-                                           R"( function onFocusHandler(e) {
-              e.target.removeEventListener(e.type, arguments.callee);
-              domAutomationController.send(true);
-            }
-            if (document.readyState === 'complete') {
-              var target = getNameElement();
-              target.addEventListener('focus', onFocusHandler);
-              target.focus();
-            } else {
-              domAutomationController.send(false);
-            })",
-                                           &result));
-  ASSERT_TRUE(result);
-  TriggerFormFillAlreadyFocused();
-
-  std::string name;
-  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
-      GetWebContents(), "window.domAutomationController.send(getName())",
-      &name));
-  EXPECT_EQ("Milton C. Waddams", name) << " for field name";
-
-  std::string address;
-  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
-      GetWebContents(), "window.domAutomationController.send(getAddress())",
-      &address));
-  EXPECT_EQ("4120 Freidrich Lane", address) << " for field address";
-
-  std::string city;
-  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
-      GetWebContents(), "window.domAutomationController.send(getCity())",
-      &city));
-  EXPECT_EQ("Austin", city) << " for field city";
-
-  std::string state;
-  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
-      GetWebContents(), "window.domAutomationController.send(getState())",
-      &state));
-  EXPECT_EQ("TX", state) << " for field state";
-
-  std::string zip;
-  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
-      GetWebContents(), "window.domAutomationController.send(getZip())", &zip));
-  EXPECT_EQ("78744", zip) << " for field zip";
-}
-
 INSTANTIATE_TEST_SUITE_P(All,
                          AutofillDynamicFormReplacementInteractiveTest,
                          testing::Bool());
diff --git a/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserStateBrowserControlsVisibilityDelegate.java b/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserStateBrowserControlsVisibilityDelegate.java
index 0f79f6f..c38c915 100644
--- a/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserStateBrowserControlsVisibilityDelegate.java
+++ b/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserStateBrowserControlsVisibilityDelegate.java
@@ -10,6 +10,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.CommandLine;
+import org.chromium.base.lifetime.Destroyable;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.cc.input.BrowserControlsState;
@@ -22,7 +23,7 @@
  * running activity.
  */
 public class BrowserStateBrowserControlsVisibilityDelegate
-        extends BrowserControlsVisibilityDelegate {
+        extends BrowserControlsVisibilityDelegate implements Destroyable {
     /** Minimum duration (in milliseconds) that the controls are shown when requested. */
     @VisibleForTesting
     static final long MINIMUM_SHOW_DURATION_MS = 3000;
@@ -138,6 +139,7 @@
     /**
      * Performs clean-up.
      */
+    @Override
     public void destroy() {
         mHandler.removeCallbacksAndMessages(null);
     }
diff --git a/chrome/browser/buildflags.gni b/chrome/browser/buildflags.gni
index 8c19e70..50e15e4 100644
--- a/chrome/browser/buildflags.gni
+++ b/chrome/browser/buildflags.gni
@@ -22,10 +22,3 @@
   enable_app_session_service =
       !(is_chromeos_lacros || is_chromecast || is_android)
 }
-
-# If true, the resource .pak files will be hashed and the digest will be
-# embedded in the binary and checked at run-time. This is incompatible with
-# enable_resource_allowlist_generation on Windows because it creates a circular
-# dependency with chrome_dll.
-enable_pak_file_integrity_checks =
-    !(enable_resource_allowlist_generation && is_win) && !is_android
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index cf7f295..bfb984bb 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -190,6 +190,7 @@
 #else
 #include "chrome/browser/resource_coordinator/tab_activity_watcher.h"
 #include "chrome/browser/resource_coordinator/tab_manager.h"
+#include "chrome/browser/resources_integrity.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/uma_browsing_activity_observer.h"
@@ -321,10 +322,6 @@
 #include "components/spellcheck/common/spellcheck_features.h"
 #endif  // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER)
 
-#if BUILDFLAG(ENABLE_PAK_FILE_INTEGRITY_CHECKS)
-#include "chrome/browser/resources_integrity.h"
-#endif
-
 namespace {
 
 #if !defined(OS_ANDROID)
@@ -595,6 +592,15 @@
 
 void ChromeBrowserMainParts::SetupOriginTrialsCommandLine(
     PrefService* local_state) {
+  // TODO(crbug.com/1211739): Temporary workaround to prevent an overly large
+  // config from crashing by exceeding command-line length limits. Set the limit
+  // to 1KB, which is far less than the known limits:
+  //  - Linux: kZygoteMaxMessageLength = 12288;
+  // This will still allow for critical updates to the public key or disabled
+  // features, but the disabled token list will be ignored.
+  const size_t kMaxAppendLength = 1024;
+  size_t appended_length = 0;
+
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   if (!command_line->HasSwitch(embedder_support::kOriginTrialPublicKey)) {
     std::string new_public_key =
@@ -604,6 +610,9 @@
           embedder_support::kOriginTrialPublicKey,
           local_state->GetString(
               embedder_support::prefs::kOriginTrialPublicKey));
+
+      // Public key is 32 bytes
+      appended_length += 32;
     }
   }
   if (!command_line->HasSwitch(
@@ -625,6 +634,7 @@
         command_line->AppendSwitchASCII(
             embedder_support::kOriginTrialDisabledFeatures,
             override_disabled_features);
+        appended_length += override_disabled_features.length();
       }
     }
   }
@@ -642,9 +652,14 @@
       if (!disabled_tokens.empty()) {
         const std::string disabled_token_switch =
             base::JoinString(disabled_tokens, "|");
-        command_line->AppendSwitchASCII(
-            embedder_support::kOriginTrialDisabledTokens,
-            disabled_token_switch);
+        // Do not append the disabled token list if will exceed a reasonable
+        // length. See above.
+        if (appended_length + disabled_token_switch.length() <=
+            kMaxAppendLength) {
+          command_line->AppendSwitchASCII(
+              embedder_support::kOriginTrialDisabledTokens,
+              disabled_token_switch);
+        }
       }
     }
   }
@@ -1109,9 +1124,7 @@
   // Start the tab manager here so that we give the most amount of time for the
   // other services to start up before we start adjusting the oom priority.
   g_browser_process->GetTabManager()->Start();
-#endif
 
-#if BUILDFLAG(ENABLE_PAK_FILE_INTEGRITY_CHECKS)
   CheckPakFileIntegrity();
 #endif
 
diff --git a/chrome/browser/data_saver/subresource_redirect_browsertest.cc b/chrome/browser/data_saver/subresource_redirect_browsertest.cc
index 755ec7a..b1897f3f 100644
--- a/chrome/browser/data_saver/subresource_redirect_browsertest.cc
+++ b/chrome/browser/data_saver/subresource_redirect_browsertest.cc
@@ -1338,10 +1338,10 @@
   EXPECT_EQ(GURL(RunScriptExtractString("imageSrc()")).port(),
             https_url().port());
 
-  VerifyCompressibleImageUkm(1);
+  VerifyCompressibleImageUkm(0);
   VerifyIneligibleImageHintsUnavailableUkm(0);
   VerifyIneligibleMissingInImageHintsUkm(0);
-  VerifyIneligibleOtherImageUkm(0);
+  VerifyIneligibleOtherImageUkm(1);
   VerifyImageCompressionPageInfoState(false);
 }
 
@@ -1670,9 +1670,9 @@
       "SubresourceRedirect.DidCompress.CompressionPercent", 0);
 
   WaitForImageCompressionUkmMetrics(1);
-  VerifyCompressibleImageUkm(1);
+  VerifyCompressibleImageUkm(0);
   VerifyIneligibleImageHintsUnavailableUkm(0);
   VerifyIneligibleMissingInImageHintsUkm(0);
-  VerifyIneligibleOtherImageUkm(0);
+  VerifyIneligibleOtherImageUkm(1);
   VerifyImageCompressionPageInfoState(false);
 }
diff --git a/chrome/browser/data_saver/subresource_redirect_login_robots_browsertest.cc b/chrome/browser/data_saver/subresource_redirect_login_robots_browsertest.cc
index f9a87e9..8d6066e 100644
--- a/chrome/browser/data_saver/subresource_redirect_login_robots_browsertest.cc
+++ b/chrome/browser/data_saver/subresource_redirect_login_robots_browsertest.cc
@@ -146,6 +146,24 @@
     return merged_metrics;
   }
 
+  void VerifyRobotsRulesFetch(
+      const std::set<std::string>& expected_robots_requests) {
+    if (!expected_robots_requests.empty()) {
+      histogram_tester_.ExpectBucketCount(
+          "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", net::HTTP_OK,
+          expected_robots_requests.size());
+      histogram_tester_.ExpectBucketCount(
+          "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", false,
+          expected_robots_requests.size());
+    } else {
+      histogram_tester_.ExpectTotalCount(
+          "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", 0);
+      histogram_tester_.ExpectTotalCount(
+          "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", 0);
+    }
+    robots_rules_server_.VerifyRequestedOrigins(expected_robots_requests);
+  }
+
  protected:
   bool enable_lite_mode_;
   bool enable_login_robots_compression_feature_;
@@ -219,14 +237,10 @@
       net::HTTP_TEMPORARY_REDIRECT, 1);
   histogram_tester_.ExpectUniqueSample(
       "SubresourceRedirect.CompressionAttempt.ServerResponded", true, 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", net::HTTP_OK, 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", false, 1);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
 
-  robots_rules_server_.VerifyRequestedOrigins({GetHttpsTestURL("/").spec()});
+  VerifyRobotsRulesFetch({GetHttpsTestURL("/").spec()});
   image_compression_server_.VerifyRequestedImagePaths(
       {"/load_image/image.png"});
 
@@ -272,14 +286,10 @@
       net::HTTP_TEMPORARY_REDIRECT, 1);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.CompressionAttempt.ServerResponded", 0);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", net::HTTP_OK, 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", false, 1);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
 
-  robots_rules_server_.VerifyRequestedOrigins({GetHttpsTestURL("/").spec()});
+  VerifyRobotsRulesFetch({GetHttpsTestURL("/").spec()});
   image_compression_server_.VerifyRequestedImagePaths({});
 
   using ImageCompressionUkm = ukm::builders::PublicImageCompressionImageLoad;
@@ -326,13 +336,9 @@
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.CompressionAttempt.ServerResponded", 0);
   histogram_tester_.ExpectTotalCount(
-      "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", 0);
-  histogram_tester_.ExpectTotalCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", 0);
-  histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
 
-  robots_rules_server_.VerifyRequestedOrigins({});
+  VerifyRobotsRulesFetch({});
   image_compression_server_.VerifyRequestedImagePaths({});
   VerifyImageCompressionPageInfoState(false);
 }
@@ -353,13 +359,9 @@
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.CompressionAttempt.ServerResponded", 0);
   histogram_tester_.ExpectTotalCount(
-      "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", 0);
-  histogram_tester_.ExpectTotalCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", 0);
-  histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
 
-  robots_rules_server_.VerifyRequestedOrigins({});
+  VerifyRobotsRulesFetch({});
   image_compression_server_.VerifyRequestedImagePaths({});
   VerifyImageCompressionPageInfoState(false);
 }
@@ -387,17 +389,13 @@
   RetryForHistogramUntilCountReached(
       &histogram_tester_, "SubresourceRedirect.RobotsRulesFetcher.ResponseCode",
       1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", net::HTTP_OK, 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", false, 1);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
   histogram_tester_.ExpectUniqueSample(
       "SubresourceRedirect.LoginRobotsDeciderAgent.RedirectResult",
       SubresourceRedirectResult::kIneligibleRobotsTimeout, 1);
 
-  robots_rules_server_.VerifyRequestedOrigins({GetHttpsTestURL("/").spec()});
+  VerifyRobotsRulesFetch({GetHttpsTestURL("/").spec()});
   image_compression_server_.VerifyRequestedImagePaths({});
 
   using ImageCompressionUkm = ukm::builders::PublicImageCompressionImageLoad;
@@ -444,14 +442,10 @@
       net::HTTP_TEMPORARY_REDIRECT, 2);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.CompressionAttempt.ServerResponded", 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", net::HTTP_OK, 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", false, 1);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
 
-  robots_rules_server_.VerifyRequestedOrigins({GetHttpsTestURL("/").spec()});
+  VerifyRobotsRulesFetch({GetHttpsTestURL("/").spec()});
   image_compression_server_.VerifyRequestedImagePaths(
       {"/load_image/image.png"});
   VerifyImageCompressionPageInfoState(true);
@@ -474,14 +468,10 @@
       net::HTTP_TEMPORARY_REDIRECT, 2);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.CompressionAttempt.ServerResponded", 2);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", net::HTTP_OK, 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", false, 1);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
 
-  robots_rules_server_.VerifyRequestedOrigins({GetHttpsTestURL("/").spec()});
+  VerifyRobotsRulesFetch({GetHttpsTestURL("/").spec()});
   image_compression_server_.VerifyRequestedImagePaths(
       {"/load_image/image.png", "/load_image/image.png?foo"});
   VerifyImageCompressionPageInfoState(true);
@@ -506,10 +496,8 @@
       net::HTTP_TEMPORARY_REDIRECT, 1);
   histogram_tester_.ExpectUniqueSample(
       "SubresourceRedirect.CompressionAttempt.ServerResponded", true, 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", false, 1);
 
-  robots_rules_server_.VerifyRequestedOrigins({GetHttpsTestURL("/").spec()});
+  VerifyRobotsRulesFetch({GetHttpsTestURL("/").spec()});
   image_compression_server_.VerifyRequestedImagePaths(
       {"/load_image/image.png"});
 
@@ -554,10 +542,8 @@
       "SubresourceRedirect.CompressionAttempt.ServerResponded", true, 1);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.RobotRulesDecider.ApplyDuration", 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", false, 1);
 
-  robots_rules_server_.VerifyRequestedOrigins({GetHttpsTestURL("/").spec()});
+  VerifyRobotsRulesFetch({GetHttpsTestURL("/").spec()});
   image_compression_server_.VerifyRequestedImagePaths(
       {"/load_image/image.png"});
 
@@ -583,9 +569,7 @@
       "SubresourceRedirect.RobotRulesDecider.ApplyDuration", 2);
 
   // Another robots rules fetch happened.
-  histogram_tester_.ExpectTotalCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", 2);
-  robots_rules_server_.VerifyRequestedOrigins(
+  VerifyRobotsRulesFetch(
       {GetHttpsTestURL("/").spec(),
        https_test_server_.GetURL("differentorigin.com", "/").spec()});
   image_compression_server_.VerifyRequestedImagePaths(
@@ -682,10 +666,6 @@
   NavigateAndWaitForLoad(browser(), GetHttpsTestURL("/load_image/image.html"));
 
   // Robots rules fetch was success.
-  histogram_tester_.ExpectUniqueSample(
-      "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", net::HTTP_OK, 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", false, 1);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.RobotRulesDecider.ApplyDuration", 1);
 
@@ -707,7 +687,7 @@
   histogram_tester_.ExpectBucketCount(
       "SubresourceRedirect.LitePagesService.BypassResult", false, 2);
 
-  robots_rules_server_.VerifyRequestedOrigins({GetHttpsTestURL("/").spec()});
+  VerifyRobotsRulesFetch({GetHttpsTestURL("/").spec()});
   image_compression_server_.VerifyRequestedImagePaths(
       {"/load_image/image.png"});
 
@@ -727,12 +707,10 @@
       "SubresourceRedirect.CompressionAttempt.ServerResponded", 0);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.RobotRulesDecider.ApplyDuration", 1);
-  histogram_tester_.ExpectTotalCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", 1);
   EXPECT_TRUE(RunScriptExtractBool("checkImage()"));
 
   // No more additional fetches.
-  robots_rules_server_.VerifyRequestedOrigins({GetHttpsTestURL("/").spec()});
+  VerifyRobotsRulesFetch({GetHttpsTestURL("/").spec()});
   image_compression_server_.VerifyRequestedImagePaths(
       {"/load_image/image.png"});
   VerifyImageCompressionPageInfoState(true);
@@ -777,13 +755,9 @@
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.CompressionAttempt.ServerResponded", 0);
   histogram_tester_.ExpectTotalCount(
-      "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", 0);
-  histogram_tester_.ExpectTotalCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", 0);
-  histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
 
-  robots_rules_server_.VerifyRequestedOrigins({});
+  VerifyRobotsRulesFetch({});
   image_compression_server_.VerifyRequestedImagePaths({});
   VerifyImageCompressionPageInfoState(false);
 }
@@ -813,14 +787,10 @@
       "SubresourceRedirect.CompressionAttempt.ServerResponded", true, 2);
   // The robots rules are fetched once, since both images are from the same
   // origin.
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", net::HTTP_OK, 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", false, 1);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
 
-  robots_rules_server_.VerifyRequestedOrigins({GetHttpsTestURL("/").spec()});
+  VerifyRobotsRulesFetch({GetHttpsTestURL("/").spec()});
   image_compression_server_.VerifyRequestedImagePaths(
       {"/load_image/image.png?mainframe", "/load_image/image.png"});
   VerifyImageCompressionPageInfoState(true);
@@ -855,16 +825,11 @@
       net::HTTP_TEMPORARY_REDIRECT, 2);
   histogram_tester_.ExpectUniqueSample(
       "SubresourceRedirect.CompressionAttempt.ServerResponded", true, 2);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", net::HTTP_OK, 2);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", false, 2);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
 
-  robots_rules_server_.VerifyRequestedOrigins(
-      {GetHttpsTestURL("/").spec(),
-       https_test_server_.GetURL("foo.com", "/").spec()});
+  VerifyRobotsRulesFetch({GetHttpsTestURL("/").spec(),
+                          https_test_server_.GetURL("foo.com", "/").spec()});
   image_compression_server_.VerifyRequestedImagePaths(
       {"/load_image/image.png?mainframe", "/load_image/image.png"});
   VerifyImageCompressionPageInfoState(true);
@@ -904,14 +869,10 @@
       net::HTTP_TEMPORARY_REDIRECT, 1);
   histogram_tester_.ExpectUniqueSample(
       "SubresourceRedirect.CompressionAttempt.ServerResponded", true, 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", net::HTTP_OK, 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", false, 1);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
 
-  robots_rules_server_.VerifyRequestedOrigins({GetHttpsTestURL("/").spec()});
+  VerifyRobotsRulesFetch({GetHttpsTestURL("/").spec()});
   image_compression_server_.VerifyRequestedImagePaths(
       {"/load_image/image.png?mainframe"});
   // Main frame still enables image compression.
@@ -944,13 +905,9 @@
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.CompressionAttempt.ServerResponded", 0);
   histogram_tester_.ExpectTotalCount(
-      "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", 0);
-  histogram_tester_.ExpectTotalCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", 0);
-  histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
 
-  robots_rules_server_.VerifyRequestedOrigins({});
+  VerifyRobotsRulesFetch({});
   image_compression_server_.VerifyRequestedImagePaths({});
   VerifyImageCompressionPageInfoState(false);
 }
@@ -1028,10 +985,6 @@
   RetryForHistogramUntilCountReached(
       &histogram_tester_, "SubresourceRedirect.RobotsRulesFetcher.ResponseCode",
       1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", net::HTTP_OK, 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", false, 1);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
   histogram_tester_.ExpectTotalCount(
@@ -1043,7 +996,7 @@
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.CompressionAttempt.ServerResponded", 0);
 
-  robots_rules_server_.VerifyRequestedOrigins({GetHttpsTestURL("/").spec()});
+  VerifyRobotsRulesFetch({GetHttpsTestURL("/").spec()});
   image_compression_server_.VerifyRequestedImagePaths({});
 
   // Now start loading the image.
@@ -1064,14 +1017,10 @@
       net::HTTP_TEMPORARY_REDIRECT, 1);
   histogram_tester_.ExpectUniqueSample(
       "SubresourceRedirect.CompressionAttempt.ServerResponded", true, 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", net::HTTP_OK, 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", false, 1);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
 
-  robots_rules_server_.VerifyRequestedOrigins({GetHttpsTestURL("/").spec()});
+  VerifyRobotsRulesFetch({GetHttpsTestURL("/").spec()});
   image_compression_server_.VerifyRequestedImagePaths(
       {"/load_image/image.png"});
 }
@@ -1131,13 +1080,9 @@
     histogram_tester_.ExpectTotalCount(
         "SubresourceRedirect.CompressionAttempt.ServerResponded", 0);
     histogram_tester_.ExpectTotalCount(
-        "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", 0);
-    histogram_tester_.ExpectTotalCount(
-        "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", 0);
-    histogram_tester_.ExpectTotalCount(
         "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
 
-    robots_rules_server_.VerifyRequestedOrigins({});
+    VerifyRobotsRulesFetch({});
     image_compression_server_.VerifyRequestedImagePaths({});
     VerifyImageCompressionPageInfoState(false);
     return;
@@ -1153,14 +1098,10 @@
       net::HTTP_TEMPORARY_REDIRECT, 1);
   histogram_tester_.ExpectUniqueSample(
       "SubresourceRedirect.CompressionAttempt.ServerResponded", true, 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", net::HTTP_OK, 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", false, 1);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
 
-  robots_rules_server_.VerifyRequestedOrigins({GetHttpsTestURL("/").spec()});
+  VerifyRobotsRulesFetch({GetHttpsTestURL("/").spec()});
   image_compression_server_.VerifyRequestedImagePaths(
       {"/load_image/image.png"});
 
@@ -1230,14 +1171,10 @@
       net::HTTP_TEMPORARY_REDIRECT, 1);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.CompressionAttempt.ServerResponded", 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", net::HTTP_OK, 1);
-  histogram_tester_.ExpectBucketCount(
-      "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", false, 1);
   histogram_tester_.ExpectTotalCount(
       "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
 
-  robots_rules_server_.VerifyRequestedOrigins({GetHttpsTestURL("/").spec()});
+  VerifyRobotsRulesFetch({GetHttpsTestURL("/").spec()});
   image_compression_server_.VerifyRequestedImagePaths(
       {"/load_image/image.png?foo"});
   VerifyImageCompressionPageInfoState(true);
@@ -1306,11 +1243,8 @@
         net::HTTP_TEMPORARY_REDIRECT, 1);
     histogram_tester_.ExpectUniqueSample(
         "SubresourceRedirect.CompressionAttempt.ServerResponded", true, 1);
-    histogram_tester_.ExpectUniqueSample(
-        "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", false, 1);
 
-    robots_rules_server_.VerifyRequestedOrigins(
-        {image_url.GetWithEmptyPath().spec()});
+    VerifyRobotsRulesFetch({image_url.GetWithEmptyPath().spec()});
     image_compression_server_.VerifyRequestedImagePaths(
         {"/load_image/image.png"});
   } else {
@@ -1320,12 +1254,8 @@
         "SubresourceRedirect.CompressionAttempt.ResponseCode", 0);
     histogram_tester_.ExpectTotalCount(
         "SubresourceRedirect.CompressionAttempt.ServerResponded", 0);
-    histogram_tester_.ExpectTotalCount(
-        "SubresourceRedirect.RobotsRulesFetcher.ResponseCode", 0);
-    histogram_tester_.ExpectTotalCount(
-        "SubresourceRedirect.RobotsRules.Browser.InMemoryCacheHit", 0);
 
-    robots_rules_server_.VerifyRequestedOrigins({});
+    VerifyRobotsRulesFetch({});
     image_compression_server_.VerifyRequestedImagePaths({});
   }
   histogram_tester_.ExpectTotalCount(
@@ -1366,4 +1296,115 @@
     testing::Combine(testing::Bool() /* allow_javascript_crossorigin_images */,
                      testing::Bool() /* is_crossorigin_image */));
 
+// Disables the actual subresource redirect and enables only recording metrics.
+class SubresourceRedirectLoginRobotsRedirectDisabledBrowserTest
+    : public SubresourceRedirectLoginRobotsBrowserTest {
+ public:
+  SubresourceRedirectLoginRobotsRedirectDisabledBrowserTest()
+      : SubresourceRedirectLoginRobotsBrowserTest(
+            {{"enable_subresource_server_redirect", "false"}},
+            true, /* enable_lite_mode */
+            true  /* enable_login_robots_compression_feature */
+        ) {}
+};
+
+IN_PROC_BROWSER_TEST_F(
+    SubresourceRedirectLoginRobotsRedirectDisabledBrowserTest,
+    DISABLE_ON_WIN_MAC_CHROMEOS(TestImageAllowedByRobots)) {
+  CreateUkmRecorder();
+  robots_rules_server_.AddRobotsRules(
+      GetHttpsTestURL("/"),
+      {{kRuleTypeAllow, "/load_image/image.png"}, {kRuleTypeDisallow, ""}});
+  NavigateAndWaitForLoad(browser(), GetHttpsTestURL("/load_image/image.html"));
+
+  VerifyRobotsRulesFetch({GetHttpsTestURL("/").spec()});
+
+  // The image will start redirect and pause when robots rules are getting
+  // fetched. But there will not be an actual redirect.
+  histogram_tester_.ExpectUniqueSample(
+      "SubresourceRedirect.CompressionAttempt.ResponseCode",
+      net::HTTP_TEMPORARY_REDIRECT, 1);
+  histogram_tester_.ExpectUniqueSample(
+      "SubresourceRedirect.LoginRobotsDeciderAgent.RedirectResult",
+      SubresourceRedirectResult::kIneligibleCompressionDisabled, 1);
+  histogram_tester_.ExpectTotalCount(
+      "SubresourceRedirect.CompressionAttempt.ServerResponded", 0);
+  histogram_tester_.ExpectTotalCount(
+      "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
+  image_compression_server_.VerifyRequestedImagePaths({});
+
+  // Image load UKM should get recorded.
+  using ImageCompressionUkm = ukm::builders::PublicImageCompressionImageLoad;
+  auto ukm_metrics = GetImageCompressionUkmMetrics();
+  EXPECT_LT(100U, ukm_metrics[ImageCompressionUkm::kOriginalBytesNameHash]);
+  EXPECT_THAT(ukm_metrics,
+              testing::Not(testing::Contains(testing::Key(
+                  ImageCompressionUkm::kCompressionPercentageNameHash))));
+  EXPECT_THAT(ukm_metrics,
+              testing::Contains(testing::Key(
+                  ImageCompressionUkm::kNavigationToRequestStartNameHash)));
+  EXPECT_THAT(ukm_metrics,
+              testing::Contains(testing::Key(
+                  ImageCompressionUkm::kNavigationToRequestSentNameHash)));
+  EXPECT_THAT(ukm_metrics,
+              testing::Contains(testing::Key(
+                  ImageCompressionUkm::kNavigationToResponseReceivedNameHash)));
+  EXPECT_THAT(ukm_metrics,
+              testing::Contains(testing::Key(
+                  ImageCompressionUkm::kRobotsRulesFetchLatencyNameHash)));
+  EXPECT_EQ(SubresourceRedirectResult::kIneligibleCompressionDisabled,
+            static_cast<SubresourceRedirectResult>(
+                ukm_metrics[ImageCompressionUkm::kRedirectResultNameHash]));
+  VerifyImageCompressionPageInfoState(false);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    SubresourceRedirectLoginRobotsRedirectDisabledBrowserTest,
+    DISABLE_ON_WIN_MAC_CHROMEOS(TestImageDisallowedByRobots)) {
+  CreateUkmRecorder();
+  robots_rules_server_.AddRobotsRules(GetHttpsTestURL("/"),
+                                      {{kRuleTypeDisallow, ""}});
+  NavigateAndWaitForLoad(browser(), GetHttpsTestURL("/load_image/image.html"));
+
+  VerifyRobotsRulesFetch({GetHttpsTestURL("/").spec()});
+
+  // The image will start redirect and pause when robots rules are getting
+  // fetched. But there will not be an actual redirect.
+  histogram_tester_.ExpectUniqueSample(
+      "SubresourceRedirect.CompressionAttempt.ResponseCode",
+      net::HTTP_TEMPORARY_REDIRECT, 1);
+  histogram_tester_.ExpectUniqueSample(
+      "SubresourceRedirect.LoginRobotsDeciderAgent.RedirectResult",
+      SubresourceRedirectResult::kIneligibleRobotsDisallowed, 1);
+  histogram_tester_.ExpectTotalCount(
+      "SubresourceRedirect.CompressionAttempt.ServerResponded", 0);
+  histogram_tester_.ExpectTotalCount(
+      "SubresourceRedirect.ImageCompressionNotificationInfoBar", 0);
+  image_compression_server_.VerifyRequestedImagePaths({});
+
+  // Image load UKM should get recorded.
+  using ImageCompressionUkm = ukm::builders::PublicImageCompressionImageLoad;
+  auto ukm_metrics = GetImageCompressionUkmMetrics();
+  EXPECT_LT(100U, ukm_metrics[ImageCompressionUkm::kOriginalBytesNameHash]);
+  EXPECT_THAT(ukm_metrics,
+              testing::Not(testing::Contains(testing::Key(
+                  ImageCompressionUkm::kCompressionPercentageNameHash))));
+  EXPECT_THAT(ukm_metrics,
+              testing::Contains(testing::Key(
+                  ImageCompressionUkm::kNavigationToRequestStartNameHash)));
+  EXPECT_THAT(ukm_metrics,
+              testing::Contains(testing::Key(
+                  ImageCompressionUkm::kNavigationToRequestSentNameHash)));
+  EXPECT_THAT(ukm_metrics,
+              testing::Contains(testing::Key(
+                  ImageCompressionUkm::kNavigationToResponseReceivedNameHash)));
+  EXPECT_THAT(ukm_metrics,
+              testing::Contains(testing::Key(
+                  ImageCompressionUkm::kRobotsRulesFetchLatencyNameHash)));
+  EXPECT_EQ(SubresourceRedirectResult::kIneligibleRobotsDisallowed,
+            static_cast<SubresourceRedirectResult>(
+                ukm_metrics[ImageCompressionUkm::kRedirectResultNameHash]));
+  VerifyImageCompressionPageInfoState(false);
+}
+
 }  // namespace subresource_redirect
diff --git a/chrome/browser/extensions/api/storage/settings_apitest.cc b/chrome/browser/extensions/api/storage/settings_apitest.cc
index 81c551a..dbf4becf 100644
--- a/chrome/browser/extensions/api/storage/settings_apitest.cc
+++ b/chrome/browser/extensions/api/storage/settings_apitest.cc
@@ -328,16 +328,16 @@
   for (const StorageAreaNamespace& storage_area : storage_areas) {
     ReplyWhenSatisfied(storage_area, "assertEmpty", "assertEmpty");
     ReplyWhenSatisfied(storage_area, "noop", "setFoo");
+    ReplyWhenSatisfied(storage_area, "assertFoo", "assertFoo");
+    ReplyWhenSatisfied(storage_area, "clear", "noop");
     // TODO(crbug.com/1185226): Move this condition accordingly as `session`
     // SettingFunction's are implemented. Currently it skips the
     // functions that `session` has not implemented yet. When all functions are
     // implemented, FinalReplyWhenSatisfied() will be moved outside the loop.
     if (storage_area == StorageAreaNamespace::kSession) {
-      FinalReplyWhenSatisfied(storage_area, "assertFoo", "assertFoo");
+      FinalReplyWhenSatisfied(storage_area, "assertEmpty", "assertEmpty");
       break;
     }
-    ReplyWhenSatisfied(storage_area, "assertFoo", "assertFoo");
-    ReplyWhenSatisfied(storage_area, "clear", "noop");
     ReplyWhenSatisfied(storage_area, "assertEmpty", "assertEmpty");
     ReplyWhenSatisfied(storage_area, "setFoo", "noop");
     ReplyWhenSatisfied(storage_area, "assertFoo", "assertFoo");
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
index 527193d..d75cdaf 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
@@ -414,7 +414,6 @@
   web_navigation_api_helpers::DispatchOnErrorOccurred(navigation_handle);
 }
 
-// See also NavigationController::IsURLSameDocumentNavigation.
 bool WebNavigationTabObserver::IsReferenceFragmentNavigation(
     content::RenderFrameHost* render_frame_host,
     const GURL& url) {
diff --git a/chrome/browser/extensions/extension_cookies_browsertest.cc b/chrome/browser/extensions/extension_cookies_browsertest.cc
index f45e890b..2963e5a 100644
--- a/chrome/browser/extensions/extension_cookies_browsertest.cc
+++ b/chrome/browser/extensions/extension_cookies_browsertest.cc
@@ -22,7 +22,9 @@
 #include "chrome/common/extensions/extension_test_util.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "components/content_settings/core/common/content_settings.h"
 #include "components/network_session_configurator/common/network_switches.h"
+#include "content/public/browser/storage_partition.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
@@ -32,6 +34,7 @@
 #include "extensions/common/value_builder.h"
 #include "extensions/test/extension_test_message_listener.h"
 #include "extensions/test/test_extension_dir.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "net/base/features.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/http/http_request_headers.h"
@@ -39,6 +42,7 @@
 #include "net/test/embedded_test_server/default_handlers.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "services/network/public/cpp/network_switches.h"
+#include "services/network/public/mojom/cookie_manager.mojom.h"
 #include "testing/gmock/include/gmock/gmock-matchers.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest-param-test.h"
@@ -333,27 +337,41 @@
 //     URL and also the extension has access to it.
 // See URLLoader::ShouldForceIgnoreSiteForCookies().
 //
-// The test fixture param is whether or not the new SameSite features are
-// enabled.
+// The test fixture param is whether or not legacy SameSite semantics are
+// enabled (i.e, whether SameSite-by-default cookies and SameSite=None
+// requires Secure are disabled).
 class ExtensionSameSiteCookiesTest
     : public ExtensionCookiesTest,
       public ::testing::WithParamInterface<bool> {
  public:
-  ExtensionSameSiteCookiesTest() {
-    std::vector<base::Feature> samesite_features = {
-        net::features::kSameSiteByDefaultCookies,
-        net::features::kCookiesWithoutSameSiteMustBeSecure};
-    if (AreSameSiteFeaturesEnabled()) {
-      feature_list_.InitWithFeatures(samesite_features /* enabled */, {});
-    } else {
-      feature_list_.InitWithFeatures({}, samesite_features /* disabled */);
-    }
-  }
+  ExtensionSameSiteCookiesTest() = default;
   ~ExtensionSameSiteCookiesTest() override = default;
   ExtensionSameSiteCookiesTest(const ExtensionSameSiteCookiesTest&) = delete;
   ExtensionSameSiteCookiesTest& operator=(const ExtensionSameSiteCookiesTest&) =
       delete;
 
+  void SetUpOnMainThread() override {
+    ExtensionCookiesTest::SetUpOnMainThread();
+
+    // If SameSite access semantics is "legacy", add content settings to allow
+    // legacy access for all sites.
+    if (HasLegacySameSiteAccessSemantics()) {
+      browser()
+          ->profile()
+          ->GetDefaultStoragePartition()
+          ->GetNetworkContext()
+          ->GetCookieManager(
+              cookie_manager_remote_.BindNewPipeAndPassReceiver());
+      cookie_manager_remote_->SetContentSettingsForLegacyCookieAccess(
+          {ContentSettingPatternSource(
+              ContentSettingsPattern::Wildcard(),
+              ContentSettingsPattern::Wildcard(),
+              base::Value(ContentSetting::CONTENT_SETTING_ALLOW),
+              /*source=*/std::string(), /*incognito=*/false)});
+      cookie_manager_remote_.FlushForTesting();
+    }
+  }
+
  protected:
   // Sets an array of cookies with various SameSite values.
   void SetCookies(const std::string& host) {
@@ -377,7 +395,7 @@
   // Expect that only cookies without SameSite are present.
   void ExpectNoSameSiteCookies(const std::string& cookie_header) {
     std::vector<std::string> expected = {kNoneCookie};
-    if (!AreSameSiteFeaturesEnabled()) {
+    if (HasLegacySameSiteAccessSemantics()) {
       expected.push_back(kUnspecifiedCookie);
     }
     EXPECT_THAT(AsCookies(cookie_header),
@@ -389,7 +407,10 @@
         {kPermissionPattern1, kPermissionPattern1Sub, kPermissionPattern2});
   }
 
-  bool AreSameSiteFeaturesEnabled() { return GetParam(); }
+  bool HasLegacySameSiteAccessSemantics() { return GetParam(); }
+
+ private:
+  mojo::Remote<network::mojom::CookieManager> cookie_manager_remote_;
 };
 
 // Tests where the extension page initiates the request.
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index a146c5f..7d4975067 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -1375,6 +1375,9 @@
   { key::kInsecureFormsWarningsEnabled,
     prefs::kMixedFormsWarningsEnabled,
     base::Value::Type::BOOLEAN },
+  { key::kLockIconInAddressBarEnabled,
+    omnibox::kLockIconInAddressBarEnabled,
+    base::Value::Type::BOOLEAN},
   { key::kLookalikeWarningAllowlistDomains,
     prefs::kLookalikeWarningAllowlistDomains,
     base::Value::Type::LIST },
diff --git a/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc b/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc
index 306bef2..244b82c 100644
--- a/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc
+++ b/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc
@@ -84,6 +84,8 @@
  public:
   TabActivityWatcherTest() = default;
   // Reset TabActivityWatcher with given |params|.
+  // This should only be called from test constructors, to avoid tsan data races
+  // with the  FeatureList.
   void SetParams(const base::FieldTrialParams& params) {
     feature_list_.InitAndEnableFeatureWithParameters(features::kTabRanker,
                                                      params);
@@ -119,9 +121,14 @@
   DISALLOW_COPY_AND_ASSIGN(TabActivityWatcherTest);
 };
 
+class TabActivityWatcherScorerType0Test : public TabActivityWatcherTest {
+ public:
+  TabActivityWatcherScorerType0Test() { SetParams({{"scorer_type", "0"}}); }
+};
+
 // Test that lifecycleunits are sorted with high activation score first order.
-TEST_F(TabActivityWatcherTest, LogAndMaybeSortLifecycleUnitWithTabRanker) {
-  SetParams({{"scorer_type", "0"}});
+TEST_F(TabActivityWatcherScorerType0Test,
+       LogAndMaybeSortLifecycleUnitWithTabRanker) {
   Browser::CreateParams params(profile(), true);
   std::unique_ptr<Browser> browser =
       CreateBrowserWithTestWindowForParams(params);
@@ -145,9 +152,13 @@
   tab_strip_model->CloseAllTabs();
 }
 
+class TabActivityWatcherScorerType3Test : public TabActivityWatcherTest {
+ public:
+  TabActivityWatcherScorerType3Test() { SetParams({{"scorer_type", "3"}}); }
+};
+
 // Test that lifecycleunits are sorted with high frecency score first order.
-TEST_F(TabActivityWatcherTest, SortLifecycleUnitWithFrecencyScorer) {
-  SetParams({{"scorer_type", "3"}});
+TEST_F(TabActivityWatcherScorerType3Test, SortLifecycleUnitWithFrecencyScorer) {
   Browser::CreateParams params(profile(), true);
   std::unique_ptr<Browser> browser =
       CreateBrowserWithTestWindowForParams(params);
@@ -181,8 +192,7 @@
 }
 
 // Test that frecency scores are calculated correctly.
-TEST_F(TabActivityWatcherTest, GetFrecencyScore) {
-  SetParams({{"scorer_type", "3"}});
+TEST_F(TabActivityWatcherScorerType3Test, GetFrecencyScore) {
   Browser::CreateParams params(profile(), true);
   std::unique_ptr<Browser> browser =
       CreateBrowserWithTestWindowForParams(params);
@@ -218,11 +228,17 @@
   tab_strip_model->CloseAllTabs();
 }
 
+class TabActiveWatcherDisableBackgroundLogTest : public TabActivityWatcherTest {
+ public:
+  TabActiveWatcherDisableBackgroundLogTest() {
+    SetParams({{"disable_background_log_with_TabRanker", "true"}});
+  }
+};
+
 // Test that lifecycleunits are correctly logged inside
 // LogAndMaybeSortLifecycleUnitWithTabRanker.
-TEST_F(TabActivityWatcherTest,
+TEST_F(TabActiveWatcherDisableBackgroundLogTest,
        LogInsideLogAndMaybeSortLifecycleUnitWithTabRanker) {
-  SetParams({{"disable_background_log_with_TabRanker", "true"}});
   Browser::CreateParams params(profile(), true);
   std::unique_ptr<Browser> browser =
       CreateBrowserWithTestWindowForParams(params);
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc
index fc13049..5704966 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc
@@ -305,6 +305,13 @@
   lifecycle_unit->SetRecentlyAudible(audible_helper->WasRecentlyAudible());
 }
 
+
+void TabLifecycleUnitSource::OnBrowserRemoved(Browser* browser) {
+  // An active browser may be removed without OnBrowserNoLongerActive() being
+  // invoked. crbug.com/1206458
+  UpdateFocusedTab();
+}
+
 void TabLifecycleUnitSource::OnBrowserSetLastActive(Browser* browser) {
   UpdateFocusedTab();
 }
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.h b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.h
index 7f1c67c..8ad0b71 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.h
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.h
@@ -112,6 +112,7 @@
                     TabChangeType change_type) override;
 
   // BrowserListObserver:
+  void OnBrowserRemoved(Browser* browser) override;
   void OnBrowserSetLastActive(Browser* browser) override;
   void OnBrowserNoLongerActive(Browser* browser) override;
 
diff --git a/chrome/browser/resources_integrity.cc b/chrome/browser/resources_integrity.cc
index aaec1a9..4a4a1667 100644
--- a/chrome/browser/resources_integrity.cc
+++ b/chrome/browser/resources_integrity.cc
@@ -6,6 +6,12 @@
 
 #include <array>
 
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
 #include "base/bind.h"
 #include "base/files/file.h"
 #include "base/memory/page_size.h"
@@ -16,9 +22,11 @@
 #include "chrome/common/chrome_paths.h"
 #include "crypto/secure_hash.h"
 
-#if BUILDFLAG(ENABLE_PAK_FILE_INTEGRITY_CHECKS)
-#include "chrome/app/packed_resources_integrity.h"
-#endif
+#if defined(OS_WIN)
+#include "chrome/app/chrome_exe_main_win.h"
+#else
+#include "chrome/app/packed_resources_integrity.h"  // nogncheck
+#endif                                              // defined(OS_WIN)
 
 namespace {
 
@@ -50,11 +58,9 @@
   return base::ranges::equal(digest, expected_signature);
 }
 
-#if BUILDFLAG(ENABLE_PAK_FILE_INTEGRITY_CHECKS)
 void ReportPakIntegrity(const std::string& histogram_name, bool hash_matches) {
   base::UmaHistogramBoolean(histogram_name, hash_matches);
 }
-#endif
 
 }  // namespace
 
@@ -70,23 +76,55 @@
       std::move(callback));
 }
 
-#if BUILDFLAG(ENABLE_PAK_FILE_INTEGRITY_CHECKS)
 void CheckPakFileIntegrity() {
   base::FilePath resources_pack_path;
   base::PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path);
 
-  CheckResourceIntegrity(resources_pack_path, kSha256_resources_pak,
+  // On Windows, the hashes cannot be embedded in the chrome.dll target that
+  // this file is a part of, because it creates a cyclic build dependency
+  // with the Grit resource allow-list generation. Instead, the hashes are
+  // embedded in chrome.exe, which provides an exported function to
+  // access them.
+#if defined(OS_WIN)
+  auto get_pak_file_hashes = reinterpret_cast<decltype(&GetPakFileHashes)>(
+      ::GetProcAddress(::GetModuleHandle(nullptr), "GetPakFileHashes"));
+  if (!get_pak_file_hashes) {
+    // This is only exported by chrome.exe and unit_tests.exe, so in
+    // other tests, like browser_tests.exe, this export will not be available.
+    return;
+  }
+
+  const uint8_t *resources_hash_raw = nullptr, *chrome_100_hash_raw = nullptr,
+                *chrome_200_hash_raw = nullptr;
+  get_pak_file_hashes(&resources_hash_raw, &chrome_100_hash_raw,
+                      &chrome_200_hash_raw);
+
+  base::span<const uint8_t, crypto::kSHA256Length> resources_hash(
+      resources_hash_raw, crypto::kSHA256Length);
+  base::span<const uint8_t, crypto::kSHA256Length> chrome_100_hash(
+      chrome_100_hash_raw, crypto::kSHA256Length);
+  base::span<const uint8_t, crypto::kSHA256Length> chrome_200_hash(
+      chrome_200_hash_raw, crypto::kSHA256Length);
+#else
+  base::span<const uint8_t, crypto::kSHA256Length> resources_hash =
+      kSha256_resources_pak;
+  base::span<const uint8_t, crypto::kSHA256Length> chrome_100_hash =
+      kSha256_chrome_100_percent_pak;
+  base::span<const uint8_t, crypto::kSHA256Length> chrome_200_hash =
+      kSha256_chrome_200_percent_pak;
+#endif  // defined(OS_WIN)
+
+  CheckResourceIntegrity(resources_pack_path, resources_hash,
                          base::BindOnce(&ReportPakIntegrity,
                                         "SafeBrowsing.PakIntegrity.Resources"));
   CheckResourceIntegrity(
       resources_pack_path.DirName().AppendASCII("chrome_100_percent.pak"),
-      kSha256_chrome_100_percent_pak,
+      chrome_100_hash,
       base::BindOnce(&ReportPakIntegrity,
                      "SafeBrowsing.PakIntegrity.Chrome100"));
   CheckResourceIntegrity(
       resources_pack_path.DirName().AppendASCII("chrome_200_percent.pak"),
-      kSha256_chrome_200_percent_pak,
+      chrome_200_hash,
       base::BindOnce(&ReportPakIntegrity,
                      "SafeBrowsing.PakIntegrity.Chrome200"));
 }
-#endif
diff --git a/chrome/browser/resources_integrity.h b/chrome/browser/resources_integrity.h
index 12e0a97..2ae8aa1 100644
--- a/chrome/browser/resources_integrity.h
+++ b/chrome/browser/resources_integrity.h
@@ -19,11 +19,9 @@
     const base::span<const uint8_t, crypto::kSHA256Length> expected_signature,
     base::OnceCallback<void(bool)> callback);
 
-#if BUILDFLAG(ENABLE_PAK_FILE_INTEGRITY_CHECKS)
 // Checks the main Chrome .pak files for corruption by calling
 // CheckResourceIntegrity(), using hashes generated from the
 // GN target //chrome:packed_resources_integrity.
 void CheckPakFileIntegrity();
-#endif
 
 #endif  // CHROME_BROWSER_RESOURCES_INTEGRITY_H_
diff --git a/chrome/browser/resources_integrity_unittest.cc b/chrome/browser/resources_integrity_unittest.cc
index 3cdf1949..1fee1a8 100644
--- a/chrome/browser/resources_integrity_unittest.cc
+++ b/chrome/browser/resources_integrity_unittest.cc
@@ -9,6 +9,8 @@
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
+#include "build/build_config.h"
+#include "chrome/app/packed_resources_integrity.h"
 #include "chrome/browser/buildflags.h"
 #include "chrome/common/chrome_paths.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -64,7 +66,20 @@
   loop.Quit();
 }
 
-#if BUILDFLAG(ENABLE_PAK_FILE_INTEGRITY_CHECKS)
+#if defined(OS_WIN)
+// On Windows, CheckPakFileIntegrity() dynamically finds this symbol from its
+// main exe module (normally chrome.exe). In unit_tests.exe, provide the same
+// export.
+extern "C" __declspec(dllexport) __cdecl void GetPakFileHashes(
+    const uint8_t** resources_pak,
+    const uint8_t** chrome_100_pak,
+    const uint8_t** chrome_200_pak) {
+  *resources_pak = kSha256_resources_pak.data();
+  *chrome_100_pak = kSha256_chrome_100_percent_pak.data();
+  *chrome_200_pak = kSha256_chrome_200_percent_pak.data();
+}
+#endif  // defined(OS_WIN)
+
 TEST_F(CheckResourceIntegrityTest, ChromePaks) {
   base::HistogramTester tester;
   CheckPakFileIntegrity();
@@ -73,4 +88,3 @@
   tester.ExpectBucketCount("SafeBrowsing.PakIntegrity.Chrome100", 1, 1);
   tester.ExpectBucketCount("SafeBrowsing.PakIntegrity.Chrome200", 1, 1);
 }
-#endif  // BUILDFLAG(ENABLE_PAK_FILE_INTEGRITY_CHECKS)
diff --git a/chrome/browser/share/share_history.cc b/chrome/browser/share/share_history.cc
index 413fd5a..ad80456 100644
--- a/chrome/browser/share/share_history.cc
+++ b/chrome/browser/share/share_history.cc
@@ -18,7 +18,11 @@
 namespace {
 
 const char* const kShareHistoryFolder = "share_history";
-static const char kShareHistoryKey[1] = "";
+
+// This is the key used for the single entry in the backing LevelDB. The fact
+// that it is the same string as the above folder name is a coincidence; please
+// do not fold these constants together.
+const char* const kShareHistoryKey = "share_history";
 
 int TodaysDay() {
   return (base::Time::Now() - base::Time::UnixEpoch()).InDays();
@@ -76,8 +80,7 @@
 
   target_history->set_count(target_history->count() + 1);
 
-  // TODO(ellyjones): Start a write back to the backing database. Once that's
-  // done, un-disable the AddsWrittenToBackingDb test.
+  FlushToBackingDb();
 }
 
 void ShareHistory::GetFlatShareHistory(GetFlatHistoryCallback callback,
@@ -126,13 +129,44 @@
 }
 
 void ShareHistory::OnInitDone(leveldb_proto::Enums::InitStatus status) {
-  init_finished_ = true;
   db_init_status_ = status;
+  if (status != leveldb_proto::Enums::kOK) {
+    // If the LevelDB initialization failed, follow the same state transitions
+    // as in the happy case, but without going through LevelDB; i.e., act as
+    // though the initial read failed, instead of the LevelDB initialization, so
+    // that control always ends up in OnInitialReadDone.
+    base::SequencedTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(&ShareHistory::OnInitialReadDone,
+                                  weak_factory_.GetWeakPtr(), false,
+                                  std::make_unique<mojom::ShareHistory>()));
+    return;
+  }
+
+  db_->GetEntry(kShareHistoryKey,
+                base::BindOnce(&ShareHistory::OnInitialReadDone,
+                               weak_factory_.GetWeakPtr()));
+}
+
+void ShareHistory::OnInitialReadDone(
+    bool ok,
+    std::unique_ptr<mojom::ShareHistory> history) {
+  if (ok && history)
+    history_ = *history;
+  init_finished_ = true;
   post_init_callbacks_.Notify();
 
   // TODO(ellyjones): Expire entries older than WINDOW days.
 }
 
+void ShareHistory::FlushToBackingDb() {
+  auto keyvals = std::make_unique<BackingDb::KeyEntryVector>();
+  keyvals->push_back({kShareHistoryKey, history_});
+
+  db_->UpdateEntries(std::move(keyvals),
+                     std::make_unique<std::vector<std::string>>(),
+                     base::DoNothing());
+}
+
 mojom::DayShareHistory* ShareHistory::DayShareHistoryForToday() {
   int today = TodaysDay();
   for (auto& day : *history_.mutable_day_histories()) {
diff --git a/chrome/browser/share/share_history.h b/chrome/browser/share/share_history.h
index d641c23..0fd0a1c 100644
--- a/chrome/browser/share/share_history.h
+++ b/chrome/browser/share/share_history.h
@@ -49,6 +49,9 @@
  private:
   void Init();
   void OnInitDone(leveldb_proto::Enums::InitStatus status);
+  void OnInitialReadDone(bool ok, std::unique_ptr<mojom::ShareHistory> history);
+
+  void FlushToBackingDb();
 
   // These two methods get or create entries in the in-memory protobuf; they do
   // not actually write back to the DB.
diff --git a/chrome/browser/share/share_history_unittest.cc b/chrome/browser/share/share_history_unittest.cc
index 909984d2..f53b9a3 100644
--- a/chrome/browser/share/share_history_unittest.cc
+++ b/chrome/browser/share/share_history_unittest.cc
@@ -6,11 +6,51 @@
 #include "base/cancelable_callback.h"
 #include "base/run_loop.h"
 #include "base/test/bind.h"
+#include "base/time/time.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/leveldb_proto/testing/fake_db.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace {
+
+const char* kTarget0Name = "baz";
+const char* kTarget1Name = "quxx";
+
+int DaysSinceUnixEpoch() {
+  return (base::Time::Now() - base::Time::UnixEpoch()).InDays();
+}
+
+sharing::mojom::ShareHistory BuildTestProto() {
+  sharing::mojom::ShareHistory proto;
+
+  {
+    auto* today = proto.mutable_day_histories()->Add();
+    today->set_day(DaysSinceUnixEpoch());
+
+    auto* baz = today->mutable_target_histories()->Add();
+    baz->mutable_target()->set_component_name(kTarget0Name);
+    baz->set_count(4);
+
+    auto* quxx = today->mutable_target_histories()->Add();
+    quxx->mutable_target()->set_component_name(kTarget1Name);
+    quxx->set_count(2);
+  }
+
+  {
+    auto* yesterday = proto.mutable_day_histories()->Add();
+    yesterday->set_day(DaysSinceUnixEpoch() - 1);
+
+    auto* baz = yesterday->mutable_target_histories()->Add();
+    baz->mutable_target()->set_component_name(kTarget0Name);
+    baz->set_count(1);
+  }
+
+  return proto;
+}
+
+}  // namespace
+
 namespace sharing {
 
 // Fixture for tests that test the behavior of ShareHistory. These tests use a
@@ -22,29 +62,21 @@
  public:
   using FakeDB = leveldb_proto::test::FakeDB<mojom::ShareHistory>;
 
-  ShareHistoryTest() {
+  ShareHistoryTest() { Init(); }
+
+  void Init(bool do_default_init = true) {
     auto backing_db = std::make_unique<FakeDB>(&backing_entries_);
     backing_db_ = backing_db.get();
 
     db_ = std::make_unique<ShareHistory>(
         &profile_, base::WrapUnique(backing_db.release()));
 
-    backing_init_callback_.Reset(base::BindOnce(
-        [](ShareHistoryTest* test) {
-          test->backing_db_->InitStatusCallback(
-              leveldb_proto::Enums::InitStatus::kOK);
-        },
-        base::Unretained(this)));
-    base::SequencedTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, backing_init_callback_.callback());
+    if (do_default_init) {
+      backing_db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
+      backing_db_->GetCallback(true);
+    }
   }
 
-  // By default, ShareHistoryTest runs start with a posted task that simulates
-  // database initialization finishing successfully. Tests that need to fake
-  // an init failure, or otherwise have tighter control over when init appears
-  // to complete, can use this method to cancel the default init.
-  void CancelDefaultInit() { backing_init_callback_.Cancel(); }
-
   // This method is a synchronous wrapper for GetFlatShareHistory() for test
   // ergonomics. Note that if the test has cancelled default init and not posted
   // its own init, this can deadlock!
@@ -62,6 +94,22 @@
     return out_result;
   }
 
+  std::unique_ptr<mojom::ShareHistory> GetBackingDbProto() {
+    base::RunLoop loop;
+    std::unique_ptr<mojom::ShareHistory> result;
+    backing_db()->GetEntry(
+        "share_history",
+        base::BindLambdaForTesting(
+            [&](bool ok, std::unique_ptr<mojom::ShareHistory> res) {
+              ASSERT_TRUE(ok);
+              result = std::move(res);
+              loop.Quit();
+            }));
+    backing_db()->GetCallback(true);
+    loop.Run();
+    return result;
+  }
+
   ShareHistory* db() { return db_.get(); }
 
   leveldb_proto::test::FakeDB<mojom::ShareHistory>* backing_db() {
@@ -76,10 +124,8 @@
  private:
   content::BrowserTaskEnvironment environment_{
       // This set of tests must use a mock time source. If they don't, and a
-      // test
-      // happens to run across UTC midnight, the day can change mid-test,
-      // causing
-      // surprising results.
+      // test happens to run across UTC midnight, the day can change mid-test,
+      // causing surprising results.
       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
   TestingProfile profile_;
   std::unique_ptr<ShareHistory> db_;
@@ -98,6 +144,8 @@
   db()->AddShareEntry("bar");
   db()->AddShareEntry("foo");
 
+  backing_db()->UpdateCallback(true);
+
   auto result = GetFlatShareHistory();
   EXPECT_EQ(result.size(), 2U);
   EXPECT_EQ(result[0].component_name, "foo");
@@ -106,20 +154,48 @@
   EXPECT_EQ(result[1].count, 1);
 }
 
-// TODO(ellyjones): Writes to the backing leveldb are not yet implemented.
-TEST_F(ShareHistoryTest, DISABLED_AddsWrittenToBackingDb) {
+TEST_F(ShareHistoryTest, AddsWrittenToBackingDb) {
   db()->AddShareEntry("foo");
   db()->AddShareEntry("bar");
   db()->AddShareEntry("foo");
+
+  backing_db()->UpdateCallback(true);
+
+  db()->AddShareEntry("foo");
+  backing_db()->UpdateCallback(true);
+
+  auto proto = GetBackingDbProto();
+  ASSERT_EQ(proto->day_histories().size(), 1);
+  auto today = proto->day_histories()[0];
+  EXPECT_EQ(today.day(), DaysSinceUnixEpoch());
+  ASSERT_EQ(today.target_histories().size(), 2);
+  EXPECT_EQ(today.target_histories()[0].target().component_name(), "foo");
+  EXPECT_EQ(today.target_histories()[0].count(), 3);
+  EXPECT_EQ(today.target_histories()[1].target().component_name(), "bar");
+  EXPECT_EQ(today.target_histories()[1].count(), 1);
 }
 
-// TODO(ellyjones): reads from the backing leveldb is not yet implemented.
-TEST_F(ShareHistoryTest, DISABLED_BackingDbIsLoaded) {
-  // backing_entries_[key] = MakeAProto();
-  auto result = GetFlatShareHistory();
+TEST_F(ShareHistoryTest, BackingDbIsLoaded) {
+  // After rewriting backing_entries(), to simulate having stored data on disk,
+  // reinitialize the database to cause it to reread the backing DB.
+  (*backing_entries())["share_history"] = BuildTestProto();
+  Init();
 
-  EXPECT_EQ(result.size(), 2U);
-  // ...
+  auto result = GetFlatShareHistory();
+  ASSERT_EQ(result.size(), 2U);
+  EXPECT_EQ(result[0].component_name, kTarget0Name);
+  EXPECT_EQ(result[0].count, 5);
+  EXPECT_EQ(result[1].component_name, kTarget1Name);
+  EXPECT_EQ(result[1].count, 2);
+}
+
+TEST_F(ShareHistoryTest, BackingDbInitFailureStillRunsCallbacks) {
+  (*backing_entries())["share_history"] = BuildTestProto();
+  Init(false);
+  backing_db()->InitStatusCallback(leveldb_proto::Enums::InitStatus::kError);
+
+  auto result = GetFlatShareHistory();
+  EXPECT_EQ(result.size(), 0U);
 }
 
 }  // namespace sharing
diff --git a/chrome/browser/sharing_hub/sharing_hub_model.cc b/chrome/browser/sharing_hub/sharing_hub_model.cc
index 8104a3f..26cd1fb 100644
--- a/chrome/browser/sharing_hub/sharing_hub_model.cc
+++ b/chrome/browser/sharing_hub/sharing_hub_model.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/media/router/media_router_feature.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/send_tab_to_self/send_tab_to_self_util.h"
+#include "chrome/browser/ui/qrcode_generator/qrcode_generator_bubble_controller.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/vector_icons/vector_icons.h"
 #include "content/public/browser/browser_context.h"
@@ -30,6 +31,11 @@
       if (DoShowSendTabToSelfForWebContents(web_contents)) {
         list->push_back(action);
       }
+    } else if (action.command_id == IDC_QRCODE_GENERATOR) {
+      if (qrcode_generator::QRCodeGeneratorBubbleController::
+              IsGeneratorAvailable(web_contents->GetLastCommittedURL())) {
+        list->push_back(action);
+      }
     } else {
       list->push_back(action);
     }
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index 58bf658..ff8cf58f 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -4408,6 +4408,14 @@
         Your computer wants to use this device to sign in to a site
       </message>
 
+      <message name="IDS_CABLEV2_BLE_ENABLE_TITLE" desc="The title of a screen that'll appear on a phone when we need to enable Bluetooth on the device. This screen will appear for a couple of seconds to give context, then a prompt will appear to allow the user to confirm that they wish to enable Bluetooth. Bluetooth is a radio technology commonly found in phones.">
+        Switching on Bluetooth…
+      </message>
+
+      <message name="IDS_CABLEV2_BLE_ENABLE_BODY" desc="The subheading on a screen that'll appear on a phone when we need to enable Bluetooth on the device. This screen will appear for a couple of seconds to give context, then a prompt will appear to allow the user to confirm that they wish to enable Bluetooth. Bluetooth is a radio technology commonly found in phones. This subheading is informing the user that, if they opt to turn on Bluetooth for this operation, it'll automatically be switched off again afterwards.">
+        We'll switch it back off after we are done
+      </message>
+
       <!-- QR Code -->
       <message name="IDS_QR_CODE_SHARE_ICON_LABEL" desc="Icon label for sharing with QR Code activity.">
         QR Code
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CABLEV2_BLE_ENABLE_BODY.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CABLEV2_BLE_ENABLE_BODY.png.sha1
new file mode 100644
index 0000000..60bfe10b
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CABLEV2_BLE_ENABLE_BODY.png.sha1
@@ -0,0 +1 @@
+678642c4318cf8a32606ba315b2525674f828ce0
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CABLEV2_BLE_ENABLE_TITLE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CABLEV2_BLE_ENABLE_TITLE.png.sha1
new file mode 100644
index 0000000..60bfe10b
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CABLEV2_BLE_ENABLE_TITLE.png.sha1
@@ -0,0 +1 @@
+678642c4318cf8a32606ba315b2525674f828ce0
\ No newline at end of file
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc
index f4e2e0e..dbbed5843 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client.cc
+++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -686,6 +686,7 @@
 
 void ChromeAutofillClient::OnVirtualCardFetched(const CreditCard* credit_card,
                                                 const std::u16string& cvc) {
+  GetFormDataImporter()->CacheFetchedVirtualCard(credit_card->LastFourDigits());
 #if defined(OS_ANDROID)
   (new AutofillSnackbarControllerImpl(web_contents()))->Show();
 #else
diff --git a/chrome/browser/ui/sharing_hub/sharing_hub_sub_menu_model.cc b/chrome/browser/ui/sharing_hub/sharing_hub_sub_menu_model.cc
index e9119ff..cb35d31 100644
--- a/chrome/browser/ui/sharing_hub/sharing_hub_sub_menu_model.cc
+++ b/chrome/browser/ui/sharing_hub/sharing_hub_sub_menu_model.cc
@@ -21,28 +21,11 @@
 
 namespace sharing_hub {
 
-SharingHubSubMenuModel::SharingHubSubMenuModel(Browser* browser)
-    : SimpleMenuModel(this), browser_(browser) {
-  Build(browser_->tab_strip_model()->GetActiveWebContents());
-}
-
-bool SharingHubSubMenuModel::IsCommandIdEnabled(int command_id) const {
-  // TODO crbug.com/1186848 ensure that commands are enabled based on sharing
-  // criteria.
-  return true;
-}
-
-void SharingHubSubMenuModel::ExecuteCommand(int command_id, int event_flags) {
-  GlobalError* error =
-      GlobalErrorServiceFactory::GetForProfile(browser_->profile())
-          ->GetGlobalErrorByMenuItemCommandID(command_id);
-  if (error) {
-    error->ExecuteMenuItem(browser_);
-    return;
-  }
-
-  // TODO crbug.com/1186848  Log metrics per command_id;
-  chrome::ExecuteCommand(browser_, command_id);
+SharingHubSubMenuModel::SharingHubSubMenuModel(
+    ui::SimpleMenuModel::Delegate* delegate,
+    content::WebContents* web_contents)
+    : SimpleMenuModel(delegate) {
+  Build(web_contents);
 }
 
 void SharingHubSubMenuModel::Build(content::WebContents* web_contents) {
diff --git a/chrome/browser/ui/sharing_hub/sharing_hub_sub_menu_model.h b/chrome/browser/ui/sharing_hub/sharing_hub_sub_menu_model.h
index d4a808b..5a505e9 100644
--- a/chrome/browser/ui/sharing_hub/sharing_hub_sub_menu_model.h
+++ b/chrome/browser/ui/sharing_hub/sharing_hub_sub_menu_model.h
@@ -8,21 +8,15 @@
 #include "content/public/browser/web_contents.h"
 #include "ui/base/models/simple_menu_model.h"
 
-class Browser;
 namespace sharing_hub {
 
-class SharingHubSubMenuModel : public ui::SimpleMenuModel,
-                               public ui::SimpleMenuModel::Delegate {
+class SharingHubSubMenuModel : public ui::SimpleMenuModel {
  public:
-  explicit SharingHubSubMenuModel(Browser* browser);
-
-  // Overridden from ui::SimpleMenuModel::Delegate:
-  bool IsCommandIdEnabled(int command_id) const override;
-  void ExecuteCommand(int command_id, int event_flags) override;
+  SharingHubSubMenuModel(ui::SimpleMenuModel::Delegate* delegate,
+                         content::WebContents* web_contents);
 
  private:
   void Build(content::WebContents* web_contents);
-  Browser* browser_;
 
   DISALLOW_COPY_AND_ASSIGN(SharingHubSubMenuModel);
 };
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc
index bb5c1fa..77d8373 100644
--- a/chrome/browser/ui/toolbar/app_menu_model.cc
+++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -110,6 +110,8 @@
 using base::UserMetricsAction;
 using content::WebContents;
 
+DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kHistoryMenuItem);
+
 namespace {
 
 constexpr size_t kMaxAppNameLength = 30;
@@ -807,6 +809,8 @@
         std::make_unique<RecentTabsSubMenuModel>(provider_, browser_));
     AddSubMenuWithStringId(IDC_RECENT_TABS_MENU, IDS_HISTORY_MENU,
                            sub_menus_.back().get());
+    SetElementIdentifierAt(GetIndexOfCommandId(IDC_RECENT_TABS_MENU),
+                           kHistoryMenuItem);
   }
   AddItemWithStringId(IDC_SHOW_DOWNLOADS, IDS_SHOW_DOWNLOADS);
   if (!browser_->profile()->IsGuestSession() &&
@@ -822,8 +826,8 @@
   AddSeparator(ui::UPPER_SEPARATOR);
 
   if (base::FeatureList::IsEnabled(sharing_hub::kSharingHubDesktopAppMenu)) {
-    sub_menus_.push_back(
-        std::make_unique<sharing_hub::SharingHubSubMenuModel>(browser_));
+    sub_menus_.push_back(std::make_unique<sharing_hub::SharingHubSubMenuModel>(
+        this, browser_->tab_strip_model()->GetActiveWebContents()));
     AddSubMenuWithStringId(IDC_SHARING_HUB_MENU, IDS_SHARING_HUB_TITLE,
                            sub_menus_.back().get());
   }
diff --git a/chrome/browser/ui/toolbar/app_menu_model.h b/chrome/browser/ui/toolbar/app_menu_model.h
index f31a24a..2ef66245 100644
--- a/chrome/browser/ui/toolbar/app_menu_model.h
+++ b/chrome/browser/ui/toolbar/app_menu_model.h
@@ -15,6 +15,7 @@
 #include "content/public/browser/host_zoom_map.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "ui/base/accelerators/accelerator.h"
+#include "ui/base/interaction/element_identifier.h"
 #include "ui/base/models/button_menu_item_model.h"
 #include "ui/base/models/simple_menu_model.h"
 
@@ -115,6 +116,8 @@
                      public TabStripModelObserver,
                      public content::WebContentsObserver {
  public:
+  DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kHistoryMenuItem);
+
   // Range of command IDs to use for the items in the recent tabs submenu.
   static const int kMinRecentTabsCommandId = 1001;
   static const int kMaxRecentTabsCommandId = 1200;
diff --git a/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.cc b/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.cc
index 854ffd73..c5a562c 100644
--- a/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.cc
+++ b/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.cc
@@ -21,6 +21,7 @@
 #include "components/offline_pages/buildflags/buildflags.h"
 #include "components/omnibox/browser/autocomplete_input.h"
 #include "components/omnibox/browser/omnibox_prefs.h"
+#include "components/omnibox/common/omnibox_features.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
 #include "components/search/ntp_features.h"
@@ -125,6 +126,19 @@
   return !profile || !search::IsInstantNTPURL(url, profile);
 }
 
+bool ChromeLocationBarModelDelegate::
+    ShouldUseUpdatedConnectionSecurityIndicators() const {
+  Profile* profile = GetProfile();
+  if (!profile) {
+    return false;
+  }
+  if (profile->GetPrefs()->GetBoolean(omnibox::kLockIconInAddressBarEnabled)) {
+    return false;
+  }
+  return base::FeatureList::IsEnabled(
+      omnibox::kUpdatedConnectionSecurityIndicators);
+}
+
 security_state::SecurityLevel ChromeLocationBarModelDelegate::GetSecurityLevel()
     const {
   content::WebContents* web_contents = GetActiveWebContents();
@@ -262,4 +276,5 @@
 void ChromeLocationBarModelDelegate::RegisterProfilePrefs(
     user_prefs::PrefRegistrySyncable* registry) {
   registry->RegisterBooleanPref(omnibox::kPreventUrlElisionsInOmnibox, false);
+  registry->RegisterBooleanPref(omnibox::kLockIconInAddressBarEnabled, false);
 }
diff --git a/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.h b/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.h
index 3071cb2c..1fa9f791 100644
--- a/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.h
+++ b/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.h
@@ -36,6 +36,7 @@
       const std::u16string& formatted_url) const override;
   bool GetURL(GURL* url) const override;
   bool ShouldDisplayURL() const override;
+  bool ShouldUseUpdatedConnectionSecurityIndicators() const override;
   security_state::SecurityLevel GetSecurityLevel() const override;
   std::unique_ptr<security_state::VisibleSecurityState>
   GetVisibleSecurityState() const override;
diff --git a/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc b/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc
index 128686b2..08e01ef9 100644
--- a/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc
+++ b/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc
@@ -48,6 +48,22 @@
 
 namespace {
 
+class ErrorIconView : public views::ImageView {
+ public:
+  METADATA_HEADER(ErrorIconView);
+
+  // views::ImageView:
+  void OnThemeChanged() override {
+    ImageView::OnThemeChanged();
+    const SkColor warning_text_color = views::style::GetColor(
+        *this, ChromeTextContext::CONTEXT_DIALOG_BODY_TEXT_SMALL, STYLE_RED);
+    SetImage(gfx::CreateVectorIcon(kBrowserToolsErrorIcon, warning_text_color));
+  }
+};
+
+BEGIN_METADATA(ErrorIconView, views::ImageView)
+END_METADATA
+
 static views::GridLayout* ResetOverlayLayout(views::View* overlay) {
   views::GridLayout* overlay_layout =
       overlay->SetLayoutManager(std::make_unique<views::GridLayout>());
@@ -222,8 +238,11 @@
   SkColor bg_color = GetNativeTheme()->GetSystemColor(
       ui::NativeTheme::kColorId_DialogBackground);
   overlay_->SetBackground(views::CreateSolidBackground(bg_color));
-  if (overlay_label_)
+  if (overlay_label_) {
     overlay_label_->SetBackgroundColor(bg_color);
+    overlay_label_->SetEnabledColor(GetNativeTheme()->GetSystemColor(
+        ui::NativeTheme::kColorId_ThrobberSpinningColor));
+  }
 }
 
 std::u16string CardUnmaskPromptViews::GetWindowTitle() const {
@@ -327,11 +346,9 @@
   controls_container_ = AddChildView(std::move(controls_container));
 
   // Instruction text of the dialog.
-  auto instructions =
-      std::make_unique<views::Label>(controller_->GetInstructionsMessage());
-  instructions->SetEnabledColor(views::style::GetColor(
-      *instructions.get(), views::style::CONTEXT_DIALOG_BODY_TEXT,
-      views::style::STYLE_SECONDARY));
+  auto instructions = std::make_unique<views::Label>(
+      controller_->GetInstructionsMessage(),
+      views::style::CONTEXT_DIALOG_BODY_TEXT, views::style::STYLE_SECONDARY);
   instructions->SetMultiLine(true);
   instructions->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   instructions_ = controls_container_->AddChildView(std::move(instructions));
@@ -388,18 +405,13 @@
   temporary_error_layout->set_cross_axis_alignment(
       views::BoxLayout::CrossAxisAlignment::kCenter);
 
-  const SkColor warning_text_color = views::style::GetColor(
-      *instructions_, ChromeTextContext::CONTEXT_DIALOG_BODY_TEXT_SMALL,
-      STYLE_RED);
-  auto error_icon = std::make_unique<views::ImageView>();
-  error_icon->SetImage(
-      gfx::CreateVectorIcon(kBrowserToolsErrorIcon, warning_text_color));
   temporary_error->SetVisible(false);
-  temporary_error->AddChildView(std::move(error_icon));
+  temporary_error->AddChildView(std::make_unique<ErrorIconView>());
 
-  auto error_label = std::make_unique<views::Label>();
+  auto error_label = std::make_unique<views::Label>(
+      std::u16string(), ChromeTextContext::CONTEXT_DIALOG_BODY_TEXT_SMALL,
+      STYLE_RED);
   error_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  error_label->SetEnabledColor(warning_text_color);
   error_label_ = temporary_error->AddChildView(std::move(error_label));
   temporary_error_layout->SetFlexForView(error_label_, 1);
   temporary_error_ = input_container->AddChildView(std::move(temporary_error));
@@ -417,9 +429,6 @@
 
   auto overlay_label = std::make_unique<views::Label>(l10n_util::GetStringUTF16(
       IDS_AUTOFILL_CARD_UNMASK_VERIFICATION_IN_PROGRESS));
-  overlay_label->SetEnabledColor(
-      overlay_label->GetNativeTheme()->GetSystemColor(
-          ui::NativeTheme::kColorId_ThrobberSpinningColor));
   overlay_label_ = overlay_layout->AddView(std::move(overlay_label));
 
   overlay_ = AddChildView(std::move(overlay));
diff --git a/chrome/browser/ui/views/autofill/payments/payments_view_util.cc b/chrome/browser/ui/views/autofill/payments/payments_view_util.cc
index 2e42bfc3..613ebb0 100644
--- a/chrome/browser/ui/views/autofill/payments/payments_view_util.cc
+++ b/chrome/browser/ui/views/autofill/payments/payments_view_util.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/ui/views/chrome_typography.h"
 #include "components/strings/grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/geometry/size.h"
@@ -44,6 +45,35 @@
 
 constexpr SkColor kTitleSeparatorColor = SkColorSetRGB(0x9E, 0x9E, 0x9E);
 
+class PayIconView : public views::ImageView {
+ public:
+  METADATA_HEADER(PayIconView);
+
+  // views::ImageView:
+  void OnThemeChanged() override {
+    ImageView::OnThemeChanged();
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+    // kGooglePayLogoIcon is square, and CreateTiledImage() will clip it whereas
+    // setting the icon size would rescale it incorrectly.
+    gfx::ImageSkia image = gfx::ImageSkiaOperations::CreateTiledImage(
+        gfx::CreateVectorIcon(kGooglePayLogoIcon,
+                              GetNativeTheme()->ShouldUseDarkColors()
+                                  ? gfx::kGoogleGrey200
+                                  : gfx::kGoogleGrey700),
+        /*x=*/0, /*y=*/0, kGooglePayLogoWidth, kGooglePayLogoHeight);
+#else
+    gfx::ImageSkia image =
+        gfx::CreateVectorIcon(kCreditCardIcon, kGooglePayLogoHeight,
+                              GetNativeTheme()->GetSystemColor(
+                                  ui::NativeTheme::kColorId_DefaultIconColor));
+#endif
+    SetImage(image);
+  }
+};
+
+BEGIN_METADATA(PayIconView, views::ImageView)
+END_METADATA
+
 }  // namespace
 
 TitleWithIconAndSeparatorView::TitleWithIconAndSeparatorView(
@@ -65,24 +95,7 @@
 
   layout->StartRow(views::GridLayout::kFixedSize, 0);
 
-  auto icon_view = std::make_unique<views::ImageView>();
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-  // kGooglePayLogoIcon is square, and CreateTiledImage() will clip it whereas
-  // setting the icon size would rescale it incorrectly.
-  gfx::ImageSkia image = gfx::ImageSkiaOperations::CreateTiledImage(
-      gfx::CreateVectorIcon(kGooglePayLogoIcon,
-                            GetNativeTheme()->ShouldUseDarkColors()
-                                ? gfx::kGoogleGrey200
-                                : gfx::kGoogleGrey700),
-      /*x=*/0, /*y=*/0, kGooglePayLogoWidth, kGooglePayLogoHeight);
-#else
-  gfx::ImageSkia image =
-      gfx::CreateVectorIcon(kCreditCardIcon, kGooglePayLogoHeight,
-                            GetNativeTheme()->GetSystemColor(
-                                ui::NativeTheme::kColorId_DefaultIconColor));
-#endif
-  icon_view->SetImage(image);
-  auto* icon_view_ptr = layout->AddView(std::move(icon_view));
+  auto* icon_view_ptr = layout->AddView(std::make_unique<PayIconView>());
 
   auto separator = std::make_unique<views::Separator>();
   separator->SetColor(kTitleSeparatorColor);
diff --git a/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc b/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc
index 3096fb2..a038952c 100644
--- a/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc
+++ b/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc
@@ -12,10 +12,12 @@
 #include "build/build_config.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/browser/ui/views/accessibility/theme_tracking_non_accessible_image_view.h"
 #include "chrome/browser/ui/views/autofill/payments/dialog_view_ids.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/chrome_typography.h"
 #include "chrome/grit/generated_resources.h"
+#include "chrome/grit/theme_resources.h"
 #include "components/autofill/core/browser/autofill_experiments.h"
 #include "components/autofill/core/browser/autofill_metrics.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
@@ -120,6 +122,21 @@
   return true;
 }
 
+void SaveCardOfferBubbleViews::AddedToWidget() {
+  SaveCardBubbleViews::AddedToWidget();
+  // Set the header image.
+  if (base::FeatureList::IsEnabled(
+          features::kAutofillUseNewHeaderForSaveCardBubble)) {
+    ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+    auto image_view = std::make_unique<ThemeTrackingNonAccessibleImageView>(
+        *bundle.GetImageSkiaNamed(IDR_SAVE_CARD),
+        *bundle.GetImageSkiaNamed(IDR_SAVE_CARD_DARK),
+        base::BindRepeating(&views::BubbleFrameView::GetBackgroundColor,
+                            base::Unretained(GetBubbleFrameView())));
+    GetBubbleFrameView()->SetHeaderView(std::move(image_view));
+  }
+}
+
 void SaveCardOfferBubbleViews::ContentsChanged(
     views::Textfield* sender,
     const std::u16string& new_contents) {
@@ -127,7 +144,7 @@
   DialogModelChanged();
 }
 
-SaveCardOfferBubbleViews::~SaveCardOfferBubbleViews() {}
+SaveCardOfferBubbleViews::~SaveCardOfferBubbleViews() = default;
 
 std::unique_ptr<views::View> SaveCardOfferBubbleViews::CreateMainContentView() {
   std::unique_ptr<views::View> view =
diff --git a/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.h b/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.h
index c0fa84a..ebb186f 100644
--- a/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.h
+++ b/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.h
@@ -32,10 +32,11 @@
                            content::WebContents* web_contents,
                            SaveCardBubbleController* controller);
 
-  // BubbleDialogDelegateView:
+  // SaveCardBubbleViews:
   void Init() override;
   bool Accept() override;
   bool IsDialogButtonEnabled(ui::DialogButton button) const override;
+  void AddedToWidget() override;
 
   // views::TextfieldController:
   void ContentsChanged(views::Textfield* sender,
diff --git a/chrome/browser/ui/views/passwords/password_save_update_view.cc b/chrome/browser/ui/views/passwords/password_save_update_view.cc
index 96bbfddb..fb87835 100644
--- a/chrome/browser/ui/views/passwords/password_save_update_view.cc
+++ b/chrome/browser/ui/views/passwords/password_save_update_view.cc
@@ -358,9 +358,14 @@
 void PasswordSaveUpdateView::AddedToWidget() {
   static_cast<views::Label*>(GetBubbleFrameView()->title())
       ->SetAllowCharacterBreak(true);
-
-  SetBubbleHeader(IDR_SAVE_PASSWORD_MULTI_DEVICE,
-                  IDR_SAVE_PASSWORD_MULTI_DEVICE_DARK);
+  if (base::FeatureList::IsEnabled(
+          password_manager::features::
+              kUseNewHeaderForLegacySavePasswordBubble)) {
+    SetBubbleHeader(IDR_SAVE_PASSWORD, IDR_SAVE_PASSWORD_DARK);
+  } else {
+    SetBubbleHeader(IDR_SAVE_PASSWORD_MULTI_DEVICE,
+                    IDR_SAVE_PASSWORD_MULTI_DEVICE_DARK);
+  }
 }
 
 void PasswordSaveUpdateView::OnThemeChanged() {
diff --git a/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.cc b/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.cc
index a06b1a58..a6a0ea5 100644
--- a/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.cc
+++ b/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.cc
@@ -636,6 +636,12 @@
 }
 
 void PasswordSaveUpdateWithAccountStoreView::UpdateHeaderImage() {
+  if (base::FeatureList::IsEnabled(
+          password_manager::features::
+              kUseNewHeaderForSavePasswordWithAccountStoreBubble)) {
+    SetBubbleHeader(IDR_SAVE_PASSWORD, IDR_SAVE_PASSWORD_DARK);
+    return;
+  }
   int light_image_id = controller_.IsCurrentStateAffectingTheAccountStore()
                            ? IDR_SAVE_PASSWORD_MULTI_DEVICE
                            : IDR_SAVE_PASSWORD_ONE_DEVICE;
diff --git a/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc b/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc
index 20baf08e..a666225d 100644
--- a/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc
+++ b/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc
@@ -122,8 +122,10 @@
       const ui::ThemeProvider& theme_provider =
           ThemeService::GetThemeProviderForProfile(profile);
       security_icon->SetImage(gfx::CreateVectorIcon(
-          location_bar_model::GetSecurityVectorIcon(security_level), 16,
-          GetOmniboxSecurityChipColor(&theme_provider, security_level)));
+          location_bar_model::GetSecurityVectorIcon(
+              security_level,
+              /* use_updated_connection_security_indicators=*/false),
+          16, GetOmniboxSecurityChipColor(&theme_provider, security_level)));
       security_icon->SetID(static_cast<int>(DialogViewID::SECURITY_ICON_VIEW));
       origin_layout->AddView(std::move(security_icon));
     }
diff --git a/chrome/browser/ui/views/safe_browsing/password_reuse_modal_warning_dialog.cc b/chrome/browser/ui/views/safe_browsing/password_reuse_modal_warning_dialog.cc
index 6f55f4d..1db2b04 100644
--- a/chrome/browser/ui/views/safe_browsing/password_reuse_modal_warning_dialog.cc
+++ b/chrome/browser/ui/views/safe_browsing/password_reuse_modal_warning_dialog.cc
@@ -35,22 +35,25 @@
 
 namespace {
 
-// Updates the image displayed on the illustration based on the current theme.
-void SafeBrowsingUpdateImageView(NonAccessibleImageView* image_view,
-                                 bool dark_mode_enabled) {
-  image_view->SetImage(
-      *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
-          dark_mode_enabled ? IDR_PASSWORD_CHECK_DARK : IDR_PASSWORD_CHECK));
-}
+class SafeBrowsingImageView : public NonAccessibleImageView {
+ public:
+  METADATA_HEADER(SafeBrowsingImageView);
+  SafeBrowsingImageView() {
+    SetVerticalAlignment(views::ImageView::Alignment::kLeading);
+  }
+  ~SafeBrowsingImageView() override = default;
 
-// Creates the illustration which is rendered on top of the dialog.
-std::unique_ptr<NonAccessibleImageView> SafeBrowsingCreateIllustration(
-    bool dark_mode_enabled) {
-  auto image_view = std::make_unique<NonAccessibleImageView>();
-  SafeBrowsingUpdateImageView(image_view.get(), dark_mode_enabled);
-  image_view->SetVerticalAlignment(views::ImageView::Alignment::kLeading);
-  return image_view;
-}
+  // NonAccessibleImageView:
+  void OnThemeChanged() override {
+    NonAccessibleImageView::OnThemeChanged();
+    SetImage(*ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+        GetNativeTheme()->ShouldUseDarkColors() ? IDR_PASSWORD_CHECK_DARK
+                                                : IDR_PASSWORD_CHECK));
+  }
+};
+
+BEGIN_METADATA(SafeBrowsingImageView, NonAccessibleImageView)
+END_METADATA
 
 // Sets up the content containing the title and description for the dialog
 // rendered below the illustration.
@@ -198,8 +201,6 @@
   SetLayoutManager(std::make_unique<BoxLayout>(
       views::BoxLayout::Orientation::kVertical, gfx::Insets(),
       0 /* between_child_spacing */));
-  std::unique_ptr<NonAccessibleImageView> illustration =
-      SafeBrowsingCreateIllustration(GetNativeTheme()->ShouldUseDarkColors());
   std::unique_ptr<views::View> content = SetupContent(
       l10n_util::GetStringUTF16(IDS_PAGE_INFO_CHANGE_PASSWORD_SUMMARY));
 
@@ -216,7 +217,7 @@
         bold_style);
   }
   styled_message_body_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  AddChildView(std::move(illustration));
+  AddChildView(std::make_unique<SafeBrowsingImageView>());
   AddChildView(std::move(content));
 }
 
diff --git a/chrome/browser/ui/views/tooltip/tooltip_browsertest.cc b/chrome/browser/ui/views/tooltip/tooltip_browsertest.cc
index 92a3c8e..21fd2ab 100644
--- a/chrome/browser/ui/views/tooltip/tooltip_browsertest.cc
+++ b/chrome/browser/ui/views/tooltip/tooltip_browsertest.cc
@@ -12,9 +12,11 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test.h"
+#include "content/public/test/hit_test_region_observer.h"
 #include "net/dns/mock_host_resolver.h"
 #include "ui/events/test/event_generator.h"
 #include "ui/gfx/native_widget_types.h"
@@ -24,6 +26,7 @@
 #include "ui/views/widget/any_widget_observer.h"
 #include "ui/views/widget/widget.h"
 
+using content::RenderFrameHost;
 using content::RenderWidgetHostView;
 using content::WebContents;
 using views::corewm::TooltipAura;
@@ -109,10 +112,27 @@
   void NavigateToURL(const std::string& relative_url) {
     ui_test_utils::NavigateToURL(
         browser(), embedded_test_server()->GetURL("a.com", relative_url));
-    rwhv_ = browser()
-                ->tab_strip_model()
-                ->GetActiveWebContents()
-                ->GetRenderWidgetHostView();
+    web_contents_ = browser()->tab_strip_model()->GetActiveWebContents();
+    rwhv_ = web_contents_->GetRenderWidgetHostView();
+    content::WaitForHitTestData(web_contents_->GetMainFrame());
+  }
+
+  void LoadCrossSitePageIntoFrame(const std::string& relative_url,
+                                  const std::string& iframe_id) {
+    // This function makes the iframe in the web page point to a different
+    // origin, making it an OOPIF.
+    GURL frame_url(embedded_test_server()->GetURL("b.com", relative_url));
+    NavigateIframeToURL(web_contents_, iframe_id, frame_url);
+
+    // Verify that the child frame is an OOPIF with a different SiteInstance.
+    RenderFrameHost* child = GetChildRenderFrameHost(0);
+    EXPECT_NE(web_contents_->GetSiteInstance(), child->GetSiteInstance());
+    EXPECT_TRUE(child->IsCrossProcessSubframe());
+    content::WaitForHitTestData(child);
+  }
+
+  RenderFrameHost* GetChildRenderFrameHost(size_t index) {
+    return ChildFrameAt(web_contents_->GetMainFrame(), index);
   }
 
   bool SkipTestForOldWinVersion() const {
@@ -148,12 +168,14 @@
  private:
   std::unique_ptr<ui::test::EventGenerator> event_generator_ = nullptr;
   RenderWidgetHostView* rwhv_ = nullptr;
+  WebContents* web_contents_ = nullptr;
 
   std::unique_ptr<TooltipControllerTestHelper> helper_;
   std::unique_ptr<TooltipWidgetMonitor> tooltip_monitor_ = nullptr;
 };  // class TooltipBrowserTest
 
-IN_PROC_BROWSER_TEST_F(TooltipBrowserTest, ShowTooltipFromWebContent) {
+IN_PROC_BROWSER_TEST_F(TooltipBrowserTest,
+                       ShowTooltipFromWebContentWithCursor) {
   if (SkipTestForOldWinVersion())
     return;
 
@@ -170,9 +192,66 @@
   EXPECT_EQ(expected_text, helper()->GetTooltipText());
 
   helper()->HideAndReset();
+}
 
-  // TODO(bebeaudr): Trigger a tooltip by setting focus with the keyboard on
-  // that web content button.
+IN_PROC_BROWSER_TEST_F(TooltipBrowserTest,
+                       ShowTooltipFromWebContentWithKeyboard) {
+  if (SkipTestForOldWinVersion())
+    return;
+
+  NavigateToURL("/tooltip.html");
+  std::u16string expected_text = u"my tooltip";
+
+  // Trigger the tooltip from the keyboard with a TAB keypress.
+  event_generator()->PressKey(ui::VKEY_TAB, ui::EF_NONE);
+  event_generator()->ReleaseKey(ui::VKEY_TAB, ui::EF_NONE);
+  tooltip_monitor()->WaitUntilTooltipShown();
+  EXPECT_TRUE(helper()->IsTooltipVisible());
+  EXPECT_EQ(expected_text, helper()->GetTooltipText());
+
+  helper()->HideAndReset();
+}
+
+IN_PROC_BROWSER_TEST_F(TooltipBrowserTest, ShowTooltipFromIFrameWithKeyboard) {
+  if (SkipTestForOldWinVersion())
+    return;
+
+  // There are two tooltips in this file: one above the iframe and one inside
+  // the iframe.
+  NavigateToURL("/tooltip_in_iframe.html");
+  std::u16string expected_text = u"my tooltip";
+
+  // Make the iframe cross-origin.
+  LoadCrossSitePageIntoFrame("/tooltip.html", "iframe1");
+
+  // Move the focus to the button outside of the iframe to get its position.
+  // We'll use it in the next step to validate that the tooltip associated with
+  // the button inside of the iframe is positioned, well, inside the iframe.
+  event_generator()->PressKey(ui::VKEY_TAB, ui::EF_NONE);
+  event_generator()->ReleaseKey(ui::VKEY_TAB, ui::EF_NONE);
+  tooltip_monitor()->WaitUntilTooltipShown();
+  EXPECT_TRUE(helper()->IsTooltipVisible());
+  EXPECT_EQ(expected_text, helper()->GetTooltipText());
+  gfx::Point first_tooltip_anchor_point = helper()->GetTooltipPosition();
+
+  // Now that we have the anchor point of the first tooltip, move the focus to
+  // the tooltip inside of the iframe.
+  event_generator()->PressKey(ui::VKEY_TAB, ui::EF_NONE);
+  event_generator()->ReleaseKey(ui::VKEY_TAB, ui::EF_NONE);
+  tooltip_monitor()->WaitUntilTooltipShown();
+  EXPECT_TRUE(helper()->IsTooltipVisible());
+  EXPECT_EQ(expected_text, helper()->GetTooltipText());
+
+  // Validate that the tooltip is correctly positioned inside the iframe.
+  // Because we explicitly removed the iframe's borders and body margins, the
+  // buttons should be positioned at the exact same x value as the button above,
+  // and at exactly twice the y value as the one outside the iframe (because the
+  // tooltip's anchor point is at the bottom-center of the button).
+  int expected_y = 2 * first_tooltip_anchor_point.y();
+  EXPECT_EQ(gfx::Point(first_tooltip_anchor_point.x(), expected_y),
+            helper()->GetTooltipPosition());
+
+  helper()->HideAndReset();
 }
 
 IN_PROC_BROWSER_TEST_F(TooltipBrowserTest, HideTooltipOnKeyPress) {
@@ -191,9 +270,23 @@
 
   // Second, send a key press event to test whether the tooltip gets hidden.
   EXPECT_TRUE(tooltip_monitor()->IsWidgetActive());
-  event_generator()->PressKey(ui::VKEY_A, 0);
+  event_generator()->PressKey(ui::VKEY_A, ui::EF_NONE);
+  event_generator()->ReleaseKey(ui::VKEY_A, ui::EF_NONE);
   tooltip_monitor()->WaitUntilTooltipClosed();
   EXPECT_FALSE(helper()->IsTooltipVisible());
 
-  // TODO(bebeaudr): Also try it with a keyboard triggered tooltip.
+  // Try the same thing with a keyboard-triggered tooltip.
+  // Trigger the tooltip from the keyboard with a TAB keypress.
+  event_generator()->PressKey(ui::VKEY_TAB, ui::EF_NONE);
+  event_generator()->ReleaseKey(ui::VKEY_TAB, ui::EF_NONE);
+  tooltip_monitor()->WaitUntilTooltipShown();
+  EXPECT_TRUE(helper()->IsTooltipVisible());
+  EXPECT_EQ(expected_text, helper()->GetTooltipText());
+
+  // Send a key press event to test whether the tooltip gets hidden.
+  EXPECT_TRUE(tooltip_monitor()->IsWidgetActive());
+  event_generator()->PressKey(ui::VKEY_A, ui::EF_NONE);
+  event_generator()->ReleaseKey(ui::VKEY_A, ui::EF_NONE);
+  tooltip_monitor()->WaitUntilTooltipClosed();
+  EXPECT_FALSE(helper()->IsTooltipVisible());
 }
diff --git a/chrome/browser/ui/views/user_education/interaction_sequence_browsertest.cc b/chrome/browser/ui/views/user_education/interaction_sequence_browsertest.cc
new file mode 100644
index 0000000..c41af6d
--- /dev/null
+++ b/chrome/browser/ui/views/user_education/interaction_sequence_browsertest.cc
@@ -0,0 +1,110 @@
+// Copyright 2021 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 <string.h>
+
+#include "base/bind.h"
+#include "base/test/bind.h"
+#include "base/test/mock_callback.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/toolbar/app_menu_model.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/toolbar/app_menu.h"
+#include "chrome/browser/ui/views/toolbar/browser_app_menu_button.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "content/public/test/browser_test.h"
+#include "ui/base/interaction/element_tracker.h"
+#include "ui/base/interaction/expect_call_in_scope.h"
+#include "ui/base/interaction/interaction_sequence.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/event.h"
+#include "ui/views/controls/menu/menu_item_view.h"
+#include "ui/views/interaction/element_tracker_views.h"
+#include "ui/views/interaction/interaction_sequence_views.h"
+
+namespace {
+
+views::View* ElementToView(ui::TrackedElement* element) {
+  return element->AsA<views::TrackedElementViews>()->view();
+}
+
+}  // namespace
+
+// This test ensures basic compatibility of InteractionSequence[Views] and a
+// live browser. It verifies that a simple journey of opening the main menu and
+// identifying a specific menu item works.
+//
+// Located in user_education because it serves as the foundation for Tutorials
+// (along with being the primary use case).
+//
+// In the future, we should add additional specific cases, such as opening a
+// dialog or multiple submenus.
+class InteractionSequenceBrowserTest : public InProcessBrowserTest {};
+
+IN_PROC_BROWSER_TEST_F(InteractionSequenceBrowserTest,
+                       OpenMainMenuAndViewHelpItem) {
+  UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted);
+  UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::CompletedCallback, completed);
+
+  const ui::ElementContext context =
+      views::ElementTrackerViews::GetContextForView(
+          BrowserView::GetBrowserViewForBrowser(browser()));
+
+  // Demonstrate that we can find the app button without having to pick through
+  // the BrowserView hierarcny.
+  views::View* const button_view = ElementToView(
+      ui::ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+          BrowserAppMenuButton::kIdentifier, context));
+  BrowserAppMenuButton* const app_menu_button =
+      static_cast<BrowserAppMenuButton*>(button_view);
+  DCHECK_EQ(std::string("BrowserAppMenuButton"),
+            std::string(app_menu_button->GetClassName()));
+
+  // Define a simple sequence of:
+  // - spotting the app menu button
+  // - clicking the app menu button
+  // - observing a submenu item
+  auto sequence =
+      ui::InteractionSequence::Builder()
+          .SetCompletedCallback(completed.Get())
+          .SetAbortedCallback(aborted.Get())
+          .AddStep(
+              views::InteractionSequenceViews::WithInitialView(app_menu_button))
+          .AddStep(ui::InteractionSequence::StepBuilder()
+                       .SetElementID(BrowserAppMenuButton::kIdentifier)
+                       .SetType(ui::InteractionSequence::StepType::kActivated)
+                       .Build())
+          .AddStep(ui::InteractionSequence::StepBuilder()
+                       .SetElementID(AppMenuModel::kHistoryMenuItem)
+                       .SetType(ui::InteractionSequence::StepType::kShown)
+                       .Build())
+          .Build();
+
+  // Start the sequence and verify that it does not proceed.
+  sequence->Start();
+
+  // Click the app menu button, displaying the target element.
+  EXPECT_CALL_IN_SCOPE(completed, Run, {
+    app_menu_button->OnKeyPressed(ui::KeyEvent(ui::ET_KEY_PRESSED,
+                                               ui::VKEY_SPACE, ui::EF_NONE,
+                                               ui::EventTimeForNow()));
+
+    app_menu_button->OnKeyReleased(ui::KeyEvent(ui::ET_KEY_RELEASED,
+                                                ui::VKEY_SPACE, ui::EF_NONE,
+                                                ui::EventTimeForNow()));
+  });
+
+  // Verify that we found the correct element and it is visible.
+  EXPECT_TRUE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+      AppMenuModel::kHistoryMenuItem, context));
+  views::MenuItemView* const history_menu_item =
+      app_menu_button->app_menu()->root_menu_item()->GetMenuItemByID(
+          IDC_RECENT_TABS_MENU);
+  EXPECT_EQ(
+      history_menu_item,
+      ElementToView(
+          ui::ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+              AppMenuModel::kHistoryMenuItem, context)));
+}
diff --git a/chrome/browser/ui/web_applications/web_app_browsertest.cc b/chrome/browser/ui/web_applications/web_app_browsertest.cc
index 3dd4e2fc..2ed89371 100644
--- a/chrome/browser/ui/web_applications/web_app_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_browsertest.cc
@@ -1270,6 +1270,29 @@
       popup_browser->CanSupportWindowFeature(Browser::FEATURE_LOCATIONBAR));
 }
 
+// Make sure chrome://internals/web-app page loads fine.
+IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, InternalWebAppPage) {
+  // Loads with no web app.
+  NavigateToURLAndWait(browser(), GURL("chrome://internals/web-app"));
+
+  const GURL app_url = GetSecureAppURL();
+  InstallPWA(app_url);
+  // Loads with one web app.
+  NavigateToURLAndWait(browser(), GURL("chrome://internals/web-app"));
+
+  // Install a non-promotable web app.
+  NavigateToURLAndWait(
+      browser(), https_server()->GetURL("/banners/no_manifest_test_page.html"));
+  chrome::SetAutoAcceptWebAppDialogForTesting(/*auto_accept=*/true,
+                                              /*auto_open_in_window=*/false);
+  WebAppInstallObserver observer(profile());
+  CHECK(chrome::ExecuteCommand(browser(), IDC_CREATE_SHORTCUT));
+  observer.AwaitNextInstall();
+  chrome::SetAutoAcceptWebAppDialogForTesting(false, false);
+  // Loads with two apps.
+  NavigateToURLAndWait(browser(), GURL("chrome://internals/web-app"));
+}
+
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest_WindowControlsOverlay,
                        WindowControlsOverlay) {
   GURL test_url = https_server()->GetURL(
diff --git a/chrome/browser/ui/web_applications/web_app_uninstall_browsertest.cc b/chrome/browser/ui/web_applications/web_app_uninstall_browsertest.cc
index 6faf630b..b57609d3 100644
--- a/chrome/browser/ui/web_applications/web_app_uninstall_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_uninstall_browsertest.cc
@@ -150,13 +150,21 @@
   const GURL app_url = GetSecureAppURL();
   const AppId app_id = InstallPWA(app_url);
 
+  base::RunLoop run_loop;
+  bool quit_run_loop = false;
+
   // Trigger app uninstall without waiting for result.
   WebAppProviderBase* const provider =
       WebAppProviderBase::GetProviderBase(profile());
   EXPECT_TRUE(provider->registrar().IsInstalled(app_id));
   DCHECK(provider->install_finalizer().CanUserUninstallWebApp(app_id));
   provider->install_finalizer().UninstallWebApp(
-      app_id, webapps::WebappUninstallSource::kAppMenu, base::DoNothing());
+      app_id, webapps::WebappUninstallSource::kAppMenu,
+      base::BindLambdaForTesting([&](bool uninstalled) {
+        if (quit_run_loop)
+          run_loop.Quit();
+        quit_run_loop = true;
+      }));
 
   // Validate that uninstalling flag is set
   auto* app = provider->registrar().AsWebAppRegistrar()->GetAppById(app_id);
@@ -164,10 +172,13 @@
   EXPECT_TRUE(app->is_uninstalling());
 
   // Trigger second uninstall call and wait for result.
-  base::RunLoop run_loop;
   provider->install_finalizer().UninstallWebApp(
       app_id, webapps::WebappUninstallSource::kAppMenu,
-      base::BindLambdaForTesting([&](bool uninstalled) { run_loop.Quit(); }));
+      base::BindLambdaForTesting([&](bool uninstalled) {
+        if (quit_run_loop)
+          run_loop.Quit();
+        quit_run_loop = true;
+      }));
   run_loop.Run();
   EXPECT_FALSE(provider->registrar().IsInstalled(app_id));
 }
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
index 7329a78d..d02643ae 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -1369,6 +1369,7 @@
   options.os_hooks[web_app::OsHookType::kShortcuts] = true;
   options.os_hooks[web_app::OsHookType::kShortcutsMenu] = true;
   options.os_hooks[web_app::OsHookType::kFileHandlers] = true;
+  options.os_hooks[web_app::OsHookType::kProtocolHandlers] = true;
   options.os_hooks[web_app::OsHookType::kRunOnOsLogin] = false;
   options.os_hooks[web_app::OsHookType::kUninstallationViaOsSettings] = true;
 #if defined(OS_WIN) || defined(OS_MAC) || \
diff --git a/chrome/browser/web_applications/components/app_registrar.h b/chrome/browser/web_applications/components/app_registrar.h
index e897f9f0..be60f6c 100644
--- a/chrome/browser/web_applications/components/app_registrar.h
+++ b/chrome/browser/web_applications/components/app_registrar.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/web_applications/components/web_app_id.h"
 #include "chrome/browser/web_applications/components/web_application_info.h"
 #include "components/services/app_service/public/cpp/file_handler.h"
+#include "components/services/app_service/public/cpp/protocol_handler_info.h"
 #include "components/services/app_service/public/cpp/url_handler_info.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -104,6 +105,8 @@
       const AppId& app_id) const = 0;
   virtual const apps::FileHandlers* GetAppFileHandlers(
       const AppId& app_id) const = 0;
+  virtual const apps::ProtocolHandlers* GetAppProtocolHandlers(
+      const AppId& app_id) const = 0;
   virtual bool IsAppFileHandlerPermissionBlocked(const AppId& app_id) const = 0;
 
   // Returns the start_url with launch_query_params appended to the end if any.
diff --git a/chrome/browser/web_applications/components/os_integration_manager.cc b/chrome/browser/web_applications/components/os_integration_manager.cc
index 05597ee9..2cff412 100644
--- a/chrome/browser/web_applications/components/os_integration_manager.cc
+++ b/chrome/browser/web_applications/components/os_integration_manager.cc
@@ -220,10 +220,10 @@
         barrier->CreateBarrierCallbackForType(OsHookType::kFileHandlers));
   }
 
-  // TODO(https://crbug.com/1108109) we should return the result of protocol
-  // handler unregistration and record errors during unregistration.
-  if (os_hooks[OsHookType::kProtocolHandlers])
-    UnregisterProtocolHandlers(app_id);
+  if (os_hooks[OsHookType::kProtocolHandlers]) {
+    UnregisterProtocolHandlers(app_id, barrier->CreateBarrierCallbackForType(
+                                           OsHookType::kProtocolHandlers));
+  }
 
   if (os_hooks[OsHookType::kUrlHandlers])
     UnregisterUrlHandlers(app_id);
@@ -249,6 +249,7 @@
   UpdateShortcuts(app_id, old_name);
   UpdateShortcutsMenu(app_id, web_app_info);
   UpdateUrlHandlers(app_id, base::DoNothing());
+  UpdateProtocolHandlers(app_id);
 }
 
 void OsIntegrationManager::GetAppExistingShortCutLocation(
@@ -322,6 +323,14 @@
   return protocol_handler_manager_->GetHandlersFor(protocol);
 }
 
+std::vector<ProtocolHandler> OsIntegrationManager::GetAppProtocolHandlers(
+    const AppId& app_id) {
+  if (!protocol_handler_manager_)
+    return std::vector<ProtocolHandler>();
+
+  return protocol_handler_manager_->GetAppProtocolHandlers(app_id);
+}
+
 FileHandlerManager& OsIntegrationManager::file_handler_manager_for_testing() {
   DCHECK(file_handler_manager_);
   return *file_handler_manager_;
@@ -508,13 +517,16 @@
       app_id, std::move(info), std::move(callback));
 }
 
-void OsIntegrationManager::UnregisterProtocolHandlers(const AppId& app_id) {
-  if (!protocol_handler_manager_)
+void OsIntegrationManager::UnregisterProtocolHandlers(
+    const AppId& app_id,
+    base::OnceCallback<void(bool)> callback) {
+  if (!protocol_handler_manager_) {
+    std::move(callback).Run(true);
     return;
+  }
 
-  // TODO(https://crbug.com/1019239) Make this take a callback, and return bool
-  // success or a single/list of enum errors.
-  protocol_handler_manager_->UnregisterOsProtocolHandlers(app_id);
+  protocol_handler_manager_->UnregisterOsProtocolHandlers(app_id,
+                                                          std::move(callback));
 }
 
 void OsIntegrationManager::UnregisterUrlHandlers(const AppId& app_id) {
@@ -611,6 +623,31 @@
                      std::move(callback_after_removal)));
 }
 
+void OsIntegrationManager::UpdateProtocolHandlers(const AppId& app_id) {
+  if (!protocol_handler_manager_)
+    return;
+
+  // Update protocol handlers via complete uninstallation, then reinstallation.
+  base::OnceCallback<void(bool)> callback = base::BindOnce(
+      [](base::WeakPtr<OsIntegrationManager> os_integration_manager,
+         const AppId& app_id, bool unregister_success) {
+        // Re-register protocol handlers regardless of `unregister_success`.
+        // TODO(https://crbug.com/1019239): Report `unregister_success` in
+        // an UMA metric.
+        if (!os_integration_manager)
+          return;
+        os_integration_manager->RegisterProtocolHandlers(
+            app_id, base::DoNothing::Once<bool>());
+      },
+      weak_ptr_factory_.GetWeakPtr(), app_id);
+
+  content::GetUIThreadTaskRunner({})->PostTask(
+      FROM_HERE,
+      base::BindOnce(&OsIntegrationManager::UnregisterProtocolHandlers,
+                     weak_ptr_factory_.GetWeakPtr(), app_id,
+                     std::move(callback)));
+}
+
 std::unique_ptr<ShortcutInfo> OsIntegrationManager::BuildShortcutInfo(
     const AppId& app_id) {
   DCHECK(shortcut_manager_);
diff --git a/chrome/browser/web_applications/components/os_integration_manager.h b/chrome/browser/web_applications/components/os_integration_manager.h
index 6ecb113a..c431579 100644
--- a/chrome/browser/web_applications/components/os_integration_manager.h
+++ b/chrome/browser/web_applications/components/os_integration_manager.h
@@ -146,6 +146,8 @@
                                                     const GURL& protocol_url);
   virtual std::vector<ProtocolHandler> GetHandlersForProtocol(
       const std::string& protocol);
+  virtual std::vector<ProtocolHandler> GetAppProtocolHandlers(
+      const AppId& app_id);
 
   // Getter for testing FileHandlerManager
   FileHandlerManager& file_handler_manager_for_testing();
@@ -238,7 +240,9 @@
   virtual void UnregisterFileHandlers(const AppId& app_id,
                                       std::unique_ptr<ShortcutInfo> info,
                                       base::OnceCallback<void(bool)> callback);
-  virtual void UnregisterProtocolHandlers(const AppId& app_id);
+  virtual void UnregisterProtocolHandlers(
+      const AppId& app_id,
+      base::OnceCallback<void(bool)> callback);
   virtual void UnregisterUrlHandlers(const AppId& app_id);
   virtual void UnregisterWebAppOsUninstallation(const AppId& app_id);
 
@@ -250,6 +254,7 @@
       const AppId& app_id,
       FileHandlerUpdateAction file_handlers_need_os_update,
       std::unique_ptr<ShortcutInfo> info);
+  virtual void UpdateProtocolHandlers(const AppId& app_id);
 
   // Utility methods:
   virtual std::unique_ptr<ShortcutInfo> BuildShortcutInfo(const AppId& app_id);
diff --git a/chrome/browser/web_applications/components/os_integration_manager_unittest.cc b/chrome/browser/web_applications/components/os_integration_manager_unittest.cc
index b466097..e2f0e25 100644
--- a/chrome/browser/web_applications/components/os_integration_manager_unittest.cc
+++ b/chrome/browser/web_applications/components/os_integration_manager_unittest.cc
@@ -112,7 +112,7 @@
               (override));
   MOCK_METHOD(void,
               UnregisterProtocolHandlers,
-              (const AppId& app_id),
+              (const AppId& app_id, base::OnceCallback<void(bool)> callback),
               (override));
   MOCK_METHOD(void, UnregisterUrlHandlers, (const AppId& app_id), (override));
   MOCK_METHOD(void,
@@ -140,6 +140,7 @@
               (const AppId& app_id,
                base::OnceCallback<void(bool success)> callback),
               (override));
+  MOCK_METHOD(void, UpdateProtocolHandlers, (const AppId& app_id), (override));
 
   // Utility methods:
   MOCK_METHOD(std::unique_ptr<ShortcutInfo>,
@@ -280,7 +281,7 @@
       .WillOnce(base::test::RunOnceCallback<3>(true));
   EXPECT_CALL(manager, UnregisterFileHandlers(app_id, testing::_, testing::_))
       .Times(1);
-  EXPECT_CALL(manager, UnregisterProtocolHandlers(app_id)).Times(1);
+  EXPECT_CALL(manager, UnregisterProtocolHandlers(app_id, testing::_)).Times(1);
   EXPECT_CALL(manager, UnregisterUrlHandlers(app_id)).Times(1);
   EXPECT_CALL(manager, UnregisterWebAppOsUninstallation(app_id)).Times(1);
   EXPECT_CALL(manager, UnregisterShortcutsMenu(app_id))
@@ -315,6 +316,7 @@
   EXPECT_CALL(manager, UpdateShortcuts(app_id, old_name)).Times(1);
   EXPECT_CALL(manager, UpdateShortcutsMenu(app_id, testing::_)).Times(1);
   EXPECT_CALL(manager, UpdateUrlHandlers(app_id, testing::_)).Times(1);
+  EXPECT_CALL(manager, UpdateProtocolHandlers(app_id)).Times(1);
 
   manager.UpdateOsHooks(app_id, old_name, nullptr,
                         FileHandlerUpdateAction::kUpdate, web_app_info);
diff --git a/chrome/browser/web_applications/components/protocol_handler_manager.cc b/chrome/browser/web_applications/components/protocol_handler_manager.cc
index 7efcab7..6b4998a 100644
--- a/chrome/browser/web_applications/components/protocol_handler_manager.cc
+++ b/chrome/browser/web_applications/components/protocol_handler_manager.cc
@@ -92,8 +92,10 @@
   }
 }
 
-void ProtocolHandlerManager::UnregisterOsProtocolHandlers(const AppId& app_id) {
-  UnregisterProtocolHandlersWithOs(app_id, profile_);
+void ProtocolHandlerManager::UnregisterOsProtocolHandlers(
+    const AppId& app_id,
+    base::OnceCallback<void(bool)> callback) {
+  UnregisterProtocolHandlersWithOs(app_id, profile_, std::move(callback));
 }
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/components/protocol_handler_manager.h b/chrome/browser/web_applications/components/protocol_handler_manager.h
index 1e0b428d..616911c 100644
--- a/chrome/browser/web_applications/components/protocol_handler_manager.h
+++ b/chrome/browser/web_applications/components/protocol_handler_manager.h
@@ -58,7 +58,8 @@
       base::OnceCallback<void(bool)> callback);
 
   // Unregisters OS specific protocol handlers for an app.
-  void UnregisterOsProtocolHandlers(const AppId& app_id);
+  void UnregisterOsProtocolHandlers(const AppId& app_id,
+                                    base::OnceCallback<void(bool)> callback);
 
   AppRegistrar* app_registrar_;
 
diff --git a/chrome/browser/web_applications/components/web_app_protocol_handler_registration.cc b/chrome/browser/web_applications/components/web_app_protocol_handler_registration.cc
index c7cf5d8..ca1d2c88 100644
--- a/chrome/browser/web_applications/components/web_app_protocol_handler_registration.cc
+++ b/chrome/browser/web_applications/components/web_app_protocol_handler_registration.cc
@@ -23,10 +23,12 @@
 }
 
 // Unregisters protocol handlers for a web app with the OS.
-//
-// TODO(crbug.com/1174805): Add a callback as part of the protocol handling
-// unregistration flow.
-void UnregisterProtocolHandlersWithOs(const AppId& app_id, Profile* profile) {}
+void UnregisterProtocolHandlersWithOs(const AppId& app_id,
+                                      Profile* profile,
+                                      base::OnceCallback<void(bool)> callback) {
+  base::SequencedTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(callback), /*success=*/true));
+}
 #endif
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_protocol_handler_registration.h b/chrome/browser/web_applications/components/web_app_protocol_handler_registration.h
index 54feade..6976360b 100644
--- a/chrome/browser/web_applications/components/web_app_protocol_handler_registration.h
+++ b/chrome/browser/web_applications/components/web_app_protocol_handler_registration.h
@@ -26,7 +26,9 @@
     std::vector<apps::ProtocolHandlerInfo> protocol_handlers,
     base::OnceCallback<void(bool)> callback);
 
-void UnregisterProtocolHandlersWithOs(const AppId& app_id, Profile* profile);
+void UnregisterProtocolHandlersWithOs(const AppId& app_id,
+                                      Profile* profile,
+                                      base::OnceCallback<void(bool)> callback);
 
 }  // namespace web_app
 
diff --git a/chrome/browser/web_applications/components/web_app_protocol_handler_registration_win.cc b/chrome/browser/web_applications/components/web_app_protocol_handler_registration_win.cc
index b54defb..5292402 100644
--- a/chrome/browser/web_applications/components/web_app_protocol_handler_registration_win.cc
+++ b/chrome/browser/web_applications/components/web_app_protocol_handler_registration_win.cc
@@ -134,14 +134,16 @@
                      app_id, std::move(callback)));
 }
 
-void UnregisterProtocolHandlersWithOs(const AppId& app_id, Profile* profile) {
+void UnregisterProtocolHandlersWithOs(const AppId& app_id,
+                                      Profile* profile,
+                                      base::OnceCallback<void(bool)> callback) {
   base::ThreadPool::PostTaskAndReply(
       FROM_HERE,
       {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
       base::BindOnce(&UnregisterProtocolHandlersWithOsInBackground, app_id,
                      profile->GetPath()),
       base::BindOnce(&CheckAndUpdateExternalInstallations, profile->GetPath(),
-                     app_id, base::DoNothing::Once<bool>()));
+                     app_id, std::move(callback)));
 }
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_protocol_handler_registration_win_unittest.cc b/chrome/browser/web_applications/components/web_app_protocol_handler_registration_win_unittest.cc
index df8750b..fd4f41e 100644
--- a/chrome/browser/web_applications/components/web_app_protocol_handler_registration_win_unittest.cc
+++ b/chrome/browser/web_applications/components/web_app_protocol_handler_registration_win_unittest.cc
@@ -242,10 +242,14 @@
   AddAndVerifyProtocolAssociations(kApp1Id, kApp1Name, kApp1Url, profile2,
                                    " (Profile 2)");
 
-  UnregisterProtocolHandlersWithOs(kApp1Id, GetProfile());
-  base::ThreadPoolInstance::Get()->FlushForTesting();
-  base::RunLoop().RunUntilIdle();
-  base::ThreadPoolInstance::Get()->FlushForTesting();
+  base::RunLoop run_loop;
+  UnregisterProtocolHandlersWithOs(
+      kApp1Id, GetProfile(), base::BindLambdaForTesting([&](bool success) {
+        EXPECT_TRUE(success);
+        run_loop.Quit();
+      }));
+  run_loop.Run();
+
   EXPECT_FALSE(base::PathExists(app_specific_launcher_path));
 
   // Verify that "(Profile 2)" was removed from the web app launcher and
@@ -282,9 +286,13 @@
       ShellUtil::GetApplicationPathForProgId(
           GetProgIdForApp(GetProfile()->GetPath(), kApp1Id));
 
-  UnregisterProtocolHandlersWithOs(kApp1Id, GetProfile());
-  base::ThreadPoolInstance::Get()->FlushForTesting();
-  base::RunLoop().RunUntilIdle();
+  base::RunLoop run_loop;
+  UnregisterProtocolHandlersWithOs(
+      kApp1Id, GetProfile(), base::BindLambdaForTesting([&](bool success) {
+        EXPECT_TRUE(success);
+        run_loop.Quit();
+      }));
+  run_loop.Run();
 
   EXPECT_FALSE(base::PathExists(app_specific_launcher_path));
   EXPECT_FALSE(ProgIdRegisteredForProtocol("mailto", kApp1Id, GetProfile()));
diff --git a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
index f486ac7..b1f9d9a0 100644
--- a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
+++ b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
@@ -2574,4 +2574,179 @@
 }
 #endif
 
+class ManifestUpdateManagerBrowserTestWithProtocolHandling
+    : public ManifestUpdateManagerBrowserTest {
+ public:
+  ManifestUpdateManagerBrowserTestWithProtocolHandling() {
+    scoped_feature_list_.InitAndEnableFeature(
+        blink::features::kWebAppEnableProtocolHandlers);
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTestWithProtocolHandling,
+                       CheckFindsAddedProtocolHandler) {
+  constexpr char kManifestTemplate[] = R"(
+    {
+      "name": "Test app name",
+      "start_url": ".",
+      "scope": "/",
+      "display": "minimal-ui",
+      "icons": $1
+    }
+  )";
+
+  constexpr char kProtocolHandlerManifestTemplate[] = R"(
+    {
+      "name": "Test app name",
+      "start_url": ".",
+      "scope": "/",
+      "display": "minimal-ui",
+      "protocol_handlers": [
+        {
+          "protocol": "mailto",
+          "url": "?mailto=%s"
+        }
+      ],
+      "icons": $1
+    }
+  )";
+
+  OverrideManifest(kManifestTemplate, {kInstallableIconList});
+  AppId app_id = InstallWebApp();
+
+  OverrideManifest(kProtocolHandlerManifestTemplate, {kInstallableIconList});
+  EXPECT_EQ(ManifestUpdateResult::kAppUpdated,
+            GetResultAfterPageLoad(GetAppURL(), &app_id));
+  histogram_tester_.ExpectBucketCount(kUpdateHistogramName,
+                                      ManifestUpdateResult::kAppUpdated, 1);
+
+  const WebApp* web_app =
+      GetProvider().registrar().AsWebAppRegistrar()->GetAppById(app_id);
+  EXPECT_FALSE(web_app->protocol_handlers().empty());
+  const auto& protocol_handler = web_app->protocol_handlers()[0];
+  EXPECT_EQ("mailto", protocol_handler.protocol);
+  EXPECT_EQ(http_server_.GetURL("/banners/manifest.json?mailto=%s"),
+            protocol_handler.url.spec());
+}
+
+IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTestWithProtocolHandling,
+                       CheckIgnoresUnchangedProtocolHandler) {
+  constexpr char kProtocolHandlerManifestTemplate[] = R"(
+    {
+      "name": "Test app name",
+      "start_url": ".",
+      "scope": "/",
+      "display": "minimal-ui",
+      "protocol_handlers": [
+        {
+          "protocol": "mailto",
+          "url": "?mailto=%s"
+        }
+      ],
+      "icons": $1
+    }
+  )";
+
+  OverrideManifest(kProtocolHandlerManifestTemplate, {kInstallableIconList});
+  AppId app_id = InstallWebApp();
+
+  OverrideManifest(kProtocolHandlerManifestTemplate, {kInstallableIconList});
+  EXPECT_EQ(ManifestUpdateResult::kAppUpToDate,
+            GetResultAfterPageLoad(GetAppURL(), &app_id));
+  histogram_tester_.ExpectBucketCount(kUpdateHistogramName,
+                                      ManifestUpdateResult::kAppUpToDate, 1);
+
+  const WebApp* web_app =
+      GetProvider().registrar().AsWebAppRegistrar()->GetAppById(app_id);
+  EXPECT_FALSE(web_app->protocol_handlers().empty());
+}
+
+IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTestWithProtocolHandling,
+                       CheckFindsChangedProtocolHandler) {
+  constexpr char kProtocolHandlerManifestTemplate[] = R"(
+    {
+      "name": "Test app name",
+      "start_url": ".",
+      "scope": "/",
+      "display": "minimal-ui",
+      "protocol_handlers": [
+        {
+          "protocol": "$1",
+          "url": "?$2=%s"
+        }
+      ],
+      "icons": $3
+    }
+  )";
+
+  OverrideManifest(kProtocolHandlerManifestTemplate,
+                   {"mailto", "mailto", kInstallableIconList});
+  AppId app_id = InstallWebApp();
+  const WebApp* web_app =
+      GetProvider().registrar().AsWebAppRegistrar()->GetAppById(app_id);
+  EXPECT_EQ(1u, web_app->protocol_handlers().size());
+  const auto& old_protocol_handler = web_app->protocol_handlers()[0];
+  EXPECT_EQ("mailto", old_protocol_handler.protocol);
+  EXPECT_EQ(http_server_.GetURL("/banners/manifest.json?mailto=%s"),
+            old_protocol_handler.url.spec());
+
+  OverrideManifest(kProtocolHandlerManifestTemplate,
+                   {"web+mailto", "web+mailto", kInstallableIconList});
+  EXPECT_EQ(ManifestUpdateResult::kAppUpdated,
+            GetResultAfterPageLoad(GetAppURL(), &app_id));
+  histogram_tester_.ExpectBucketCount(kUpdateHistogramName,
+                                      ManifestUpdateResult::kAppUpdated, 1);
+
+  EXPECT_EQ(1u, web_app->protocol_handlers().size());
+  const auto& new_protocol_handler = web_app->protocol_handlers()[0];
+  EXPECT_EQ("web+mailto", new_protocol_handler.protocol);
+  EXPECT_EQ(http_server_.GetURL("/banners/manifest.json?web+mailto=%s"),
+            new_protocol_handler.url.spec());
+}
+
+IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTestWithProtocolHandling,
+                       CheckFindsDeletedProtocolHandler) {
+  constexpr char kProtocolHandlerManifestTemplate[] = R"(
+    {
+      "name": "Test app name",
+      "start_url": ".",
+      "scope": "/",
+      "display": "minimal-ui",
+      "protocol_handlers": [
+        {
+          "protocol": "mailto",
+          "url": "?mailto=%s"
+        }
+      ],
+      "icons": $1
+    }
+  )";
+
+  constexpr char kManifestTemplate[] = R"(
+    {
+      "name": "Test app name",
+      "start_url": ".",
+      "scope": "/",
+      "display": "minimal-ui",
+      "icons": $1
+    }
+  )";
+
+  OverrideManifest(kProtocolHandlerManifestTemplate, {kInstallableIconList});
+  AppId app_id = InstallWebApp();
+
+  OverrideManifest(kManifestTemplate, {kInstallableIconList});
+  EXPECT_EQ(ManifestUpdateResult::kAppUpdated,
+            GetResultAfterPageLoad(GetAppURL(), &app_id));
+  histogram_tester_.ExpectBucketCount(kUpdateHistogramName,
+                                      ManifestUpdateResult::kAppUpdated, 1);
+
+  const WebApp* web_app =
+      GetProvider().registrar().AsWebAppRegistrar()->GetAppById(app_id);
+  EXPECT_TRUE(web_app->protocol_handlers().empty());
+}
+
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/manifest_update_task.cc b/chrome/browser/web_applications/manifest_update_task.cc
index ea08be6f..7fcb57d 100644
--- a/chrome/browser/web_applications/manifest_update_task.cc
+++ b/chrome/browser/web_applications/manifest_update_task.cc
@@ -134,6 +134,29 @@
   return false;
 }
 
+bool HaveProtocolHandlersChanged(
+    const apps::ProtocolHandlers* old_handlers,
+    const std::vector<blink::Manifest::ProtocolHandler>& new_handlers) {
+  if (!old_handlers)
+    return true;
+
+  if (old_handlers->size() != new_handlers.size())
+    return true;
+
+  for (size_t i = 0; i < old_handlers->size(); ++i) {
+    // Compare apps::ProtocolHandlerInfo and blink::Manifest::ProtocolHandler.
+    const apps::ProtocolHandlerInfo& old_handler = (*old_handlers)[i];
+    const blink::Manifest::ProtocolHandler& new_handler = new_handlers[i];
+
+    if (old_handler.protocol != base::UTF16ToUTF8(new_handler.protocol))
+      return true;
+
+    if (old_handler.url != new_handler.url)
+      return true;
+  }
+  return false;
+}
+
 ManifestUpdateTask::ManifestUpdateTask(
     const GURL& url,
     const AppId& app_id,
@@ -288,6 +311,12 @@
     return true;
   }
 
+  if (HaveProtocolHandlersChanged(
+          /*old_handlers=*/registrar_.GetAppProtocolHandlers(app_id_),
+          /*new_handlers=*/web_application_info_->protocol_handlers)) {
+    return true;
+  }
+
   if (web_application_info_->capture_links !=
       registrar_.GetAppCaptureLinks(app_id_)) {
     return true;
diff --git a/chrome/browser/web_applications/manifest_update_task.h b/chrome/browser/web_applications/manifest_update_task.h
index cd65afb5..527deeb 100644
--- a/chrome/browser/web_applications/manifest_update_task.h
+++ b/chrome/browser/web_applications/manifest_update_task.h
@@ -15,6 +15,7 @@
 #include "chrome/browser/web_applications/components/web_application_info.h"
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/services/app_service/public/cpp/file_handler.h"
+#include "components/services/app_service/public/cpp/protocol_handler_info.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/manifest/manifest.h"
@@ -34,6 +35,12 @@
     const apps::FileHandlers* old_handlers,
     const std::vector<blink::Manifest::FileHandler>& new_handlers);
 
+// Checks whether protocol handlers have changed. Ignores differences in
+// ordering, which may change after being inserted into a set or map.
+bool HaveProtocolHandlersChanged(
+    const apps::ProtocolHandlers* old_handlers,
+    const std::vector<blink::Manifest::ProtocolHandler>& new_handlers);
+
 class AppIconManager;
 class AppRegistrar;
 class WebAppUiManager;
diff --git a/chrome/browser/web_applications/test/test_app_registrar.cc b/chrome/browser/web_applications/test/test_app_registrar.cc
index 752d2fab..a135e8a 100644
--- a/chrome/browser/web_applications/test/test_app_registrar.cc
+++ b/chrome/browser/web_applications/test/test_app_registrar.cc
@@ -137,6 +137,11 @@
   return nullptr;
 }
 
+const apps::ProtocolHandlers* TestAppRegistrar::GetAppProtocolHandlers(
+    const AppId& app_id) const {
+  return nullptr;
+}
+
 bool TestAppRegistrar::IsAppFileHandlerPermissionBlocked(
     const web_app::AppId& app_id) const {
   return false;
diff --git a/chrome/browser/web_applications/test/test_app_registrar.h b/chrome/browser/web_applications/test/test_app_registrar.h
index 5bc079e..7c79b08 100644
--- a/chrome/browser/web_applications/test/test_app_registrar.h
+++ b/chrome/browser/web_applications/test/test_app_registrar.h
@@ -70,6 +70,8 @@
       const AppId& app_id) const override;
   const apps::FileHandlers* GetAppFileHandlers(
       const AppId& app_id) const override;
+  const apps::ProtocolHandlers* GetAppProtocolHandlers(
+      const AppId& app_id) const override;
   bool IsAppFileHandlerPermissionBlocked(
       const web_app::AppId& app_id) const override;
   absl::optional<GURL> GetAppScopeInternal(const AppId& app_id) const override;
diff --git a/chrome/browser/web_applications/web_app_registrar.cc b/chrome/browser/web_applications/web_app_registrar.cc
index 566a1fd3..6f0bdc0 100644
--- a/chrome/browser/web_applications/web_app_registrar.cc
+++ b/chrome/browser/web_applications/web_app_registrar.cc
@@ -152,6 +152,12 @@
   return web_app ? &web_app->file_handlers() : nullptr;
 }
 
+const apps::ProtocolHandlers* WebAppRegistrar::GetAppProtocolHandlers(
+    const AppId& app_id) const {
+  auto* web_app = GetAppById(app_id);
+  return web_app ? &web_app->protocol_handlers() : nullptr;
+}
+
 bool WebAppRegistrar::IsAppFileHandlerPermissionBlocked(
     const web_app::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
diff --git a/chrome/browser/web_applications/web_app_registrar.h b/chrome/browser/web_applications/web_app_registrar.h
index 22d326f..4c94599 100644
--- a/chrome/browser/web_applications/web_app_registrar.h
+++ b/chrome/browser/web_applications/web_app_registrar.h
@@ -68,6 +68,8 @@
       const AppId& app_id) const override;
   const apps::FileHandlers* GetAppFileHandlers(
       const AppId& app_id) const override;
+  const apps::ProtocolHandlers* GetAppProtocolHandlers(
+      const AppId& app_id) const override;
   bool IsAppFileHandlerPermissionBlocked(
       const web_app::AppId& app_id) const override;
   absl::optional<GURL> GetAppScopeInternal(const AppId& app_id) const override;
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 8c0f6bd0..cae7b69 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-master-1621608799-749456934e595384e13c7908f6a5d0c8462bd2e1.profdata
+chrome-win32-master-1621630772-36788a0eb81f240735a9457bfe3e528c4e40dafa.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 45d1e1a4..a9781a0 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-master-1621608799-68f509a28cd5aebcefa69a20e008b949801e880f.profdata
+chrome-win64-master-1621619906-5cc86b5858d58114cf85995b693f6fc6ebfc59a3.profdata
diff --git a/chrome/renderer/subresource_redirect/login_robots_decider_agent.cc b/chrome/renderer/subresource_redirect/login_robots_decider_agent.cc
index 9d9d887..2f62e9e 100644
--- a/chrome/renderer/subresource_redirect/login_robots_decider_agent.cc
+++ b/chrome/renderer/subresource_redirect/login_robots_decider_agent.cc
@@ -24,6 +24,10 @@
     RobotsRulesParser::CheckResult check_result) {
   switch (check_result) {
     case RobotsRulesParser::CheckResult::kAllowed:
+      if (ShouldEnableLoginRobotsCheckedImageCompression() &&
+          !ShouldCompressRedirectSubresource()) {
+        return SubresourceRedirectResult::kIneligibleCompressionDisabled;
+      }
       return SubresourceRedirectResult::kRedirectable;
     case RobotsRulesParser::CheckResult::kDisallowed:
     case RobotsRulesParser::CheckResult::kInvalidated:
diff --git a/chrome/renderer/subresource_redirect/public_image_hints_decider_agent.cc b/chrome/renderer/subresource_redirect/public_image_hints_decider_agent.cc
index 5a63ed3c..b34afbe5 100644
--- a/chrome/renderer/subresource_redirect/public_image_hints_decider_agent.cc
+++ b/chrome/renderer/subresource_redirect/public_image_hints_decider_agent.cc
@@ -93,6 +93,8 @@
 
   if (public_image_urls_->find(GetURLForPublicDecision(url)) !=
       public_image_urls_->end()) {
+    if (!ShouldCompressRedirectSubresource())
+      return SubresourceRedirectResult::kIneligibleCompressionDisabled;
     return SubresourceRedirectResult::kRedirectable;
   }
 
@@ -160,6 +162,7 @@
     case SubresourceRedirectResult::kIneligibleRedirectFailed:
     case SubresourceRedirectResult::kIneligibleBlinkDisallowed:
     case SubresourceRedirectResult::kIneligibleSubframeResource:
+    case SubresourceRedirectResult::kIneligibleCompressionDisabled:
       public_image_compression_data_use.SetIneligibleOtherImageBytes(
           content_length);
       break;
diff --git a/chrome/renderer/subresource_redirect/subresource_redirect_url_loader_throttle.cc b/chrome/renderer/subresource_redirect/subresource_redirect_url_loader_throttle.cc
index eb139e4..983fe04 100644
--- a/chrome/renderer/subresource_redirect/subresource_redirect_url_loader_throttle.cc
+++ b/chrome/renderer/subresource_redirect/subresource_redirect_url_loader_throttle.cc
@@ -150,9 +150,6 @@
   if (IsCompressionServerOrigin(request->url))
     return;
 
-  if (!ShouldCompressRedirectSubresource())
-    return;
-
   if (login_robots_compression_metrics_)
     login_robots_compression_metrics_->NotifyRequestStart();
 
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index fd408fe..935e2aa 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2561,6 +2561,7 @@
         "../browser/ui/views/translate/translate_bubble_view_browsertest.cc",
         "../browser/ui/views/translate/translate_language_browsertest.cc",
         "../browser/ui/views/user_education/feature_promo_dialog_browsertest.cc",
+        "../browser/ui/views/user_education/interaction_sequence_browsertest.cc",
         "../browser/ui/views/user_education/tip_marquee_view_browsertest.cc",
         "../browser/ui/views/user_education/tutorial_dialog_browsertest.cc",
         "../browser/ui/views/web_apps/web_app_uninstall_dialog_browsertest.cc",
@@ -4548,6 +4549,7 @@
     assert(toolkit_views)
     sources += [ "../browser/ui/startup/credential_provider_signin_info_fetcher_win_unittest.cc" ]
     deps += [
+      "//chrome:packed_resources_integrity",
       "//chrome/browser/win/conflicts:unit_tests",
       "//chrome/test:credential_provider_test_utils",
     ]
@@ -8192,3 +8194,47 @@
   sources =
       [ "../browser/persisted_state_db/profile_proto_db_test_proto.proto" ]
 }
+
+# This target is defined for Lacros testing.
+# See //chrome/test/base/chromeos/README.md for more information.
+if (is_chromeos_ash) {
+  assert(use_aura)
+
+  _target_name = "test_ash_chrome"
+  executable(_target_name) {
+    output_name = _target_name
+
+    sources = [
+      "//chrome/app/chrome_exe_main_aura.cc",
+      "//chrome/app/chrome_main_delegate.cc",
+      "//chrome/app/chrome_main_delegate.h",
+      "base/chromeos/fake_ash_test_chrome_browser_main_extra_parts.cc",
+      "base/chromeos/fake_ash_test_chrome_browser_main_extra_parts.h",
+      "base/chromeos/test_chrome_base.cc",
+      "base/chromeos/test_chrome_base.h",
+      "base/chromeos/test_chrome_main.cc",
+    ]
+    deps = [
+      "//chromeos/services/machine_learning/public/cpp:stub",
+
+      # On Linux, link the dependencies (libraries) that make up actual
+      # Chromium functionality directly into the executable.
+      "//chrome:browser_dependencies",
+      "//chrome:child_dependencies",
+
+      # For the sampling profiler.
+      # The way it's currently implemented requires us to keep it, but from a
+      # technical perspective it shouldn't be necessary
+      "//chrome/common/profiler",
+      "//content/public/app",
+
+      # For headless mode.
+      "//headless:headless_shell_lib",
+    ]
+    data = [ "$root_out_dir/resources.pak" ]
+    data_deps = [
+      # The step's output are needed at runtime, so we also need a data_dep.
+      "//chrome:packed_resources",
+    ]
+  }
+}
diff --git a/chrome/test/base/chromeos/DEPS b/chrome/test/base/chromeos/DEPS
new file mode 100644
index 0000000..ee1d1d26
--- /dev/null
+++ b/chrome/test/base/chromeos/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+headless",
+]
diff --git a/chrome/test/base/chromeos/OWNERS b/chrome/test/base/chromeos/OWNERS
new file mode 100644
index 0000000..aae4f73
--- /dev/null
+++ b/chrome/test/base/chromeos/OWNERS
@@ -0,0 +1,3 @@
+svenzheng@chromium.org
+liaoyuke@chromium.org
+erikchen@chromium.org
diff --git a/chrome/test/base/chromeos/README.md b/chrome/test/base/chromeos/README.md
new file mode 100644
index 0000000..a25bbf5
--- /dev/null
+++ b/chrome/test/base/chromeos/README.md
@@ -0,0 +1,13 @@
+This is for Lacros testing on Linux.
+
+This directory contains code that is compiled into Ash-chrome.
+The tests themselves are compiled into binaries based on Lacros,
+which communicate to this copy of Ash-chrome over crosapi.
+
+When you need to write a Lacros gtest(unit test, browser test, etc), and
+you need to change Ash's behavior, you can change here.
+As an example, ml service client library requires the ml service daemon,
+which is not present in the unit test or browser test environment. So they
+need a fake ml service in ash. With that, they need to install the fake
+component in
+//chrome/test/base/chromeos/fake_ash_test_chrome_browser_main_extra_parts.cc.
diff --git a/chrome/test/base/chromeos/fake_ash_test_chrome_browser_main_extra_parts.cc b/chrome/test/base/chromeos/fake_ash_test_chrome_browser_main_extra_parts.cc
new file mode 100644
index 0000000..947b4cc
--- /dev/null
+++ b/chrome/test/base/chromeos/fake_ash_test_chrome_browser_main_extra_parts.cc
@@ -0,0 +1,27 @@
+// Copyright 2021 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 "fake_ash_test_chrome_browser_main_extra_parts.h"
+#include "chromeos/services/machine_learning/public/cpp/fake_service_connection.h"
+
+namespace test {
+
+FakeAshTestChromeBrowserMainExtraParts::
+    FakeAshTestChromeBrowserMainExtraParts() = default;
+
+FakeAshTestChromeBrowserMainExtraParts::
+    ~FakeAshTestChromeBrowserMainExtraParts() = default;
+
+void FakeAshTestChromeBrowserMainExtraParts::PostBrowserStart() {
+  // Fake ML service is needed because ml service client library
+  // requires the ml service daemon, which is not present in the
+  // unit test or browser test environment.
+  auto* fake_service_connection =
+      new chromeos::machine_learning::FakeServiceConnectionImpl();
+  fake_service_connection->Initialize();
+  chromeos::machine_learning::ServiceConnection::
+      UseFakeServiceConnectionForTesting(fake_service_connection);
+}
+
+}  // namespace test
diff --git a/chrome/test/base/chromeos/fake_ash_test_chrome_browser_main_extra_parts.h b/chrome/test/base/chromeos/fake_ash_test_chrome_browser_main_extra_parts.h
new file mode 100644
index 0000000..e6bc607
--- /dev/null
+++ b/chrome/test/base/chromeos/fake_ash_test_chrome_browser_main_extra_parts.h
@@ -0,0 +1,27 @@
+// Copyright 2021 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_TEST_BASE_CHROMEOS_FAKE_ASH_TEST_CHROME_BROWSER_MAIN_EXTRA_PARTS_H_
+#define CHROME_TEST_BASE_CHROMEOS_FAKE_ASH_TEST_CHROME_BROWSER_MAIN_EXTRA_PARTS_H_
+
+#include "chrome/browser/chrome_browser_main_extra_parts.h"
+
+namespace test {
+
+class FakeAshTestChromeBrowserMainExtraParts
+    : public ChromeBrowserMainExtraParts {
+ public:
+  FakeAshTestChromeBrowserMainExtraParts();
+  FakeAshTestChromeBrowserMainExtraParts(
+      const FakeAshTestChromeBrowserMainExtraParts&) = delete;
+  FakeAshTestChromeBrowserMainExtraParts& operator=(
+      const FakeAshTestChromeBrowserMainExtraParts&) = delete;
+  ~FakeAshTestChromeBrowserMainExtraParts() override;
+
+  void PostBrowserStart() override;
+};
+
+}  // namespace test
+
+#endif  // CHROME_TEST_BASE_CHROMEOS_FAKE_ASH_TEST_CHROME_BROWSER_MAIN_EXTRA_PARTS_H_
diff --git a/chrome/test/base/chromeos/test_chrome_base.cc b/chrome/test/base/chromeos/test_chrome_base.cc
new file mode 100644
index 0000000..2a2e3db
--- /dev/null
+++ b/chrome/test/base/chromeos/test_chrome_base.cc
@@ -0,0 +1,52 @@
+// Copyright 2021 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 "test_chrome_base.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "chrome/browser/chrome_browser_main.h"
+#include "chrome/test/base/chromeos/fake_ash_test_chrome_browser_main_extra_parts.h"
+#include "content/public/browser/browser_main_parts.h"
+#include "headless/public/headless_shell.h"
+#include "ui/gfx/switches.h"
+
+namespace test {
+
+TestChromeBase::TestChromeBase(const content::ContentMainParams& params)
+    : params_(params) {
+  auto created_main_parts_closure =
+      std::make_unique<content::CreatedMainPartsClosure>(
+          base::BindOnce(&TestChromeBase::CreatedBrowserMainPartsImpl,
+                         weak_ptr_factory_.GetWeakPtr()));
+  params_.created_main_parts_closure = created_main_parts_closure.release();
+}
+
+TestChromeBase::~TestChromeBase() = default;
+
+int TestChromeBase::Start() {
+  int rv = 0;
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless)) {
+    rv = headless::HeadlessShellMain(params_);
+  } else {
+    rv = content::ContentMain(params_);
+  }
+  return rv;
+}
+
+void TestChromeBase::CreatedBrowserMainPartsImpl(
+    content::BrowserMainParts* browser_main_parts) {
+  browser_main_parts_ =
+      static_cast<ChromeBrowserMainParts*>(browser_main_parts);
+  CreateFakeAshTestChromeBrowserMainExtraParts();
+}
+
+void TestChromeBase::CreateFakeAshTestChromeBrowserMainExtraParts() {
+  browser_main_parts_->AddParts(
+      std::make_unique<test::FakeAshTestChromeBrowserMainExtraParts>());
+}
+
+}  // namespace test
diff --git a/chrome/test/base/chromeos/test_chrome_base.h b/chrome/test/base/chromeos/test_chrome_base.h
new file mode 100644
index 0000000..0eed0e3a
--- /dev/null
+++ b/chrome/test/base/chromeos/test_chrome_base.h
@@ -0,0 +1,43 @@
+// Copyright 2021 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_TEST_BASE_CHROMEOS_TEST_CHROME_BASE_H_
+#define CHROME_TEST_BASE_CHROMEOS_TEST_CHROME_BASE_H_
+
+#include "base/memory/weak_ptr.h"
+#include "content/public/app/content_main.h"
+
+namespace content {
+class BrowserMainParts;
+}
+class ChromeBrowserMainParts;
+
+namespace test {
+
+class TestChromeBase {
+ public:
+  explicit TestChromeBase(const content::ContentMainParams& params);
+  TestChromeBase(const TestChromeBase&) = delete;
+  TestChromeBase& operator=(const TestChromeBase&) = delete;
+  ~TestChromeBase();
+
+  // Start the browser.
+  int Start();
+
+  // Captures |browser_main_parts_| so main parts can be added in tests.
+  void CreatedBrowserMainPartsImpl(
+      content::BrowserMainParts* browser_main_parts);
+
+  // Create fake ash browser main extra parts.
+  void CreateFakeAshTestChromeBrowserMainExtraParts();
+
+ private:
+  content::ContentMainParams params_;
+  ChromeBrowserMainParts* browser_main_parts_ = nullptr;
+  base::WeakPtrFactory<TestChromeBase> weak_ptr_factory_{this};
+};
+
+}  // namespace test
+
+#endif  // CHROME_TEST_BASE_CHROMEOS_TEST_CHROME_BASE_H_
diff --git a/chrome/test/base/chromeos/test_chrome_main.cc b/chrome/test/base/chromeos/test_chrome_main.cc
new file mode 100644
index 0000000..95febb0
--- /dev/null
+++ b/chrome/test/base/chromeos/test_chrome_main.cc
@@ -0,0 +1,40 @@
+// Copyright 2021 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 <cstdint>
+
+#include "base/command_line.h"
+#include "base/time/time.h"
+#include "chrome/app/chrome_main_delegate.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/profiler/main_thread_stack_sampling_profiler.h"
+#include "chrome/test/base/chromeos/test_chrome_base.h"
+
+extern "C" {
+__attribute__((visibility("default"))) int ChromeMain(int argc,
+                                                      const char** argv);
+}
+
+int ChromeMain(int argc, const char** argv) {
+  ChromeMainDelegate chrome_main_delegate(base::TimeTicks::Now());
+  content::ContentMainParams params(&chrome_main_delegate);
+
+  params.argc = argc;
+  params.argv = argv;
+  base::CommandLine::Init(params.argc, params.argv);
+
+  // Start the sampling profiler as early as possible - namely, once the command
+  // line data is available. Allocated as an object on the stack to ensure that
+  // the destructor runs on shutdown, which is important to avoid the profiler
+  // thread's destruction racing with main thread destruction.
+  // This is the same as
+  // https://source.chromium.org/chromium/chromium/src/+/main:chrome/app/chrome_main.cc?q=scoped_sampling_profiler
+  // The way it's currently implemented requires us to keep it, but from a
+  // technical perspective it shouldn't be necessary. There's no need to
+  // run the sampling profiler for test ash chrome.
+  MainThreadStackSamplingProfiler scoped_sampling_profiler;
+
+  test::TestChromeBase test_chrome_base(params);
+  return test_chrome_base.Start();
+}
diff --git a/chrome/test/base/find_result_waiter.cc b/chrome/test/base/find_result_waiter.cc
index d221f33..48b4739 100644
--- a/chrome/test/base/find_result_waiter.cc
+++ b/chrome/test/base/find_result_waiter.cc
@@ -16,7 +16,7 @@
       find_in_page::FindTabHelper::FromWebContents(parent_tab);
   current_find_request_id_ = find_tab_helper->current_find_request_id() +
       request_offset;
-  observer_.Add(find_tab_helper);
+  observation_.Observe(find_tab_helper);
 }
 
 FindResultWaiter::~FindResultWaiter() = default;
diff --git a/chrome/test/base/find_result_waiter.h b/chrome/test/base/find_result_waiter.h
index 7c3cf8d5..07d17c3 100644
--- a/chrome/test/base/find_result_waiter.h
+++ b/chrome/test/base/find_result_waiter.h
@@ -7,7 +7,7 @@
 
 #include <memory>
 
-#include "base/scoped_observer.h"
+#include "base/scoped_observation.h"
 #include "components/find_in_page/find_result_observer.h"
 #include "components/find_in_page/find_tab_helper.h"
 #include "ui/gfx/geometry/rect.h"
@@ -53,8 +53,9 @@
   void OnFindResultAvailable(content::WebContents* web_contents) override;
 
   std::unique_ptr<base::RunLoop> run_loop_;
-  ScopedObserver<find_in_page::FindTabHelper, find_in_page::FindResultObserver>
-      observer_{this};
+  base::ScopedObservation<find_in_page::FindTabHelper,
+                          find_in_page::FindResultObserver>
+      observation_{this};
 
   // We will at some point (before final update) be notified of the ordinal and
   // we need to preserve it so we can send it later.
diff --git a/chrome/test/base/ui_test_utils.cc b/chrome/test/base/ui_test_utils.cc
index b8db7656..539ab04 100644
--- a/chrome/test/base/ui_test_utils.cc
+++ b/chrome/test/base/ui_test_utils.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "chrome/test/base/ui_test_utils.h"
+#include "base/scoped_observation.h"
 
 #include <stddef.h>
 
@@ -163,7 +164,7 @@
 class AutocompleteChangeObserver : public AutocompleteController::Observer {
  public:
   explicit AutocompleteChangeObserver(Profile* profile) {
-    scoped_observer_.Add(
+    scoped_observation_.Observe(
         OmniboxControllerEmitter::GetForBrowserContext(profile));
   }
 
@@ -183,8 +184,9 @@
 
  private:
   base::RunLoop run_loop_;
-  ScopedObserver<OmniboxControllerEmitter, AutocompleteController::Observer>
-      scoped_observer_{this};
+  base::ScopedObservation<OmniboxControllerEmitter,
+                          AutocompleteController::Observer>
+      scoped_observation_{this};
 };
 
 }  // namespace
@@ -560,9 +562,10 @@
     scoped_refptr<content::MessageLoopRunner> runner =
         new content::MessageLoopRunner;
     WaitHistoryLoadedObserver observer(runner.get());
-    ScopedObserver<history::HistoryService, history::HistoryServiceObserver>
+    base::ScopedObservation<history::HistoryService,
+                            history::HistoryServiceObserver>
         scoped_observer(&observer);
-    scoped_observer.Add(history_service);
+    scoped_observer.Observe(history_service);
     runner->Run();
   }
 }
diff --git a/chrome/test/data/autofill/shadowdom.html b/chrome/test/data/autofill/shadowdom.html
deleted file mode 100644
index 6f2050d..0000000
--- a/chrome/test/data/autofill/shadowdom.html
+++ /dev/null
@@ -1,81 +0,0 @@
-<!DOCTYPE html>
-
-<p>go to chrome://settings/addresses to set up autofill</p>
-<p>autofill is not supported in file:// urls</p>
-
-<form>
-  <div>
-    <label for=input1>name</label>
-    <span id=input1>
-      <template shadowroot=open>
-        <span>
-          <template shadowroot=open>
-            <input>
-          </template>
-        </span>
-      </template>
-    </span>
-  </div>
-  <div>
-    <label for=input2>address</label>
-    <span id=input2>
-      <template shadowroot=open>
-        <input>
-      </template>
-    </span>
-  </div>
-  <div>
-    <label for=input3>city</label>
-    <span id=input3>
-      <template shadowroot=open>
-        <input id=shadowinput name=shadowname>
-      </template>
-    </span>
-  </div>
-  <div>
-    <label for=input4>state</label>
-    <span id=input4>
-      <template shadowroot=open>
-        <select>
-          <option value=WA>WA</option>
-          <option value=CA>CA</option>
-          <option value=TX>TX</option>
-        </select>
-      </template>
-    </span>
-  </div>
-  <div>
-    <label for=input5>zip</label>
-    <span id=input5>
-      <template shadowroot=open>
-        <input id=shadowinput>
-      </template>
-    </span>
-  </div>
-</form>
-
-<script>
-function getNameElement() {
-  return input1.shadowRoot.querySelector('span').shadowRoot.querySelector('input');
-}
-
-function getName() {
-  return getNameElement().value;
-}
-
-function getAddress() {
-  return input2.shadowRoot.querySelector('input').value;
-}
-
-function getCity() {
-  return input3.shadowRoot.querySelector('input').value;
-}
-
-function getState() {
-  return input4.shadowRoot.querySelector('select').value;
-}
-
-function getZip() {
-  return input5.shadowRoot.querySelector('input').value;
-}
-</script>
diff --git a/chrome/test/data/extensions/api_test/service_worker/worker_based_background/storage/service_worker_background.js b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/storage/service_worker_background.js
index 4b3579bd..3597be95 100644
--- a/chrome/test/data/extensions/api_test/service_worker/worker_based_background/storage/service_worker_background.js
+++ b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/storage/service_worker_background.js
@@ -93,6 +93,9 @@
   }
 };
 
+// TODO(emiliapaz): After all `session` functions are added, create
+// an array of objects(storage_area, key, value) that loops through the tests
+// since they are the same.
 var localKey = '_local_key';
 var localValue = 'this is a local value';
 var syncKey = '_sync_key';
@@ -152,4 +155,10 @@
   function testSessionOnStorageChanged() {
     testOnStorageChanged(chrome.storage.session);
   },
+  function testSessionClearSetup() {
+    testSetStorage(chrome.storage.session, sessionKey, sessionValue);
+  },
+  function testSessionClear() {
+    testClearStorage(chrome.storage.session, sessionKey);
+  }
 ]);
diff --git a/chrome/test/data/extensions/api_test/settings/simple_test/background.js b/chrome/test/data/extensions/api_test/settings/simple_test/background.js
index e6b03d0..a1d868f 100644
--- a/chrome/test/data/extensions/api_test/settings/simple_test/background.js
+++ b/chrome/test/data/extensions/api_test/settings/simple_test/background.js
@@ -178,7 +178,7 @@
       assertEq({}, settings);
       this.succeed();
     }
-    test(stage0);
+    test(stage0, true);
   },
 
   function clearWhenNonempty() {
@@ -199,7 +199,7 @@
       assertEq({}, settings);
       this.succeed();
     }
-    test(stage0);
+    test(stage0, true);
   },
 
   function keysWithDots() {
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index e5ff3ab..122e504 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -8254,6 +8254,15 @@
       }
     ]
   },
+  "LockIconInAddressBarEnabled": {
+    "os": ["win", "linux", "mac", "chromeos", "android"],
+    "policy_pref_mapping_tests": [
+      {
+        "policies": { "LockIconInAddressBarEnabled": true },
+        "prefs": { "omnibox.lock_icon_in_address_bar_enabled": {} }
+      }
+    ]
+  },
   "InsecureFormsWarningsEnabled": {
     "os": ["win", "linux", "mac", "chromeos", "android"],
     "policy_pref_mapping_tests": [
diff --git a/chrome/test/data/tooltip_in_iframe.html b/chrome/test/data/tooltip_in_iframe.html
new file mode 100644
index 0000000..50e9fd2
--- /dev/null
+++ b/chrome/test/data/tooltip_in_iframe.html
@@ -0,0 +1,8 @@
+<html>
+<head></head>
+<body style="margin: 0;">
+  <button title="my tooltip">My button</button>
+  <br>
+  <iframe id="iframe1" src="tooltip.html" marginwidth="0" marginheight="0" frameborder="0" />
+</body>
+</html>
\ No newline at end of file
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_app_test.js b/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_app_test.js
index d2379984..9d434547 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_app_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_app_test.js
@@ -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 {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js';
 import {fakeChromeVersion, fakeStates} from 'chrome://shimless-rma/fake_data.js';
 import {FakeShimlessRmaService} from 'chrome://shimless-rma/fake_shimless_rma_service.js';
 import {setShimlessRmaServiceForTesting} from 'chrome://shimless-rma/mojo_interface_provider.js';
@@ -66,6 +67,16 @@
     assertTrue(!!backBtn);
   }
 
+  /**
+   * Utility function to click next button
+   * @return {Promise}
+   */
+  function clickNext() {
+    const nextBtn = component.shadowRoot.querySelector('#next');
+    nextBtn.click();
+    return flushTasks();
+  }
+
   test('ShimlessRMALoaded', async () => {
     await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]);
     assertNavButtons();
@@ -79,16 +90,14 @@
     assertTrue(!!initialPage);
     assertFalse(initialPage.hidden);
 
-    const nextBtn = component.shadowRoot.querySelector('#next');
-    nextBtn.click();
-    await flushTasks();
+    await clickNext();
 
     // TODO(joonbug): enable when page is ready.
     // const selectComponentPage =
     //     component.shadowRoot.querySelector('onboarding-select-components');
     // assertTrue(!!selectComponentPage);
     // assertFalse(selectComponentPage.hidden);
-    assertTrue(!!initialPage);  // initial page should not be destroyed on nav.
+    assertTrue(!!initialPage);
     assertTrue(initialPage.hidden);
 
     const prevBtn = component.shadowRoot.querySelector('#back');
@@ -106,9 +115,7 @@
 
     const initialPage =
         component.shadowRoot.querySelector('onboarding-landing-page');
-    const nextBtn = component.shadowRoot.querySelector('#next');
-    nextBtn.click();
-    await flushTasks();
+    await clickNext();
 
     const cancelBtn = component.shadowRoot.querySelector('#cancel');
     cancelBtn.click();
@@ -117,4 +124,42 @@
     // back to initial page
     assertFalse(initialPage.hidden);
   });
+
+  test('NextBtnClickedOnReady', async () => {
+    await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]);
+
+    const initialPage =
+        component.shadowRoot.querySelector('onboarding-landing-page');
+    assertTrue(!!initialPage);
+
+    const resolver = new PromiseResolver();
+    initialPage.onNextBtnClick = () => resolver.promise;
+
+    await clickNext();
+    assertFalse(initialPage.hidden);
+
+    resolver.resolve(true);
+    await flushTasks();
+
+    assertTrue(initialPage.hidden);
+  });
+
+  test('NextBtnClickedOnNotReady', async () => {
+    await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]);
+
+    const initialPage =
+        component.shadowRoot.querySelector('onboarding-landing-page');
+    assertTrue(!!initialPage);
+
+    const resolver = new PromiseResolver();
+    initialPage.onNextBtnClick = () => resolver.promise;
+
+    await clickNext();
+    assertFalse(initialPage.hidden);
+
+    resolver.resolve(false);
+    await flushTasks();
+
+    assertFalse(initialPage.hidden);
+  });
 }
diff --git a/chrome/test/ppapi/ppapi_test.cc b/chrome/test/ppapi/ppapi_test.cc
index f9ee2f2..b58631d 100644
--- a/chrome/test/ppapi/ppapi_test.cc
+++ b/chrome/test/ppapi/ppapi_test.cc
@@ -82,11 +82,8 @@
 }
 
 PPAPITestBase::InfoBarObserver::InfoBarObserver(PPAPITestBase* test_base)
-    : test_base_(test_base),
-      expecting_infobar_(false),
-      should_accept_(false),
-      infobar_observer_(this) {
-  infobar_observer_.Add(GetInfoBarManager());
+    : test_base_(test_base), expecting_infobar_(false), should_accept_(false) {
+  infobar_observation_.Observe(GetInfoBarManager());
 }
 
 PPAPITestBase::InfoBarObserver::~InfoBarObserver() {
@@ -112,7 +109,8 @@
 
 void PPAPITestBase::InfoBarObserver::OnManagerShuttingDown(
     infobars::InfoBarManager* manager) {
-  infobar_observer_.Remove(manager);
+  ASSERT_TRUE(infobar_observation_.IsObservingSource(manager));
+  infobar_observation_.Reset();
 }
 
 void PPAPITestBase::InfoBarObserver::VerifyInfoBarState() {
diff --git a/chrome/test/ppapi/ppapi_test.h b/chrome/test/ppapi/ppapi_test.h
index 7faef67..81e9a9d37 100644
--- a/chrome/test/ppapi/ppapi_test.h
+++ b/chrome/test/ppapi/ppapi_test.h
@@ -9,7 +9,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/scoped_observer.h"
+#include "base/scoped_observation.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/infobars/core/infobar_manager.h"
@@ -84,8 +84,9 @@
     bool expecting_infobar_;
     bool should_accept_;
 
-    ScopedObserver<infobars::InfoBarManager, infobars::InfoBarManager::Observer>
-        infobar_observer_;
+    base::ScopedObservation<infobars::InfoBarManager,
+                            infobars::InfoBarManager::Observer>
+        infobar_observation_{this};
   };
 
   // Runs the test for a tab given the tab that's already navigated to the
diff --git a/chrome/test/views/accessibility_checker.cc b/chrome/test/views/accessibility_checker.cc
index f52c2b8..58e149b 100644
--- a/chrome/test/views/accessibility_checker.cc
+++ b/chrome/test/views/accessibility_checker.cc
@@ -119,10 +119,10 @@
   }
 }
 
-AccessibilityChecker::AccessibilityChecker() : scoped_observer_(this) {}
+AccessibilityChecker::AccessibilityChecker() = default;
 
 AccessibilityChecker::~AccessibilityChecker() {
-  DCHECK(!scoped_observer_.IsObservingSources());
+  DCHECK(!scoped_observations_.IsObservingAnySource());
 }
 
 void AccessibilityChecker::OnBeforeWidgetInit(
@@ -131,11 +131,11 @@
   ChromeViewsDelegate::OnBeforeWidgetInit(params, delegate);
   views::Widget* widget = delegate->AsWidget();
   if (widget)
-    scoped_observer_.Add(widget);
+    scoped_observations_.AddObservation(widget);
 }
 
 void AccessibilityChecker::OnWidgetDestroying(views::Widget* widget) {
-  scoped_observer_.Remove(widget);
+  scoped_observations_.RemoveObservation(widget);
 }
 
 void AccessibilityChecker::OnWidgetVisibilityChanged(views::Widget* widget,
diff --git a/chrome/test/views/accessibility_checker.h b/chrome/test/views/accessibility_checker.h
index bf1f1f2e..34bf67c5 100644
--- a/chrome/test/views/accessibility_checker.h
+++ b/chrome/test/views/accessibility_checker.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_TEST_VIEWS_ACCESSIBILITY_CHECKER_H_
 #define CHROME_TEST_VIEWS_ACCESSIBILITY_CHECKER_H_
 
-#include "base/scoped_observer.h"
+#include "base/scoped_multi_source_observation.h"
 #include "chrome/browser/ui/views/chrome_views_delegate.h"
 #include "ui/views/widget/widget_observer.h"
 
@@ -34,7 +34,8 @@
   void OnWidgetVisibilityChanged(views::Widget* widget, bool visible) override;
 
  private:
-  ScopedObserver<views::Widget, WidgetObserver> scoped_observer_;
+  base::ScopedMultiSourceObservation<views::Widget, WidgetObserver>
+      scoped_observations_{this};
 
   DISALLOW_COPY_AND_ASSIGN(AccessibilityChecker);
 };
diff --git a/chromecast/browser/extensions/api/tabs/tabs_api.cc b/chromecast/browser/extensions/api/tabs/tabs_api.cc
index c2c3252b..6038b4ad 100644
--- a/chromecast/browser/extensions/api/tabs/tabs_api.cc
+++ b/chromecast/browser/extensions/api/tabs/tabs_api.cc
@@ -20,7 +20,6 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/notreached.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/pattern.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
diff --git a/chromecast/browser/service_manager_context.cc b/chromecast/browser/service_manager_context.cc
index be8e628..4b2141b 100644
--- a/chromecast/browser/service_manager_context.cc
+++ b/chromecast/browser/service_manager_context.cc
@@ -21,7 +21,6 @@
 #include "base/no_destructor.h"
 #include "base/process/process_handle.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
 #include "build/build_config.h"
diff --git a/chromecast/browser/webview/webview_window_manager.cc b/chromecast/browser/webview/webview_window_manager.cc
index c72d7c3a..a2d13f4 100644
--- a/chromecast/browser/webview/webview_window_manager.cc
+++ b/chromecast/browser/webview/webview_window_manager.cc
@@ -5,7 +5,6 @@
 #include "chromecast/browser/webview/webview_window_manager.h"
 
 #include "base/logging.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "components/exo/shell_surface_util.h"
 #include "components/exo/surface.h"
diff --git a/chromeos/lacros/BUILD.gn b/chromeos/lacros/BUILD.gn
index 6058044..7ad108b 100644
--- a/chromeos/lacros/BUILD.gn
+++ b/chromeos/lacros/BUILD.gn
@@ -69,15 +69,15 @@
   }
 
   lacros_tast_tests("lacros_fyi_tast_tests") {
-    # The following expression filters out all non-critical tests. See the link
-    # below for more details:
-    # https://chromium.googlesource.com/chromiumos/platform/tast/+/main/docs/test_attributes.md
-    tast_attr_expr = "\"group:mainline\" && (\"dep:lacros\" || \"dep:lacros_stable\" || \"dep:lacros_unstable\")"
-
-    tast_disabled_tests = [
-      # Chromium CI/CQ is meant to test the tip of the trunk or branch, but
-      # test tests again the live Lacros on Omaha, so it's not applicable here.
-      "lacros.ShelfLaunch.omaha",
+    tast_tests = [
+      "lacros.AppLauncherLaunch",
+      "lacros.AppLauncherLaunch.unstable",
+      "lacros.AudioPlay",
+      "lacros.AudioPlay.unstable",
+      "lacros.Basic",
+      "lacros.Basic.unstable",
+      "lacros.ShelfLaunch",
+      "lacros.ShelfLaunch.unstable",
     ]
   }
 }
diff --git a/components/arc/arc_features_parser.cc b/components/arc/arc_features_parser.cc
index 6ffa6530..1833ada7 100644
--- a/components/arc/arc_features_parser.cc
+++ b/components/arc/arc_features_parser.cc
@@ -10,7 +10,6 @@
 #include "base/files/file_util.h"
 #include "base/json/json_reader.h"
 #include "base/logging.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
diff --git a/components/arc/intent_helper/arc_intent_helper_bridge.cc b/components/arc/intent_helper/arc_intent_helper_bridge.cc
index 579e28a..53380623 100644
--- a/components/arc/intent_helper/arc_intent_helper_bridge.cc
+++ b/components/arc/intent_helper/arc_intent_helper_bridge.cc
@@ -14,7 +14,6 @@
 #include "base/memory/singleton.h"
 #include "base/memory/weak_ptr.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/values.h"
 #include "components/arc/arc_browser_context_keyed_service_factory_base.h"
diff --git a/components/arc/timer/arc_timer_bridge.cc b/components/arc/timer/arc_timer_bridge.cc
index 1653a9e..1aea85dd 100644
--- a/components/arc/timer/arc_timer_bridge.cc
+++ b/components/arc/timer/arc_timer_bridge.cc
@@ -8,7 +8,6 @@
 #include "base/containers/flat_set.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
-#include "base/stl_util.h"
 #include "base/task_runner_util.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc
index 17674ad..1e5a397 100644
--- a/components/autofill/content/renderer/form_autofill_util.cc
+++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -82,10 +82,6 @@
 // Maximal length of all button titles.
 const int kMaxLengthForAllButtonTitles = 200;
 
-// Number of shadow roots to traverse upwards when looking for relevant forms
-// and labels of an input element inside a shadow root.
-const int kMaxShadowLevelsUp = 2;
-
 // Text features to detect form submission buttons. Features are selected based
 // on analysis of real forms and their buttons.
 // TODO(crbug.com/910546): Consider to add more features (e.g. non-English
@@ -1298,77 +1294,28 @@
 // pointer.
 struct CompareByRendererId {
   using is_transparent = void;
-  bool operator()(const std::pair<FormFieldData*, ShadowFieldData>& f,
-                  const std::pair<FormFieldData*, ShadowFieldData>& g) const {
-    DCHECK(f.first && g.first);
-    return f.first->unique_renderer_id < g.first->unique_renderer_id;
+  constexpr bool operator()(const FormFieldData* f,
+                            const FormFieldData* g) const {
+    DCHECK(f && g);
+    return f->unique_renderer_id < g->unique_renderer_id;
   }
-  bool operator()(const FieldRendererId f,
-                  const std::pair<FormFieldData*, ShadowFieldData>& g) const {
-    DCHECK(g.first);
-    return f < g.first->unique_renderer_id;
+  constexpr bool operator()(const FieldRendererId f,
+                            const FormFieldData* g) const {
+    DCHECK(g);
+    return f < g->unique_renderer_id;
   }
-  bool operator()(const std::pair<FormFieldData*, ShadowFieldData>& f,
-                  FieldRendererId g) const {
-    DCHECK(f.first);
-    return f.first->unique_renderer_id < g;
+  constexpr bool operator()(const FormFieldData* f, FieldRendererId g) const {
+    DCHECK(f);
+    return f->unique_renderer_id < g;
   }
 };
 
-// Searches field_set for a matching named element in the case that
-// Label::CorrespondingControl from blink didn't return a matching form control
-// element. Returns nullptr if no match was found.
-FormFieldData* SearchForFormControlByName(
-    const std::u16string& target_name,
-    const base::flat_set<std::pair<FormFieldData*, ShadowFieldData>,
-                         CompareByRendererId>& field_set) {
-  // Sometimes site authors will incorrectly specify the corresponding
-  // field element's name rather than its id, so we compensate here.
-  if (target_name.empty())
-    return nullptr;
-
-  // Look through the list for elements with this name. There can actually
-  // be more than one. In this case, the label may not be particularly
-  // useful, so just discard it.
-  FormFieldData* field_data = nullptr;
-  for (const auto& iter : field_set) {
-    if (iter.first->name == target_name) {
-      if (field_data) {
-        field_data = nullptr;
-        break;
-      }
-      field_data = iter.first;
-    }
-  }
-
-  if (field_data)
-    return field_data;
-
-  // If there is identifying information that will help us find the target
-  // form control in the form control's shadow host(s), look there too.
-  for (const auto& iter : field_set) {
-    for (const std::u16string& shadow_host_name :
-         iter.second.shadow_host_name_attributes) {
-      if (shadow_host_name == target_name)
-        return iter.first;
-    }
-    for (const std::u16string& shadow_host_id :
-         iter.second.shadow_host_id_attributes) {
-      if (shadow_host_id == target_name)
-        return iter.first;
-    }
-  }
-
-  return nullptr;
-}
-
 // Updates the FormFieldData::label of each field in `field_set` according to
 // the <label> descendant of |form_or_fieldset|, if there is any. The extracted
 // label is label.firstChild().nodeValue() of the label element.
 void MatchLabelsAndFields(
     const WebElement& form_or_fieldset,
-    const base::flat_set<std::pair<FormFieldData*, ShadowFieldData>,
-                         CompareByRendererId>& field_set) {
+    const base::flat_set<FormFieldData*, CompareByRendererId>& field_set) {
   static base::NoDestructor<WebString> kLabel("label");
   static base::NoDestructor<WebString> kFor("for");
   static base::NoDestructor<WebString> kHidden("hidden");
@@ -1384,8 +1331,23 @@
     FormFieldData* field_data = nullptr;
 
     if (control.IsNull()) {
-      field_data = SearchForFormControlByName(label.GetAttribute(*kFor).Utf16(),
-                                              field_set);
+      // Sometimes site authors will incorrectly specify the corresponding
+      // field element's name rather than its id, so we compensate here.
+      std::u16string element_name = label.GetAttribute(*kFor).Utf16();
+      if (element_name.empty())
+        continue;
+      // Look through the field set with this name. There can actually
+      // be more than one. In this case, the label may not be particularly
+      // useful, so just discard it.
+      for (FormFieldData* field : field_set) {
+        if (field->name == element_name) {
+          if (field_data) {
+            field_data = nullptr;
+            break;
+          }
+          field_data = field;
+        }
+      }
     } else if (control.IsFormControlElement()) {
       WebFormControlElement form_control = control.To<WebFormControlElement>();
       if (form_control.FormControlTypeForAutofill() == *kHidden)
@@ -1395,7 +1357,7 @@
           FieldRendererId(form_control.UniqueRendererFormControlId()));
       if (iter == field_set.end())
         continue;
-      field_data = iter->first;
+      field_data = *iter;
     }
 
     if (!field_data)
@@ -1460,8 +1422,6 @@
   }
   std::vector<bool> fields_extracted(control_elements.size(), false);
 
-  std::vector<ShadowFieldData> shadow_field_data;
-
   for (size_t i = 0, next_iframe = 0; i < control_elements.size(); ++i) {
     const WebFormControlElement& control_element = control_elements[i];
 
@@ -1469,11 +1429,9 @@
       continue;
 
     form->fields.push_back(FormFieldData());
-    ShadowFieldData shadow_field;
     WebFormControlElementToFormField(form->unique_renderer_id, control_element,
                                      field_data_manager, extract_mask,
-                                     &form->fields.back(), &shadow_field);
-    shadow_field_data.emplace_back(shadow_field);
+                                     &form->fields.back());
     fields_extracted[i] = true;
 
     if (base::FeatureList::IsEnabled(features::kAutofillAcrossIframes)) {
@@ -1505,15 +1463,11 @@
 
   // Extracts field labels from the <label for="..."> tags.
   {
-    std::vector<std::pair<FormFieldData*, ShadowFieldData>> items;
-    DCHECK_EQ(form->fields.size(), shadow_field_data.size());
-    for (size_t i = 0; i < form->fields.size(); i++) {
-      items.emplace_back(
-          std::make_pair(&form->fields[i], std::move(shadow_field_data[i])));
-    }
-    base::flat_set<std::pair<FormFieldData*, ShadowFieldData>,
-                   CompareByRendererId>
-        field_set(std::move(items));
+    std::vector<FormFieldData*> items;
+    for (FormFieldData& field : form->fields)
+      items.push_back(&field);
+    base::flat_set<FormFieldData*, CompareByRendererId> field_set(
+        std::move(items));
 
     if (form_element) {
       MatchLabelsAndFields(*form_element, field_set);
@@ -1648,39 +1602,6 @@
   return base::flat_map<FieldRendererId, size_t>(std::move(items));
 }
 
-std::string GetAutocompleteAttribute(const WebElement& element) {
-  static base::NoDestructor<WebString> kAutocomplete("autocomplete");
-  std::string autocomplete_attribute =
-      element.GetAttribute(*kAutocomplete).Utf8();
-  if (autocomplete_attribute.size() > kMaxDataLength) {
-    // Discard overly long attribute values to avoid DOS-ing the browser
-    // process.  However, send over a default string to indicate that the
-    // attribute was present.
-    return "x-max-data-length-exceeded";
-  }
-  return autocomplete_attribute;
-}
-
-void FindFormElementUpShadowRoots(const WebElement& element,
-                                  WebFormElement* found_form_element) {
-  // If we are in shadowdom, then look to see if the host(s) are inside a form
-  // element we can use.
-  int levels_up = kMaxShadowLevelsUp;
-  for (WebElement host = element.OwnerShadowHost(); !host.IsNull() && levels_up;
-       host = host.OwnerShadowHost(), --levels_up) {
-    for (WebNode parent = host; !parent.IsNull();
-         parent = parent.ParentNode()) {
-      if (parent.IsElementNode()) {
-        WebElement parentElement = parent.To<WebElement>();
-        if (parentElement.HasHTMLTagName("form")) {
-          *found_form_element = parentElement.To<WebFormElement>();
-          return;
-        }
-      }
-    }
-  }
-}
-
 }  // namespace
 
 bool IsVisibleIframe(const WebElement& element) {
@@ -1934,11 +1855,11 @@
     const WebFormControlElement& element,
     const FieldDataManager* field_data_manager,
     ExtractMask extract_mask,
-    FormFieldData* field,
-    ShadowFieldData* shadow_data) {
+    FormFieldData* field) {
   DCHECK(field);
   DCHECK(!element.IsNull());
   DCHECK(element.GetDocument().GetFrame());
+  static base::NoDestructor<WebString> kAutocomplete("autocomplete");
   static base::NoDestructor<WebString> kName("name");
   static base::NoDestructor<WebString> kRole("role");
   static base::NoDestructor<WebString> kPlaceholder("placeholder");
@@ -1954,7 +1875,13 @@
   field->host_form_id = form_renderer_id;
   field->form_control_ax_id = element.GetAxId();
   field->form_control_type = element.FormControlTypeForAutofill().Utf8();
-  field->autocomplete_attribute = GetAutocompleteAttribute(element);
+  field->autocomplete_attribute = element.GetAttribute(*kAutocomplete).Utf8();
+  if (field->autocomplete_attribute.size() > kMaxDataLength) {
+    // Discard overly long attribute values to avoid DOS-ing the browser
+    // process.  However, send over a default string to indicate that the
+    // attribute was present.
+    field->autocomplete_attribute = "x-max-data-length-exceeded";
+  }
   if (base::LowerCaseEqualsASCII(element.GetAttribute(*kRole).Utf16(),
                                  "presentation")) {
     field->role = FormFieldData::RoleAttribute::kPresentation;
@@ -1973,40 +1900,6 @@
   field->aria_label = GetAriaLabel(element.GetDocument(), element);
   field->aria_description = GetAriaDescription(element.GetDocument(), element);
 
-  // Traverse up through shadow hosts to see if we can gather missing fields.
-  WebFormElement form_element_up_shadow_hosts;
-  FindFormElementUpShadowRoots(element, &form_element_up_shadow_hosts);
-  int levels_up = kMaxShadowLevelsUp;
-  for (WebElement host = element.OwnerShadowHost();
-       !host.IsNull() && levels_up &&
-       (!form_element_up_shadow_hosts.IsNull() &&
-        form_element_up_shadow_hosts.OwnerShadowHost() != host);
-       host = host.OwnerShadowHost(), --levels_up) {
-    std::u16string shadow_host_id = host.GetIdAttribute().Utf16();
-    if (shadow_data && !shadow_host_id.empty())
-      shadow_data->shadow_host_id_attributes.push_back(shadow_host_id);
-    std::u16string shadow_host_name = host.GetAttribute(*kName).Utf16();
-    if (shadow_data && !shadow_host_name.empty())
-      shadow_data->shadow_host_name_attributes.push_back(shadow_host_name);
-
-    if (field->id_attribute.empty())
-      field->id_attribute = host.GetIdAttribute().Utf16();
-    if (field->name_attribute.empty())
-      field->name_attribute = host.GetAttribute(*kName).Utf16();
-    if (field->name.empty()) {
-      field->name = field->name_attribute.empty() ? field->id_attribute
-                                                  : field->name_attribute;
-    }
-    if (field->autocomplete_attribute.empty())
-      field->autocomplete_attribute = GetAutocompleteAttribute(host);
-    if (field->css_classes.empty() && host.HasAttribute(*kClass))
-      field->css_classes = host.GetAttribute(*kClass).Utf16();
-    if (field->aria_label.empty())
-      field->aria_label = GetAriaLabel(host.GetDocument(), host);
-    if (field->aria_description.empty())
-      field->aria_description = GetAriaDescription(host.GetDocument(), host);
-  }
-
   if (!IsAutofillableElement(element))
     return;
 
@@ -2247,11 +2140,7 @@
 
   extract_mask =
       static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTIONS | extract_mask);
-  WebFormElement form_element = element.Form();
-
-  if (form_element.IsNull())
-    FindFormElementUpShadowRoots(element, &form_element);
-
+  const WebFormElement form_element = element.Form();
   if (form_element.IsNull()) {
     // No associated form, try the synthetic form for unowned form elements.
     WebDocument document = element.GetDocument();
@@ -2282,9 +2171,6 @@
     const FormData& form,
     const WebFormControlElement& element) {
   WebFormElement form_element = element.Form();
-  if (form_element.IsNull())
-    FindFormElementUpShadowRoots(element, &form_element);
-
   if (form_element.IsNull()) {
     return ForEachMatchingUnownedFormField(element, form,
                                            FILTER_ALL_NON_EDITABLE_ELEMENTS,
@@ -2304,9 +2190,6 @@
     const FormData& form,
     const WebFormControlElement& element) {
   WebFormElement form_element = element.Form();
-  if (form_element.IsNull())
-    FindFormElementUpShadowRoots(element, &form_element);
-
   if (form_element.IsNull()) {
     return ForEachMatchingUnownedFormField(element, form,
                                            FILTER_ALL_NON_EDITABLE_ELEMENTS,
@@ -2578,7 +2461,7 @@
 }  // namespace
 
 std::u16string GetAriaLabel(const blink::WebDocument& document,
-                            const WebElement& element) {
+                            const WebFormControlElement& element) {
   static const base::NoDestructor<WebString> kAriaLabelledBy("aria-labelledby");
   if (element.HasAttribute(*kAriaLabelledBy)) {
     std::u16string text =
@@ -2595,16 +2478,11 @@
 }
 
 std::u16string GetAriaDescription(const blink::WebDocument& document,
-                                  const WebElement& element) {
+                                  const WebFormControlElement& element) {
   static const base::NoDestructor<WebString> kAriaDescribedBy(
       "aria-describedby");
   return CoalesceTextByIdList(document,
                               element.GetAttribute(*kAriaDescribedBy));
 }
-
-ShadowFieldData::ShadowFieldData() = default;
-ShadowFieldData::ShadowFieldData(const ShadowFieldData& other) = default;
-ShadowFieldData::~ShadowFieldData() = default;
-
 }  // namespace form_util
 }  // namespace autofill
diff --git a/components/autofill/content/renderer/form_autofill_util.h b/components/autofill/content/renderer/form_autofill_util.h
index ce115b4..48df011 100644
--- a/components/autofill/content/renderer/form_autofill_util.h
+++ b/components/autofill/content/renderer/form_autofill_util.h
@@ -70,18 +70,6 @@
                                  // kMaxDataLength.
 };
 
-struct ShadowFieldData {
-  ShadowFieldData();
-  ShadowFieldData(const ShadowFieldData& other);
-  ~ShadowFieldData();
-
-  // If the form control is inside shadow DOM, then these lists will contain
-  // id and name attributes of the parent shadow host elements. There may be
-  // more than one if the form control is in nested shadow DOM.
-  std::vector<std::u16string> shadow_host_id_attributes;
-  std::vector<std::u16string> shadow_host_name_attributes;
-};
-
 // Indicates if an iframe |element| is considered actually visible to the user.
 //
 // This function is not intended to implement a perfect visibility check. It
@@ -214,8 +202,7 @@
     const blink::WebFormControlElement& element,
     const FieldDataManager* field_data_manager,
     ExtractMask extract_mask,
-    FormFieldData* field,
-    ShadowFieldData* shadow_data = nullptr);
+    FormFieldData* field);
 
 // Fills |form| with the FormData object corresponding to the |form_element|.
 // If |field| is non-NULL, also fills |field| with the FormField object
@@ -394,12 +381,12 @@
 // attribute of |element| or the value of the aria-label attribute of
 // |element|, with priority given to the aria-labelledby attribute.
 std::u16string GetAriaLabel(const blink::WebDocument& document,
-                            const blink::WebElement& element);
+                            const blink::WebFormControlElement& element);
 
 // Returns the ARIA label text of the elements denoted by the aria-describedby
 // attribute of |element|.
 std::u16string GetAriaDescription(const blink::WebDocument& document,
-                                  const blink::WebElement& element);
+                                  const blink::WebFormControlElement& element);
 
 }  // namespace form_util
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autocomplete_history_manager_unittest.cc b/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
index 6734832..70fa331 100644
--- a/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
+++ b/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
@@ -9,7 +9,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/run_loop.h"
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/test/metrics/histogram_tester.h"
diff --git a/components/autofill/core/browser/autofill_client.cc b/components/autofill/core/browser/autofill_client.cc
index a13ad261..5a07a7e 100644
--- a/components/autofill/core/browser/autofill_client.cc
+++ b/components/autofill/core/browser/autofill_client.cc
@@ -5,7 +5,6 @@
 #include "components/autofill/core/browser/autofill_client.h"
 
 #include "base/no_destructor.h"
-#include "base/stl_util.h"
 #include "components/autofill/core/browser/autofill_ablation_study.h"
 #include "components/autofill/core/browser/ui/suggestion.h"
 #include "components/version_info/channel.h"
diff --git a/components/autofill/core/browser/form_data_importer.cc b/components/autofill/core/browser/form_data_importer.cc
index 65460aa2..1e4a996 100644
--- a/components/autofill/core/browser/form_data_importer.cc
+++ b/components/autofill/core/browser/form_data_importer.cc
@@ -418,6 +418,11 @@
            is_zip_invalid);
 }
 
+void FormDataImporter::CacheFetchedVirtualCard(
+    const std::u16string& last_four) {
+  fetched_virtual_cards_.insert(last_four);
+}
+
 bool FormDataImporter::ImportFormData(
     const FormStructure& submitted_form,
     bool profile_autofill_enabled,
@@ -775,6 +780,10 @@
     return false;
   }
 
+  // If the imported card is a known virtual card, abort saving.
+  if (fetched_virtual_cards_.contains(candidate_credit_card.LastFourDigits()))
+    return false;
+
   // Can import one valid card per form. Start by treating it as NEW_CARD, but
   // overwrite this type if we discover it is already a local or server card.
   imported_credit_card_record_type_ = ImportedCreditCardRecordType::NEW_CARD;
diff --git a/components/autofill/core/browser/form_data_importer.h b/components/autofill/core/browser/form_data_importer.h
index 128e048..ddba86c 100644
--- a/components/autofill/core/browser/form_data_importer.h
+++ b/components/autofill/core/browser/form_data_importer.h
@@ -69,6 +69,10 @@
                                       const std::string& app_locale,
                                       LogBuffer* import_log_buffer);
 
+  // Cache the last four of the fetched virtual card so we don't offer saving
+  // them.
+  void CacheFetchedVirtualCard(const std::u16string& last_four);
+
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
   LocalCardMigrationManager* local_card_migration_manager() {
     return local_card_migration_manager_.get();
@@ -179,6 +183,9 @@
 
   std::string app_locale_;
 
+  // Used to store the last four digits of the fetched virtual cards.
+  base::flat_set<std::u16string> fetched_virtual_cards_;
+
   friend class AutofillMergeTest;
   friend class FormDataImporterTest;
   friend class FormDataImporterTestBase;
@@ -218,6 +225,9 @@
       ImportFormData_ImportCreditCardRecordType_NoCard_InvalidCardNumber);
   FRIEND_TEST_ALL_PREFIXES(
       FormDataImporterTest,
+      ImportFormData_ImportCreditCardRecordType_NoCard_VirtualCard);
+  FRIEND_TEST_ALL_PREFIXES(
+      FormDataImporterTest,
       ImportFormData_ImportCreditCardRecordType_NoCard_NoCardOnForm);
   FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
                            ImportFormData_OneAddressCreditCardDisabled);
diff --git a/components/autofill/core/browser/form_data_importer_unittest.cc b/components/autofill/core/browser/form_data_importer_unittest.cc
index 4d349b2..47370dc 100644
--- a/components/autofill/core/browser/form_data_importer_unittest.cc
+++ b/components/autofill/core/browser/form_data_importer_unittest.cc
@@ -3109,6 +3109,33 @@
 }
 
 // Ensures that |imported_credit_card_record_type_| is set correctly.
+TEST_P(FormDataImporterTest,
+       ImportFormData_ImportCreditCardRecordType_NoCard_VirtualCard) {
+  // Simulate a form submission using a credit card that is known as a virtual
+  // card.
+  FormData form;
+  form.url = GURL("https://wwww.foo.com");
+  AddFullCreditCardForm(&form, "Biggie Smalls", "4111 1111 1111 1111", "01",
+                        "2999");
+  FormStructure form_structure(form);
+  form_structure.DetermineHeuristicTypes(nullptr, nullptr);
+  form_data_importer_->CacheFetchedVirtualCard(u"1111");
+  std::unique_ptr<CreditCard> imported_credit_card;
+  absl::optional<std::string> imported_upi_id;
+
+  EXPECT_FALSE(form_data_importer_->ImportFormData(
+      form_structure, /*profile_autofill_enabled=*/true,
+      /*credit_card_autofill_enabled=*/true,
+      /*should_return_local_card=*/true, &imported_credit_card,
+      &imported_upi_id));
+  ASSERT_FALSE(imported_credit_card);
+  // |imported_credit_card_record_type_| should be NO_CARD because the card
+  // imported from the form was a virtual card.
+  ASSERT_TRUE(form_data_importer_->imported_credit_card_record_type_ ==
+              FormDataImporter::ImportedCreditCardRecordType::NO_CARD);
+}
+
+// Ensures that |imported_credit_card_record_type_| is set correctly.
 TEST_P(
     FormDataImporterTest,
     ImportFormData_ImportCreditCardRecordType_NewCard_ExpiredCard_WithExpDateFixFlow) {
diff --git a/components/autofill/core/browser/form_parsing/credit_card_field.cc b/components/autofill/core/browser/form_parsing/credit_card_field.cc
index f7b3944..a2d868b 100644
--- a/components/autofill/core/browser/form_parsing/credit_card_field.cc
+++ b/components/autofill/core/browser/form_parsing/credit_card_field.cc
@@ -11,7 +11,6 @@
 #include <utility>
 
 #include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/time/time.h"
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc
index 5e8aa5c..e8337c3 100644
--- a/components/autofill/core/browser/form_structure.cc
+++ b/components/autofill/core/browser/form_structure.cc
@@ -2518,8 +2518,9 @@
            << base::StrCat(
                   {"renderer id: ",
                    base::NumberToString(field->unique_renderer_id.value()),
-                   ", host frame: ", form.host_frame().ToString(), " - ",
-                   field->origin.Serialize(), ", host form renderer id: ",
+                   ", host frame: ", form.global_id().frame_token.ToString(),
+                   " - ", field->origin.Serialize(),
+                   ", host form renderer id: ",
                    base::NumberToString(field->host_form_id.value())});
     buffer << "\n  Signature: "
            << base::StrCat(
@@ -2574,8 +2575,9 @@
            << base::StrCat(
                   {"renderer id: ",
                    base::NumberToString(field->unique_renderer_id.value()),
-                   ", host frame: ", form.host_frame().ToString(), " - ",
-                   field->origin.Serialize(), ", host form renderer id: ",
+                   ", host frame: ", form.global_id().frame_token.ToString(),
+                   " - ", field->origin.Serialize(),
+                   ", host form renderer id: ",
                    base::NumberToString(field->host_form_id.value())});
     buffer << Tr{} << "Signature:"
            << base::StrCat(
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h
index 478ddcb..f1f8f77e 100644
--- a/components/autofill/core/browser/form_structure.h
+++ b/components/autofill/core/browser/form_structure.h
@@ -396,8 +396,6 @@
   }
 
   FormGlobalId global_id() const { return {host_frame_, unique_renderer_id_}; }
-  LocalFrameToken host_frame() const { return host_frame_; }
-  FormRendererId unique_renderer_id() const { return unique_renderer_id_; }
 
   bool ShouldSkipFieldVisibleForTesting(const FormFieldData& field) const {
     return ShouldSkipField(field);
@@ -657,7 +655,7 @@
 
   bool value_from_dynamic_change_form_ = false;
 
-  // An identifier of the frame that is unique over the lifetime of the browser.
+  // A unique identifier of the containing frame.
   // This value must not be leaked to other renderer processes.
   LocalFrameToken host_frame_;
 
diff --git a/components/autofill/core/browser/logging/log_router.cc b/components/autofill/core/browser/logging/log_router.cc
index 320e2354..0e8bb05 100644
--- a/components/autofill/core/browser/logging/log_router.cc
+++ b/components/autofill/core/browser/logging/log_router.cc
@@ -4,7 +4,6 @@
 
 #include "components/autofill/core/browser/logging/log_router.h"
 
-#include "base/stl_util.h"
 #include "base/strings/string_split.h"
 #include "components/autofill/core/browser/logging/log_manager.h"
 #include "components/autofill/core/browser/logging/log_receiver.h"
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc b/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
index b83c1b5..ce95df8 100644
--- a/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
+++ b/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
@@ -20,7 +20,6 @@
 #include "base/metrics/field_trial.h"
 #include "base/metrics/metrics_hashes.h"
 #include "base/run_loop.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc b/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc
index 32d08172..353fe03 100644
--- a/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc
+++ b/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc
@@ -19,7 +19,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/metrics_hashes.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc b/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc
index eae3366..a4ef9e9 100644
--- a/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc
+++ b/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc
@@ -19,7 +19,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/metrics_hashes.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/components/autofill/core/browser/randomized_encoder.cc b/components/autofill/core/browser/randomized_encoder.cc
index 4a3a467..5211562 100644
--- a/components/autofill/core/browser/randomized_encoder.cc
+++ b/components/autofill/core/browser/randomized_encoder.cc
@@ -13,7 +13,6 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/sparse_histogram.h"
 #include "base/numerics/safe_conversions.h"
-#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/unguessable_token.h"
diff --git a/components/autofill/core/browser/test_autofill_client.cc b/components/autofill/core/browser/test_autofill_client.cc
index 77d9a2d..dce60f78 100644
--- a/components/autofill/core/browser/test_autofill_client.cc
+++ b/components/autofill/core/browser/test_autofill_client.cc
@@ -4,7 +4,6 @@
 
 #include "components/autofill/core/browser/test_autofill_client.h"
 
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/autofill/core/browser/autofill_metrics.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
diff --git a/components/autofill/core/browser/test_autofill_download_manager.cc b/components/autofill/core/browser/test_autofill_download_manager.cc
index 31261f5..06571d1 100644
--- a/components/autofill/core/browser/test_autofill_download_manager.cc
+++ b/components/autofill/core/browser/test_autofill_download_manager.cc
@@ -26,8 +26,8 @@
     const std::vector<FormData>& expected_forms) {
   ASSERT_EQ(expected_forms.size(), last_queried_forms_.size());
   for (size_t i = 0; i < expected_forms.size(); ++i) {
-    EXPECT_EQ(last_queried_forms_[i]->unique_renderer_id(),
-              expected_forms[i].unique_renderer_id);
+    EXPECT_EQ(last_queried_forms_[i]->global_id().renderer_id,
+              expected_forms[i].global_id().renderer_id);
   }
 }
 
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_service.cc b/components/autofill/core/browser/webdata/autofill_webdata_service.cc
index 522e871..98d6b89 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_service.cc
+++ b/components/autofill/core/browser/webdata/autofill_webdata_service.cc
@@ -9,7 +9,6 @@
 #include "base/check.h"
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "components/autofill/core/browser/data_model/autofill_offer_data.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
diff --git a/components/autofill/core/common/autofill_payments_features.cc b/components/autofill/core/common/autofill_payments_features.cc
index bc82b4f..68df963d 100644
--- a/components/autofill/core/common/autofill_payments_features.cc
+++ b/components/autofill/core/common/autofill_payments_features.cc
@@ -167,6 +167,11 @@
 const base::Feature kAutofillUpstreamAllowAllEmailDomains{
     "AutofillUpstreamAllowAllEmailDomains", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Controls whether we should use the new header images for the save card
+// bubble.
+const base::Feature kAutofillUseNewHeaderForSaveCardBubble{
+    "AutofillUseNewHeaderForSaveCardBubble", base::FEATURE_ENABLED_BY_DEFAULT};
+
 bool ShouldShowImprovedUserConsentForCreditCardSave() {
 // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
 // of lacros-chrome is complete.
diff --git a/components/autofill/core/common/autofill_payments_features.h b/components/autofill/core/common/autofill_payments_features.h
index e21a996a..b45f3dc 100644
--- a/components/autofill/core/common/autofill_payments_features.h
+++ b/components/autofill/core/common/autofill_payments_features.h
@@ -42,6 +42,7 @@
 extern const base::Feature kAutofillSuppressCreditCardSaveForAssistant;
 extern const base::Feature kAutofillUpstream;
 extern const base::Feature kAutofillUpstreamAllowAllEmailDomains;
+extern const base::Feature kAutofillUseNewHeaderForSaveCardBubble;
 
 // Return whether a [No thanks] button and new messaging is shown in the save
 // card bubbles. This will be called only on desktop platforms.
diff --git a/components/base32/base32_fuzzer.cc b/components/base32/base32_fuzzer.cc
index e591cb2..dd1009d 100644
--- a/components/base32/base32_fuzzer.cc
+++ b/components/base32/base32_fuzzer.cc
@@ -8,7 +8,6 @@
 #include <limits>
 
 #include "base/check_op.h"
-#include "base/stl_util.h"
 #include "components/base32/base32.h"
 
 base32::Base32EncodePolicy GetBase32EncodePolicyFromUint8(uint8_t value) {
diff --git a/components/bookmarks/browser/titled_url_index_unittest.cc b/components/bookmarks/browser/titled_url_index_unittest.cc
index 91e2d80c..60508bc 100644
--- a/components/bookmarks/browser/titled_url_index_unittest.cc
+++ b/components/bookmarks/browser/titled_url_index_unittest.cc
@@ -8,7 +8,6 @@
 #include <string>
 #include <vector>
 
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
diff --git a/components/bookmarks/test/test_bookmark_client.cc b/components/bookmarks/test/test_bookmark_client.cc
index 08920b4..0aa8bb4 100644
--- a/components/bookmarks/test/test_bookmark_client.cc
+++ b/components/bookmarks/test/test_bookmark_client.cc
@@ -12,7 +12,6 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "components/bookmarks/browser/bookmark_load_details.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/browser/bookmark_node.h"
diff --git a/components/browsing_data/content/database_helper.cc b/components/browsing_data/content/database_helper.cc
index 248c33a2..da2da1d 100644
--- a/components/browsing_data/content/database_helper.cc
+++ b/components/browsing_data/content/database_helper.cc
@@ -14,7 +14,6 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/location.h"
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
 #include "components/browsing_data/content/browsing_data_helper.h"
diff --git a/components/browsing_data/content/file_system_helper.cc b/components/browsing_data/content/file_system_helper.cc
index 236225c..1566048 100644
--- a/components/browsing_data/content/file_system_helper.cc
+++ b/components/browsing_data/content/file_system_helper.cc
@@ -11,7 +11,6 @@
 #include "base/callback_helpers.h"
 #include "base/location.h"
 #include "base/sequenced_task_runner.h"
-#include "base/stl_util.h"
 #include "components/browsing_data/content/browsing_data_helper.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/components/browsing_data/content/local_storage_helper_browsertest.cc b/components/browsing_data/content/local_storage_helper_browsertest.cc
index b4900a1..8ad290e 100644
--- a/components/browsing_data/content/local_storage_helper_browsertest.cc
+++ b/components/browsing_data/content/local_storage_helper_browsertest.cc
@@ -14,7 +14,6 @@
 #include "base/callback_helpers.h"
 #include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind.h"
 #include "base/test/thread_test_helper.h"
diff --git a/components/cast_channel/cast_message_util.cc b/components/cast_channel/cast_message_util.cc
index 0e57d23..8959ba0 100644
--- a/components/cast_channel/cast_message_util.cc
+++ b/components/cast_channel/cast_message_util.cc
@@ -8,7 +8,6 @@
 
 #include "base/json/json_writer.h"
 #include "base/logging.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
diff --git a/components/cast_streaming/browser/BUILD.gn b/components/cast_streaming/browser/BUILD.gn
index 80cc8436..950ef3e 100644
--- a/components/cast_streaming/browser/BUILD.gn
+++ b/components/cast_streaming/browser/BUILD.gn
@@ -32,6 +32,28 @@
 source_set("receiver_session") {
   deps = [
     ":core",
+    ":streaming_session",
+    "//base",
+    "//media",
+    "//media/mojo/common",
+    "//media/mojo/mojom",
+    "//mojo/public/cpp/system",
+  ]
+  public_deps = [
+    "//components/cast_streaming/mojo:mojom",
+    "//third_party/openscreen/src/cast/common:channel",
+  ]
+  visibility = [ ":*" ]
+  public = [ "public/receiver_session.h" ]
+  sources = [
+    "receiver_session_impl.cc",
+    "receiver_session_impl.h",
+  ]
+}
+
+source_set("streaming_session") {
+  deps = [
+    ":core",
     "//base",
     "//components/openscreen_platform",
     "//media",
@@ -44,9 +66,9 @@
   ]
   public_deps = [ "//components/cast/message_port" ]
   visibility = [ ":*" ]
-  public = [ "public/cast_streaming_session.h" ]
   sources = [
     "cast_streaming_session.cc",
+    "cast_streaming_session.h",
     "stream_consumer.cc",
     "stream_consumer.h",
   ]
@@ -101,7 +123,7 @@
 source_set("test_receiver") {
   testonly = true
   deps = [
-    ":receiver_session",
+    ":streaming_session",
     "//base",
     "//components/openscreen_platform",
     "//media",
@@ -123,7 +145,7 @@
 test("e2e_tests") {
   deps = [
     ":core",
-    ":receiver_session",
+    ":streaming_session",
     ":test_receiver",
     ":test_sender",
     "//base/test:test_support",
diff --git a/components/cast_streaming/browser/cast_streaming_session.cc b/components/cast_streaming/browser/cast_streaming_session.cc
index 35b51a1..4e5af97 100644
--- a/components/cast_streaming/browser/cast_streaming_session.cc
+++ b/components/cast_streaming/browser/cast_streaming_session.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/cast_streaming/browser/public/cast_streaming_session.h"
+#include "components/cast_streaming/browser/cast_streaming_session.h"
 
 #include "base/bind.h"
 #include "base/timer/timer.h"
diff --git a/components/cast_streaming/browser/public/cast_streaming_session.h b/components/cast_streaming/browser/cast_streaming_session.h
similarity index 93%
rename from components/cast_streaming/browser/public/cast_streaming_session.h
rename to components/cast_streaming/browser/cast_streaming_session.h
index 0efe080..64e1327 100644
--- a/components/cast_streaming/browser/public/cast_streaming_session.h
+++ b/components/cast_streaming/browser/cast_streaming_session.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 COMPONENTS_CAST_STREAMING_BROWSER_PUBLIC_CAST_STREAMING_SESSION_H_
-#define COMPONENTS_CAST_STREAMING_BROWSER_PUBLIC_CAST_STREAMING_SESSION_H_
+#ifndef COMPONENTS_CAST_STREAMING_BROWSER_CAST_STREAMING_SESSION_H_
+#define COMPONENTS_CAST_STREAMING_BROWSER_CAST_STREAMING_SESSION_H_
 
 #include <memory>
 
@@ -92,4 +92,4 @@
 
 }  // namespace cast_streaming
 
-#endif  // COMPONENTS_CAST_STREAMING_BROWSER_PUBLIC_CAST_STREAMING_SESSION_H_
+#endif  // COMPONENTS_CAST_STREAMING_BROWSER_CAST_STREAMING_SESSION_H_
diff --git a/components/cast_streaming/browser/cast_streaming_session_unittest.cc b/components/cast_streaming/browser/cast_streaming_session_unittest.cc
index bb5c266..930793b 100644
--- a/components/cast_streaming/browser/cast_streaming_session_unittest.cc
+++ b/components/cast_streaming/browser/cast_streaming_session_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/cast_streaming/browser/public/cast_streaming_session.h"
+#include "components/cast_streaming/browser/cast_streaming_session.h"
 
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
diff --git a/components/cast_streaming/browser/public/receiver_session.h b/components/cast_streaming/browser/public/receiver_session.h
new file mode 100644
index 0000000..2032de7a
--- /dev/null
+++ b/components/cast_streaming/browser/public/receiver_session.h
@@ -0,0 +1,45 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CAST_STREAMING_BROWSER_PUBLIC_RECEIVER_SESSION_H_
+#define COMPONENTS_CAST_STREAMING_BROWSER_PUBLIC_RECEIVER_SESSION_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "components/cast_streaming/mojo/cast_streaming_session.mojom.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+
+namespace cast_api_bindings {
+class MessagePort;
+}
+
+namespace cast_streaming {
+
+// This interface handles a single Cast Streaming Receiver Session over a given
+// |message_port| and with a given |cast_streaming_receiver|. On destruction,
+// the Cast Streaming Receiver Session will be terminated if it was ever
+// started.
+class ReceiverSession {
+ public:
+  using MessagePortProvider =
+      base::OnceCallback<std::unique_ptr<cast_api_bindings::MessagePort>()>;
+
+  virtual ~ReceiverSession() = default;
+
+  static std::unique_ptr<ReceiverSession> Create(
+      MessagePortProvider message_port_provider);
+
+  // Sets up the CastStreamingReceiver mojo remote. This will immediately call
+  // CastStreamingReceiver::EnableReceiver(). Upon receiving the callback for
+  // this method, the Cast Streaming Receiver Session will be started and audio
+  // and/or video frames will be sent over a Mojo channel.
+  virtual void SetCastStreamingReceiver(
+      mojo::AssociatedRemote<mojom::CastStreamingReceiver>
+          cast_streaming_receiver) = 0;
+};
+
+}  // namespace cast_streaming
+
+#endif  // COMPONENTS_CAST_STREAMING_BROWSER_PUBLIC_RECEIVER_SESSION_H_
diff --git a/fuchsia/engine/browser/cast_streaming_session_client.cc b/components/cast_streaming/browser/receiver_session_impl.cc
similarity index 71%
rename from fuchsia/engine/browser/cast_streaming_session_client.cc
rename to components/cast_streaming/browser/receiver_session_impl.cc
index dce63eca..e391c2d 100644
--- a/fuchsia/engine/browser/cast_streaming_session_client.cc
+++ b/components/cast_streaming/browser/receiver_session_impl.cc
@@ -2,21 +2,31 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "fuchsia/engine/browser/cast_streaming_session_client.h"
+#include "components/cast_streaming/browser/receiver_session_impl.h"
 
 #include "base/threading/sequenced_task_runner_handle.h"
-#include "components/cast/message_port/message_port_fuchsia.h"
 #include "media/base/audio_decoder_config.h"
 #include "media/base/video_decoder_config.h"
 #include "media/mojo/mojom/media_types.mojom.h"
 
-CastStreamingSessionClient::CastStreamingSessionClient(
-    fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request)
-    : message_port_request_(std::move(message_port_request)) {}
+namespace cast_streaming {
 
-CastStreamingSessionClient::~CastStreamingSessionClient() = default;
+// static
+std::unique_ptr<ReceiverSession> ReceiverSession::Create(
+    ReceiverSession::MessagePortProvider message_port_provider) {
+  return std::make_unique<ReceiverSessionImpl>(
+      std::move(message_port_provider));
+}
 
-void CastStreamingSessionClient::StartMojoConnection(
+ReceiverSessionImpl::ReceiverSessionImpl(
+    ReceiverSession::MessagePortProvider message_port_provider)
+    : message_port_provider_(std::move(message_port_provider)) {
+  DCHECK(message_port_provider_);
+}
+
+ReceiverSessionImpl::~ReceiverSessionImpl() = default;
+
+void ReceiverSessionImpl::SetCastStreamingReceiver(
     mojo::AssociatedRemote<mojom::CastStreamingReceiver>
         cast_streaming_receiver) {
   DVLOG(1) << __func__;
@@ -26,21 +36,19 @@
   // AssociatedRemote, is owned by |this| and will be torn-down at the same time
   // as |this|.
   cast_streaming_receiver_->EnableReceiver(base::BindOnce(
-      &CastStreamingSessionClient::OnReceiverEnabled, base::Unretained(this)));
+      &ReceiverSessionImpl::OnReceiverEnabled, base::Unretained(this)));
   cast_streaming_receiver_.set_disconnect_handler(base::BindOnce(
-      &CastStreamingSessionClient::OnMojoDisconnect, base::Unretained(this)));
+      &ReceiverSessionImpl::OnMojoDisconnect, base::Unretained(this)));
 }
 
-void CastStreamingSessionClient::OnReceiverEnabled() {
+void ReceiverSessionImpl::OnReceiverEnabled() {
   DVLOG(1) << __func__;
-  DCHECK(message_port_request_);
-  cast_streaming_session_.Start(this,
-                                cast_api_bindings::MessagePortFuchsia::Create(
-                                    std::move(message_port_request_)),
+  DCHECK(message_port_provider_);
+  cast_streaming_session_.Start(this, std::move(message_port_provider_).Run(),
                                 base::SequencedTaskRunnerHandle::Get());
 }
 
-void CastStreamingSessionClient::OnSessionInitialization(
+void ReceiverSessionImpl::OnSessionInitialization(
     absl::optional<cast_streaming::CastStreamingSession::AudioStreamInfo>
         audio_stream_info,
     absl::optional<cast_streaming::CastStreamingSession::VideoStreamInfo>
@@ -68,21 +76,21 @@
       std::move(mojo_audio_stream_info), std::move(mojo_video_stream_info));
 }
 
-void CastStreamingSessionClient::OnAudioBufferReceived(
+void ReceiverSessionImpl::OnAudioBufferReceived(
     media::mojom::DecoderBufferPtr buffer) {
   DVLOG(3) << __func__;
   DCHECK(audio_remote_);
   audio_remote_->ProvideBuffer(std::move(buffer));
 }
 
-void CastStreamingSessionClient::OnVideoBufferReceived(
+void ReceiverSessionImpl::OnVideoBufferReceived(
     media::mojom::DecoderBufferPtr buffer) {
   DVLOG(3) << __func__;
   DCHECK(video_remote_);
   video_remote_->ProvideBuffer(std::move(buffer));
 }
 
-void CastStreamingSessionClient::OnSessionReinitialization(
+void ReceiverSessionImpl::OnSessionReinitialization(
     absl::optional<cast_streaming::CastStreamingSession::AudioStreamInfo>
         audio_stream_info,
     absl::optional<cast_streaming::CastStreamingSession::VideoStreamInfo>
@@ -101,7 +109,7 @@
   }
 }
 
-void CastStreamingSessionClient::OnSessionEnded() {
+void ReceiverSessionImpl::OnSessionEnded() {
   DVLOG(1) << __func__;
 
   // Tear down the Mojo connection.
@@ -115,14 +123,12 @@
     video_remote_.reset();
 }
 
-void CastStreamingSessionClient::OnMojoDisconnect() {
+void ReceiverSessionImpl::OnMojoDisconnect() {
   DVLOG(1) << __func__;
 
-  if (message_port_request_) {
-    // Close the MessagePort if the Cast Streaming Session was never started.
-    message_port_request_.Close(ZX_ERR_PEER_CLOSED);
-    cast_streaming_receiver_.reset();
-    return;
+  // Close the underlying connection.
+  if (message_port_provider_) {
+    std::move(message_port_provider_).Run().reset();
   }
 
   // Close the Cast Streaming Session. OnSessionEnded() will be called as part
@@ -133,3 +139,5 @@
   audio_remote_.reset();
   video_remote_.reset();
 }
+
+}  // namespace cast_streaming
diff --git a/fuchsia/engine/browser/cast_streaming_session_client.h b/components/cast_streaming/browser/receiver_session_impl.h
similarity index 60%
rename from fuchsia/engine/browser/cast_streaming_session_client.h
rename to components/cast_streaming/browser/receiver_session_impl.h
index c4fc0ae..58193083 100644
--- a/fuchsia/engine/browser/cast_streaming_session_client.h
+++ b/components/cast_streaming/browser/receiver_session_impl.h
@@ -2,34 +2,33 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef FUCHSIA_ENGINE_BROWSER_CAST_STREAMING_SESSION_CLIENT_H_
-#define FUCHSIA_ENGINE_BROWSER_CAST_STREAMING_SESSION_CLIENT_H_
+#ifndef COMPONENTS_CAST_STREAMING_BROWSER_RECEIVER_SESSION_IMPL_H_
+#define COMPONENTS_CAST_STREAMING_BROWSER_RECEIVER_SESSION_IMPL_H_
 
-#include <fuchsia/web/cpp/fidl.h>
-
-#include "components/cast_streaming/browser/public/cast_streaming_session.h"
+#include "components/cast_streaming/browser/cast_streaming_session.h"
+#include "components/cast_streaming/browser/public/receiver_session.h"
 #include "components/cast_streaming/mojo/cast_streaming_session.mojom.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
+namespace cast_streaming {
+
 // Owns the CastStreamingSession and sends buffers to the renderer process via
 // a Mojo service.
-//
-// TODO(crbug.com/1208194): Move this class to //components/cast_streaming,
-class CastStreamingSessionClient
-    : public cast_streaming::CastStreamingSession::Client {
+class ReceiverSessionImpl : public cast_streaming::CastStreamingSession::Client,
+                            public ReceiverSession {
  public:
-  explicit CastStreamingSessionClient(
-      fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request);
-  ~CastStreamingSessionClient() final;
+  explicit ReceiverSessionImpl(MessagePortProvider message_port_provider);
+  ~ReceiverSessionImpl() final;
 
-  CastStreamingSessionClient(const CastStreamingSessionClient&) = delete;
-  CastStreamingSessionClient& operator=(const CastStreamingSessionClient&) =
-      delete;
+  ReceiverSessionImpl(const ReceiverSessionImpl&) = delete;
+  ReceiverSessionImpl& operator=(const ReceiverSessionImpl&) = delete;
 
-  void StartMojoConnection(mojo::AssociatedRemote<mojom::CastStreamingReceiver>
-                               cast_streaming_receiver);
+  // ReceiverSession implementation.
+  void SetCastStreamingReceiver(
+      mojo::AssociatedRemote<mojom::CastStreamingReceiver>
+          cast_streaming_receiver) override;
 
  private:
   // Handler for |cast_streaming_receiver_| disconnect.
@@ -53,7 +52,10 @@
           video_stream_info) final;
   void OnSessionEnded() final;
 
-  fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request_;
+  // Populated in the ctor, and empty following a call to either
+  // OnReceiverEnabled() or OnMojoDisconnect().
+  MessagePortProvider message_port_provider_;
+
   mojo::AssociatedRemote<mojom::CastStreamingReceiver> cast_streaming_receiver_;
   cast_streaming::CastStreamingSession cast_streaming_session_;
 
@@ -61,4 +63,6 @@
   mojo::Remote<mojom::CastStreamingBufferReceiver> video_remote_;
 };
 
-#endif  // FUCHSIA_ENGINE_BROWSER_CAST_STREAMING_SESSION_CLIENT_H_
+}  // namespace cast_streaming
+
+#endif  // COMPONENTS_CAST_STREAMING_BROWSER_RECEIVER_SESSION_IMPL_H_
diff --git a/components/cast_streaming/browser/test/cast_streaming_test_receiver.h b/components/cast_streaming/browser/test/cast_streaming_test_receiver.h
index 28b9fd9..fcec931 100644
--- a/components/cast_streaming/browser/test/cast_streaming_test_receiver.h
+++ b/components/cast_streaming/browser/test/cast_streaming_test_receiver.h
@@ -7,7 +7,7 @@
 
 #include "base/callback.h"
 #include "components/cast/message_port/message_port.h"
-#include "components/cast_streaming/browser/public/cast_streaming_session.h"
+#include "components/cast_streaming/browser/cast_streaming_session.h"
 #include "media/mojo/common/mojo_decoder_buffer_converter.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
diff --git a/components/cast_streaming/browser/test/run_all_unittests.cc b/components/cast_streaming/browser/test/run_all_unittests.cc
index b092301..21817cd4 100644
--- a/components/cast_streaming/browser/test/run_all_unittests.cc
+++ b/components/cast_streaming/browser/test/run_all_unittests.cc
@@ -5,7 +5,7 @@
 #include "base/bind.h"
 #include "base/test/launcher/unit_test_launcher.h"
 #include "base/test/test_suite.h"
-#include "components/cast_streaming/browser/public/cast_streaming_session.h"
+#include "components/cast_streaming/browser/cast_streaming_session.h"
 #include "mojo/core/embedder/embedder.h"
 
 int main(int argc, char** argv) {
diff --git a/components/cbor/reader.cc b/components/cbor/reader.cc
index d1fd6f20..f81eaf2 100644
--- a/components/cbor/reader.cc
+++ b/components/cbor/reader.cc
@@ -12,7 +12,6 @@
 #include "base/notreached.h"
 #include "base/numerics/checked_math.h"
 #include "base/numerics/safe_conversions.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "components/cbor/constants.h"
 
diff --git a/components/certificate_transparency/ct_known_logs.cc b/components/certificate_transparency/ct_known_logs.cc
index d5935ff9..5b8da33 100644
--- a/components/certificate_transparency/ct_known_logs.cc
+++ b/components/certificate_transparency/ct_known_logs.cc
@@ -11,7 +11,6 @@
 #include <iterator>
 
 #include "base/macros.h"
-#include "base/stl_util.h"
 #include "base/time/time.h"
 #include "crypto/sha2.h"
 
diff --git a/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc b/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc
index a8c569dd..b550641 100644
--- a/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc
+++ b/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc
@@ -27,7 +27,6 @@
 #include "base/numerics/safe_conversions.h"
 #include "base/path_service.h"
 #include "base/posix/eintr_wrapper.h"
-#include "base/stl_util.h"
 #include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread.h"
diff --git a/components/component_updater/configurator_impl.cc b/components/component_updater/configurator_impl.cc
index 98990d712..53dda33 100644
--- a/components/component_updater/configurator_impl.cc
+++ b/components/component_updater/configurator_impl.cc
@@ -10,7 +10,6 @@
 
 #include "base/callback.h"
 #include "base/feature_list.h"
-#include "base/stl_util.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/version.h"
diff --git a/components/component_updater/installer_policies/origin_trials_component_installer.cc b/components/component_updater/installer_policies/origin_trials_component_installer.cc
index 6122093..e24a05af 100644
--- a/components/component_updater/installer_policies/origin_trials_component_installer.cc
+++ b/components/component_updater/installer_policies/origin_trials_component_installer.cc
@@ -14,7 +14,6 @@
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/path_service.h"
-#include "base/stl_util.h"
 #include "base/values.h"
 #include "components/component_updater/component_updater_paths.h"
 
diff --git a/components/consent_auditor/consent_sync_bridge_impl.cc b/components/consent_auditor/consent_sync_bridge_impl.cc
index ca51b34..d49f0f24 100644
--- a/components/consent_auditor/consent_sync_bridge_impl.cc
+++ b/components/consent_auditor/consent_sync_bridge_impl.cc
@@ -13,7 +13,6 @@
 #include "base/callback_helpers.h"
 #include "base/location.h"
 #include "base/logging.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "build/build_config.h"
 #include "components/sync/model/data_type_activation_request.h"
diff --git a/components/content_settings/browser/page_specific_content_settings.cc b/components/content_settings/browser/page_specific_content_settings.cc
index 0a206ad4..20cab53 100644
--- a/components/content_settings/browser/page_specific_content_settings.cc
+++ b/components/content_settings/browser/page_specific_content_settings.cc
@@ -10,7 +10,6 @@
 #include "base/command_line.h"
 #include "base/lazy_instance.h"
 #include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
diff --git a/components/content_settings/core/browser/content_settings_pref_unittest.cc b/components/content_settings/core/browser/content_settings_pref_unittest.cc
index 1ebaa09e..f7acbb5 100644
--- a/components/content_settings/core/browser/content_settings_pref_unittest.cc
+++ b/components/content_settings/core/browser/content_settings_pref_unittest.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/callback_helpers.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/test/gtest_util.h"
 #include "base/values.h"
diff --git a/components/cronet/stale_host_resolver.cc b/components/cronet/stale_host_resolver.cc
index 6983ad3..ad56a6c1 100644
--- a/components/cronet/stale_host_resolver.cc
+++ b/components/cronet/stale_host_resolver.cc
@@ -12,7 +12,6 @@
 #include "base/callback_helpers.h"
 #include "base/check_op.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "base/timer/timer.h"
 #include "base/values.h"
 #include "net/base/host_port_pair.h"
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc
index 6d7a7aa..7b67569 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc
@@ -12,7 +12,6 @@
 
 #include "base/metrics/field_trial_params.h"
 #include "base/rand_util.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
diff --git a/components/dbus/properties/dbus_properties.h b/components/dbus/properties/dbus_properties.h
index ac25d69..65ecdcc5 100644
--- a/components/dbus/properties/dbus_properties.h
+++ b/components/dbus/properties/dbus_properties.h
@@ -9,7 +9,6 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/stl_util.h"
 #include "components/dbus/properties/types.h"
 #include "dbus/bus.h"
 #include "dbus/exported_object.h"
diff --git a/components/dom_distiller/content/renderer/distillability_agent.cc b/components/dom_distiller/content/renderer/distillability_agent.cc
index 3f75c87..77901f87 100644
--- a/components/dom_distiller/content/renderer/distillability_agent.cc
+++ b/components/dom_distiller/content/renderer/distillability_agent.cc
@@ -6,7 +6,6 @@
 
 #include "base/json/json_writer.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "components/dom_distiller/content/common/mojom/distillability_service.mojom.h"
 #include "components/dom_distiller/core/distillable_page_detector.h"
diff --git a/components/dom_distiller/core/task_tracker.cc b/components/dom_distiller/core/task_tracker.cc
index 9d916a7d..f0f1c79d 100644
--- a/components/dom_distiller/core/task_tracker.cc
+++ b/components/dom_distiller/core/task_tracker.cc
@@ -12,7 +12,6 @@
 #include "base/auto_reset.h"
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/dom_distiller/core/distilled_content_store.h"
 #include "components/dom_distiller/core/proto/distilled_article.pb.h"
diff --git a/components/download/internal/common/download_item_impl.cc b/components/download/internal/common/download_item_impl.cc
index 2d56947d..29db91f 100644
--- a/components/download/internal/common/download_item_impl.cc
+++ b/components/download/internal/common/download_item_impl.cc
@@ -34,7 +34,6 @@
 #include "base/json/string_escape.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
diff --git a/components/download/internal/common/download_stats.cc b/components/download/internal/common/download_stats.cc
index 7095d8a1..d7ece36 100644
--- a/components/download/internal/common/download_stats.cc
+++ b/components/download/internal/common/download_stats.cc
@@ -10,7 +10,6 @@
 #include "base/files/file_path.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "build/build_config.h"
 #include "components/download/public/common/download_danger_type.h"
diff --git a/components/exo/buffer.cc b/components/exo/buffer.cc
index 8a5fdcf..eafd8447 100644
--- a/components/exo/buffer.cc
+++ b/components/exo/buffer.cc
@@ -13,7 +13,6 @@
 #include "base/callback_helpers.h"
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
-#include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
diff --git a/components/exo/frame_sink_resource_manager.cc b/components/exo/frame_sink_resource_manager.cc
index 6b6c46b..dfac8353 100644
--- a/components/exo/frame_sink_resource_manager.cc
+++ b/components/exo/frame_sink_resource_manager.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "base/stl_util.h"
 
 namespace exo {
 
diff --git a/components/feed/core/v2/web_feed_subscriptions/subscribe_to_web_feed_task.cc b/components/feed/core/v2/web_feed_subscriptions/subscribe_to_web_feed_task.cc
index a1c7197..6aa60bf 100644
--- a/components/feed/core/v2/web_feed_subscriptions/subscribe_to_web_feed_task.cc
+++ b/components/feed/core/v2/web_feed_subscriptions/subscribe_to_web_feed_task.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 
 #include "base/bind.h"
-#include "base/stl_util.h"
 #include "components/feed/core/v2/feed_stream.h"
 #include "components/feed/core/v2/web_feed_subscription_coordinator.h"
 #include "components/feed/core/v2/web_feed_subscriptions/wire_to_store.h"
diff --git a/components/feed/core/v2/web_feed_subscriptions/unsubscribe_from_web_feed_task.cc b/components/feed/core/v2/web_feed_subscriptions/unsubscribe_from_web_feed_task.cc
index fb9a7fb..ea9f433 100644
--- a/components/feed/core/v2/web_feed_subscriptions/unsubscribe_from_web_feed_task.cc
+++ b/components/feed/core/v2/web_feed_subscriptions/unsubscribe_from_web_feed_task.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 
 #include "base/bind.h"
-#include "base/stl_util.h"
 #include "components/feed/core/proto/v2/store.pb.h"
 #include "components/feed/core/proto/v2/wire/web_feeds.pb.h"
 #include "components/feed/core/v2/feed_store.h"
diff --git a/components/flags_ui/feature_entry_macros.h b/components/flags_ui/feature_entry_macros.h
index 132f094..accb85c 100644
--- a/components/flags_ui/feature_entry_macros.h
+++ b/components/flags_ui/feature_entry_macros.h
@@ -5,7 +5,6 @@
 #ifndef COMPONENTS_FLAGS_UI_FEATURE_ENTRY_MACROS_H_
 #define COMPONENTS_FLAGS_UI_FEATURE_ENTRY_MACROS_H_
 
-#include "base/stl_util.h"
 
 // Macros to simplify specifying the type of FeatureEntry. Please refer to
 // the comments on FeatureEntry::Type in feature_entry.h, which explain the
diff --git a/components/gcm_driver/gcm_client_impl.cc b/components/gcm_driver/gcm_client_impl.cc
index d71b3ee..fec98045 100644
--- a/components/gcm_driver/gcm_client_impl.cc
+++ b/components/gcm_driver/gcm_client_impl.cc
@@ -18,7 +18,6 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/time/default_clock.h"
 #include "base/timer/timer.h"
diff --git a/components/gcm_driver/instance_id/instance_id_android.cc b/components/gcm_driver/instance_id/instance_id_android.cc
index ed79682d..4dea8b052 100644
--- a/components/gcm_driver/instance_id/instance_id_android.cc
+++ b/components/gcm_driver/instance_id/instance_id_android.cc
@@ -13,7 +13,6 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/logging.h"
-#include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "components/gcm_driver/instance_id/android/jni_headers/InstanceIDBridge_jni.h"
diff --git a/components/history/core/browser/history_types.cc b/components/history/core/browser/history_types.cc
index 1e77d11..d140c059 100644
--- a/components/history/core/browser/history_types.cc
+++ b/components/history/core/browser/history_types.cc
@@ -8,7 +8,6 @@
 
 #include "base/check.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "components/history/core/browser/page_usage_data.h"
 
 namespace history {
diff --git a/components/invalidation/impl/fcm_invalidation_listener_unittest.cc b/components/invalidation/impl/fcm_invalidation_listener_unittest.cc
index f53a53f..a331d07 100644
--- a/components/invalidation/impl/fcm_invalidation_listener_unittest.cc
+++ b/components/invalidation/impl/fcm_invalidation_listener_unittest.cc
@@ -8,7 +8,6 @@
 #include <vector>
 
 #include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/test/task_environment.h"
 #include "components/invalidation/impl/fcm_invalidation_listener.h"
diff --git a/components/invalidation/impl/per_user_topic_subscription_manager.cc b/components/invalidation/impl/per_user_topic_subscription_manager.cc
index afc5f19..9c22e8f3 100644
--- a/components/invalidation/impl/per_user_topic_subscription_manager.cc
+++ b/components/invalidation/impl/per_user_topic_subscription_manager.cc
@@ -16,7 +16,6 @@
 #include "base/bind.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/rand_util.h"
-#include "base/stl_util.h"
 #include "base/strings/strcat.h"
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
diff --git a/components/invalidation/impl/per_user_topic_subscription_manager_unittest.cc b/components/invalidation/impl/per_user_topic_subscription_manager_unittest.cc
index ffafa132..1ec91a55 100644
--- a/components/invalidation/impl/per_user_topic_subscription_manager_unittest.cc
+++ b/components/invalidation/impl/per_user_topic_subscription_manager_unittest.cc
@@ -8,7 +8,6 @@
 #include "base/json/json_string_value_serializer.h"
 #include "base/json/json_writer.h"
 #include "base/run_loop.h"
-#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
diff --git a/components/leveldb_proto/public/shared_proto_database_client_list.cc b/components/leveldb_proto/public/shared_proto_database_client_list.cc
index 669844f..23123df 100644
--- a/components/leveldb_proto/public/shared_proto_database_client_list.cc
+++ b/components/leveldb_proto/public/shared_proto_database_client_list.cc
@@ -9,7 +9,6 @@
 #include <string>
 
 #include "base/metrics/field_trial_params.h"
-#include "base/stl_util.h"
 
 #include "base/notreached.h"
 #include "components/leveldb_proto/internal/leveldb_proto_feature_list.h"
diff --git a/components/media_message_center/media_notification_view_modern_impl.cc b/components/media_message_center/media_notification_view_modern_impl.cc
index 7cdd4db..4fc8015 100644
--- a/components/media_message_center/media_notification_view_modern_impl.cc
+++ b/components/media_message_center/media_notification_view_modern_impl.cc
@@ -6,7 +6,6 @@
 
 #include "base/containers/contains.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
 #include "components/media_message_center/media_artwork_view.h"
 #include "components/media_message_center/media_controls_progress_view.h"
 #include "components/media_message_center/media_notification_background_impl.h"
diff --git a/components/media_router/browser/media_router_base.cc b/components/media_router/browser/media_router_base.cc
index d1d3b05f..89e5e21 100644
--- a/components/media_router/browser/media_router_base.cc
+++ b/components/media_router/browser/media_router_base.cc
@@ -8,7 +8,6 @@
 
 #include "base/bind.h"
 #include "base/guid.h"
-#include "base/stl_util.h"
 #include "content/public/browser/browser_thread.h"
 
 using blink::mojom::PresentationConnectionState;
diff --git a/components/metrics/call_stack_profile_builder.cc b/components/metrics/call_stack_profile_builder.cc
index 93cdaca..e0e46a66 100644
--- a/components/metrics/call_stack_profile_builder.cc
+++ b/components/metrics/call_stack_profile_builder.cc
@@ -16,7 +16,6 @@
 #include "base/logging.h"
 #include "base/metrics/metrics_hashes.h"
 #include "base/no_destructor.h"
-#include "base/stl_util.h"
 #include "build/build_config.h"
 #include "components/metrics/call_stack_profile_encoding.h"
 
diff --git a/components/metrics/metrics_service_unittest.cc b/components/metrics/metrics_service_unittest.cc
index ebdd2065..5d84be0 100644
--- a/components/metrics/metrics_service_unittest.cc
+++ b/components/metrics/metrics_service_unittest.cc
@@ -17,7 +17,6 @@
 #include "base/metrics/metrics_hashes.h"
 #include "base/metrics/statistics_recorder.h"
 #include "base/metrics/user_metrics.h"
-#include "base/stl_util.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/platform_thread.h"
diff --git a/components/mirroring/service/receiver_setup_querier.cc b/components/mirroring/service/receiver_setup_querier.cc
index 8ccfdbc..06184b4b 100644
--- a/components/mirroring/service/receiver_setup_querier.cc
+++ b/components/mirroring/service/receiver_setup_querier.cc
@@ -9,7 +9,6 @@
 
 #include "base/bind.h"
 #include "base/json/json_reader.h"
-#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "components/mirroring/service/value_util.h"
 #include "components/version_info/version_info.h"
diff --git a/components/offline_items_collection/core/offline_content_aggregator.cc b/components/offline_items_collection/core/offline_content_aggregator.cc
index c75e87a1..9246cb48 100644
--- a/components/offline_items_collection/core/offline_content_aggregator.cc
+++ b/components/offline_items_collection/core/offline_content_aggregator.cc
@@ -7,7 +7,6 @@
 #include <utility>
 
 #include "base/bind.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/offline_items_collection/core/offline_content_aggregator.h"
diff --git a/components/offline_pages/core/background/request_coordinator.cc b/components/offline_pages/core/background/request_coordinator.cc
index ab220e9d..4682118 100644
--- a/components/offline_pages/core/background/request_coordinator.cc
+++ b/components/offline_pages/core/background/request_coordinator.cc
@@ -15,7 +15,6 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/rand_util.h"
-#include "base/stl_util.h"
 #include "base/system/sys_info.h"
 #include "base/time/time.h"
 #include "components/offline_pages/core/background/offliner.h"
diff --git a/components/omnibox/browser/location_bar_model_delegate.cc b/components/omnibox/browser/location_bar_model_delegate.cc
index 929c4b4..c900de4 100644
--- a/components/omnibox/browser/location_bar_model_delegate.cc
+++ b/components/omnibox/browser/location_bar_model_delegate.cc
@@ -16,6 +16,11 @@
   return true;
 }
 
+bool LocationBarModelDelegate::ShouldUseUpdatedConnectionSecurityIndicators()
+    const {
+  return false;
+}
+
 security_state::SecurityLevel LocationBarModelDelegate::GetSecurityLevel()
     const {
   return security_state::NONE;
diff --git a/components/omnibox/browser/location_bar_model_delegate.h b/components/omnibox/browser/location_bar_model_delegate.h
index 0c5825d..a135dea 100644
--- a/components/omnibox/browser/location_bar_model_delegate.h
+++ b/components/omnibox/browser/location_bar_model_delegate.h
@@ -49,6 +49,10 @@
   // in the location bar.
   virtual bool ShouldDisplayURL() const;
 
+  // Returns whether the omnibox should use the new security indicators for
+  // secure HTTPS connections.
+  virtual bool ShouldUseUpdatedConnectionSecurityIndicators() const;
+
   // Returns the underlying security level of the page without regard to any
   // user edits that may be in progress.
   virtual security_state::SecurityLevel GetSecurityLevel() const;
diff --git a/components/omnibox/browser/location_bar_model_impl.cc b/components/omnibox/browser/location_bar_model_impl.cc
index c4dcfd7..0efffc14 100644
--- a/components/omnibox/browser/location_bar_model_impl.cc
+++ b/components/omnibox/browser/location_bar_model_impl.cc
@@ -207,7 +207,9 @@
     return omnibox::kOfflinePinIcon;
 #endif
 
-  return location_bar_model::GetSecurityVectorIcon(GetSecurityLevel());
+  return location_bar_model::GetSecurityVectorIcon(
+      GetSecurityLevel(),
+      delegate_->ShouldUseUpdatedConnectionSecurityIndicators());
 }
 
 std::u16string LocationBarModelImpl::GetSecureDisplayText() const {
diff --git a/components/omnibox/browser/location_bar_model_util.cc b/components/omnibox/browser/location_bar_model_util.cc
index 7a20e59..3378f8e4 100644
--- a/components/omnibox/browser/location_bar_model_util.cc
+++ b/components/omnibox/browser/location_bar_model_util.cc
@@ -19,14 +19,14 @@
 namespace location_bar_model {
 
 const gfx::VectorIcon& GetSecurityVectorIcon(
-    security_state::SecurityLevel security_level) {
+    security_state::SecurityLevel security_level,
+    bool use_updated_connection_security_indicators) {
 #if (!defined(OS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !defined(OS_IOS)
   switch (security_level) {
     case security_state::NONE:
       return omnibox::kHttpIcon;
     case security_state::SECURE: {
-      return base::FeatureList::IsEnabled(
-                 omnibox::kUpdatedConnectionSecurityIndicators)
+      return use_updated_connection_security_indicators
                  ? vector_icons::kHttpsValidArrowIcon
                  : vector_icons::kHttpsValidIcon;
     }
diff --git a/components/omnibox/browser/location_bar_model_util.h b/components/omnibox/browser/location_bar_model_util.h
index 00803fc..e7ae55a 100644
--- a/components/omnibox/browser/location_bar_model_util.h
+++ b/components/omnibox/browser/location_bar_model_util.h
@@ -13,10 +13,13 @@
 
 namespace location_bar_model {
 
-// Get the vector icon according to security level.
-// It indicates security state of the page.
+// Get the vector icon according to security level. It indicates security state
+// of the page. If |use_updated_connection_security_indicators| is true, this
+// function will return the updated "connection secure" icon if |security_level|
+// indicates a secure connection.
 const gfx::VectorIcon& GetSecurityVectorIcon(
-    security_state::SecurityLevel security_level);
+    security_state::SecurityLevel security_level,
+    bool use_updated_connection_security_indicators);
 
 }  // namespace location_bar_model
 
diff --git a/components/omnibox/browser/location_bar_model_util_unittest.cc b/components/omnibox/browser/location_bar_model_util_unittest.cc
index 39e0f574..8e208403 100644
--- a/components/omnibox/browser/location_bar_model_util_unittest.cc
+++ b/components/omnibox/browser/location_bar_model_util_unittest.cc
@@ -11,31 +11,44 @@
 
 TEST(LocationBarModelUtilTest, GetSecurityVectorIconWithNoneLevel) {
   const gfx::VectorIcon& icon = location_bar_model::GetSecurityVectorIcon(
-      security_state::SecurityLevel::NONE);
+      security_state::SecurityLevel::NONE,
+      /*use_updated_connection_security_indicators=*/false);
   EXPECT_EQ(icon.name, omnibox::kHttpIcon.name);
 }
 
 TEST(LocationBarModelUtilTest, GetSecurityVectorIconWithSecureLevel) {
   const gfx::VectorIcon& icon = location_bar_model::GetSecurityVectorIcon(
-      security_state::SecurityLevel::SECURE);
+      security_state::SecurityLevel::SECURE,
+      /*use_updated_connection_security_indicators=*/false);
   EXPECT_EQ(icon.name, vector_icons::kHttpsValidIcon.name);
 }
 
 TEST(LocationBarModelUtilTest,
+     GetSecurityVectorIconWithSecureLevelUpdatedIcon) {
+  const gfx::VectorIcon& icon = location_bar_model::GetSecurityVectorIcon(
+      security_state::SecurityLevel::SECURE,
+      /*use_updated_connection_security_indicators=*/true);
+  EXPECT_EQ(icon.name, vector_icons::kHttpsValidArrowIcon.name);
+}
+
+TEST(LocationBarModelUtilTest,
      GetSecurityVectorIconWithSecureWithPolicyInstalledCertLevel) {
   const gfx::VectorIcon& icon = location_bar_model::GetSecurityVectorIcon(
-      security_state::SecurityLevel::SECURE_WITH_POLICY_INSTALLED_CERT);
+      security_state::SecurityLevel::SECURE_WITH_POLICY_INSTALLED_CERT,
+      /*use_updated_connection_security_indicators=*/false);
   EXPECT_EQ(icon.name, vector_icons::kBusinessIcon.name);
 }
 
 TEST(LocationBarModelUtilTest, GetSecurityVectorIconWithDangerousLevel) {
   const gfx::VectorIcon& icon = location_bar_model::GetSecurityVectorIcon(
-      security_state::SecurityLevel::DANGEROUS);
+      security_state::SecurityLevel::DANGEROUS,
+      /*use_updated_connection_security_indicators=*/false);
   EXPECT_EQ(icon.name, vector_icons::kNotSecureWarningIcon.name);
 }
 
 TEST(LocationBarModelUtilTest, GetSecurityVectorIconWithWarningLevel) {
   const gfx::VectorIcon& icon = location_bar_model::GetSecurityVectorIcon(
-      security_state::SecurityLevel::WARNING);
+      security_state::SecurityLevel::WARNING,
+      /*use_updated_connection_security_indicators=*/false);
   EXPECT_EQ(icon.name, vector_icons::kNotSecureWarningIcon.name);
 }
diff --git a/components/omnibox/browser/omnibox_prefs.cc b/components/omnibox/browser/omnibox_prefs.cc
index 9aeeffeb..802b8c5e 100644
--- a/components/omnibox/browser/omnibox_prefs.cc
+++ b/components/omnibox/browser/omnibox_prefs.cc
@@ -6,7 +6,6 @@
 
 #include "base/check.h"
 #include "base/metrics/sparse_histogram.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/values.h"
 #include "components/pref_registry/pref_registry_syncable.h"
@@ -35,6 +34,11 @@
 const char kKeywordSpaceTriggeringEnabled[] =
     "omnibox.keyword_space_triggering_enabled";
 
+// Boolean that specifies whether the omnibox should display a lock icon for
+// secure connections.
+const char kLockIconInAddressBarEnabled[] =
+    "omnibox.lock_icon_in_address_bar_enabled";
+
 // A dictionary of visibility preferences for suggestion groups. The key is the
 // suggestion group ID serialized as a string, and the value is
 // SuggestionGroupVisibility serialized as an integer.
diff --git a/components/omnibox/browser/omnibox_prefs.h b/components/omnibox/browser/omnibox_prefs.h
index 379337b..fcb1ea6 100644
--- a/components/omnibox/browser/omnibox_prefs.h
+++ b/components/omnibox/browser/omnibox_prefs.h
@@ -34,6 +34,7 @@
 extern const char kDocumentSuggestEnabled[];
 extern const char kIntranetRedirectBehavior[];
 extern const char kKeywordSpaceTriggeringEnabled[];
+extern const char kLockIconInAddressBarEnabled[];
 extern const char kSuggestionGroupVisibility[];
 extern const char kPreventUrlElisionsInOmnibox[];
 extern const char kZeroSuggestCachedResults[];
diff --git a/components/omnibox/browser/test_scheme_classifier.cc b/components/omnibox/browser/test_scheme_classifier.cc
index b4ddbbe..fb851432 100644
--- a/components/omnibox/browser/test_scheme_classifier.cc
+++ b/components/omnibox/browser/test_scheme_classifier.cc
@@ -6,7 +6,6 @@
 
 #include <string>
 
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "build/build_config.h"
 #include "components/omnibox/browser/test_scheme_classifier.h"
diff --git a/components/omnibox/browser/zero_suggest_provider.cc b/components/omnibox/browser/zero_suggest_provider.cc
index 74e0f5d..7a42b57 100644
--- a/components/omnibox/browser/zero_suggest_provider.cc
+++ b/components/omnibox/browser/zero_suggest_provider.cc
@@ -16,7 +16,6 @@
 #include "base/json/json_string_value_serializer.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
diff --git a/components/page_info/page_info.cc b/components/page_info/page_info.cc
index 4d970f4..9eaadaf 100644
--- a/components/page_info/page_info.cc
+++ b/components/page_info/page_info.cc
@@ -17,7 +17,6 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
diff --git a/components/page_load_metrics/renderer/page_resource_data_use.cc b/components/page_load_metrics/renderer/page_resource_data_use.cc
index cf3100c..53a47e9 100644
--- a/components/page_load_metrics/renderer/page_resource_data_use.cc
+++ b/components/page_load_metrics/renderer/page_resource_data_use.cc
@@ -4,7 +4,6 @@
 
 #include "components/page_load_metrics/renderer/page_resource_data_use.h"
 
-#include "base/stl_util.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
 #include "services/network/public/cpp/url_loader_completion_status.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
diff --git a/components/password_manager/core/browser/form_fetcher_impl_unittest.cc b/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
index 7afd341..bb9aeb92 100644
--- a/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
+++ b/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
@@ -11,7 +11,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
diff --git a/components/password_manager/core/browser/hash_password_manager.cc b/components/password_manager/core/browser/hash_password_manager.cc
index 4f197f27..4f3b2683 100644
--- a/components/password_manager/core/browser/hash_password_manager.cc
+++ b/components/password_manager/core/browser/hash_password_manager.cc
@@ -7,7 +7,6 @@
 #include <vector>
 
 #include "base/base64.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "components/os_crypt/os_crypt.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc
index 06dce4d..b1840173 100644
--- a/components/password_manager/core/browser/login_database.cc
+++ b/components/password_manager/core/browser/login_database.cc
@@ -21,7 +21,6 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/pickle.h"
-#include "base/stl_util.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc
index 3a2374a..fba3b0f 100644
--- a/components/password_manager/core/browser/password_form_manager.cc
+++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -18,7 +18,6 @@
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
 #include "base/ranges/algorithm.h"
-#include "base/stl_util.h"
 #include "build/build_config.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/password_form_generation_data.h"
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc
index ec056841..b280d0a 100644
--- a/components/password_manager/core/browser/password_manager.cc
+++ b/components/password_manager/core/browser/password_manager.cc
@@ -183,15 +183,6 @@
   }
 }
 
-FormData SimplifiedFormDataFromFormStructure(
-    const FormStructure& form_structure) {
-  FormData form_data;
-  form_data.name = form_structure.form_name();
-  form_data.is_form_tag = form_structure.is_form_tag();
-  form_data.unique_renderer_id = form_structure.unique_renderer_id();
-  return form_data;
-}
-
 bool HasMutedCredentials(base::span<const InsecureCredential> credentials,
                          const std::u16string& username) {
   return base::ranges::any_of(credentials, [&username](const auto& credential) {
@@ -1122,8 +1113,7 @@
   for (const FormStructure* form : forms) {
     if (logger)
       logger->LogFormStructure(Logger::STRING_SERVER_PREDICTIONS, *form);
-    FormData form_data = SimplifiedFormDataFromFormStructure(*form);
-    if (GetMatchedManager(driver, form_data.unique_renderer_id)) {
+    if (GetMatchedManager(driver, form->global_id().renderer_id)) {
       // The form manager is already created.
       continue;
     }
diff --git a/components/password_manager/core/browser/password_manager_util_unittest.cc b/components/password_manager/core/browser/password_manager_util_unittest.cc
index 3368615..1ad2b215 100644
--- a/components/password_manager/core/browser/password_manager_util_unittest.cc
+++ b/components/password_manager/core/browser/password_manager_util_unittest.cc
@@ -11,7 +11,6 @@
 
 #include "base/callback_helpers.h"
 #include "base/macros.h"
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "components/autofill/core/common/password_generation_util.h"
diff --git a/components/password_manager/core/browser/password_store_impl.cc b/components/password_manager/core/browser/password_store_impl.cc
index f48182e..0e3f696 100644
--- a/components/password_manager/core/browser/password_store_impl.cc
+++ b/components/password_manager/core/browser/password_store_impl.cc
@@ -10,7 +10,6 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
-#include "base/stl_util.h"
 #include "components/password_manager/core/browser/password_store_change.h"
 #include "components/prefs/pref_service.h"
 
diff --git a/components/password_manager/core/browser/password_store_impl_unittest.cc b/components/password_manager/core/browser/password_store_impl_unittest.cc
index b78ba4e..cc732e1 100644
--- a/components/password_manager/core/browser/password_store_impl_unittest.cc
+++ b/components/password_manager/core/browser/password_store_impl_unittest.cc
@@ -11,7 +11,6 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/run_loop.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/task_environment.h"
diff --git a/components/password_manager/core/browser/password_store_unittest.cc b/components/password_manager/core/browser/password_store_unittest.cc
index 75947b39..b49de5d3 100644
--- a/components/password_manager/core/browser/password_store_unittest.cc
+++ b/components/password_manager/core/browser/password_store_unittest.cc
@@ -11,7 +11,6 @@
 #include "base/callback_helpers.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/run_loop.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
diff --git a/components/password_manager/core/browser/psl_matching_helper_unittest.cc b/components/password_manager/core/browser/psl_matching_helper_unittest.cc
index 5808a27d..6d631d92 100644
--- a/components/password_manager/core/browser/psl_matching_helper_unittest.cc
+++ b/components/password_manager/core/browser/psl_matching_helper_unittest.cc
@@ -8,7 +8,6 @@
 #include <cctype>
 
 #include "base/macros.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/password_manager/core/browser/sync_credentials_filter_unittest.cc b/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
index 9dacb2a..0d5b8a60 100644
--- a/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
+++ b/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
@@ -13,7 +13,6 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/macros.h"
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/metrics/user_action_tester.h"
 #include "base/test/scoped_feature_list.h"
diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc
index dcf3d16..3cd6d0d1 100644
--- a/components/password_manager/core/common/password_manager_features.cc
+++ b/components/password_manager/core/common/password_manager_features.cc
@@ -148,6 +148,18 @@
 const base::Feature kTreatNewPasswordHeuristicsAsReliable = {
     "TreatNewPasswordHeuristicsAsReliable", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Controls whether we should use the new header images for the legacy save
+// password bubble.
+const base::Feature kUseNewHeaderForLegacySavePasswordBubble{
+    "UseNewHeaderForLegacySavePasswordBubble",
+    base::FEATURE_ENABLED_BY_DEFAULT};
+
+// Controls whether we should use the new header images for the save
+// password bubble with account store.
+const base::Feature kUseNewHeaderForSavePasswordWithAccountStoreBubble{
+    "UseNewHeaderForSavePasswordWithAccountStoreBubble",
+    base::FEATURE_ENABLED_BY_DEFAULT};
+
 // Enables use of Hash Affiliation fetcher for all requests.
 const base::Feature kUseOfHashAffiliationFetcher = {
     "UseOfHashAffiliationFetcher", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/password_manager/core/common/password_manager_features.h b/components/password_manager/core/common/password_manager_features.h
index 5d323d4..85ace627 100644
--- a/components/password_manager/core/common/password_manager_features.h
+++ b/components/password_manager/core/common/password_manager_features.h
@@ -41,6 +41,8 @@
 extern const base::Feature kSecondaryServerFieldPredictions;
 extern const base::Feature kSyncingCompromisedCredentials;
 extern const base::Feature kTreatNewPasswordHeuristicsAsReliable;
+extern const base::Feature kUseNewHeaderForLegacySavePasswordBubble;
+extern const base::Feature kUseNewHeaderForSavePasswordWithAccountStoreBubble;
 extern const base::Feature kUseOfHashAffiliationFetcher;
 extern const base::Feature kUsernameFirstFlow;
 
diff --git a/components/payments/content/autofill_payment_app.cc b/components/payments/content/autofill_payment_app.cc
index 25abbc2..ea80ca4c 100644
--- a/components/payments/content/autofill_payment_app.cc
+++ b/components/payments/content/autofill_payment_app.cc
@@ -10,7 +10,6 @@
 #include "base/bind.h"
 #include "base/json/json_writer.h"
 #include "base/metrics/histogram_functions.h"
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "components/autofill/core/browser/autofill_data_util.h"
diff --git a/components/payments/core/can_make_payment_query.cc b/components/payments/core/can_make_payment_query.cc
index 567395b..fc537da 100644
--- a/components/payments/core/can_make_payment_query.cc
+++ b/components/payments/core/can_make_payment_query.cc
@@ -9,7 +9,6 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/location.h"
-#include "base/stl_util.h"
 #include "base/time/time.h"
 #include "components/payments/core/features.h"
 #include "url/gurl.h"
diff --git a/components/performance_manager/execution_context_priority/boosting_vote_aggregator.cc b/components/performance_manager/execution_context_priority/boosting_vote_aggregator.cc
index f4dbf442..fb6617d2 100644
--- a/components/performance_manager/execution_context_priority/boosting_vote_aggregator.cc
+++ b/components/performance_manager/execution_context_priority/boosting_vote_aggregator.cc
@@ -8,7 +8,6 @@
 #include <tuple>
 #include <utility>
 
-#include "base/stl_util.h"
 #include "components/performance_manager/public/execution_context/execution_context.h"
 
 // This voter allows expressing "priority boosts" which are used to resolve
diff --git a/components/performance_manager/freezing/freezing_vote_aggregator.cc b/components/performance_manager/freezing/freezing_vote_aggregator.cc
index c24a9aabf..8fe1381 100644
--- a/components/performance_manager/freezing/freezing_vote_aggregator.cc
+++ b/components/performance_manager/freezing/freezing_vote_aggregator.cc
@@ -6,7 +6,6 @@
 
 #include <algorithm>
 
-#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "components/performance_manager/public/freezing/freezing.h"
 #include "components/performance_manager/public/graph/node_data_describer_registry.h"
diff --git a/components/performance_manager/graph/graph_impl.cc b/components/performance_manager/graph/graph_impl.cc
index f9fed62..7f8b729 100644
--- a/components/performance_manager/graph/graph_impl.cc
+++ b/components/performance_manager/graph/graph_impl.cc
@@ -14,7 +14,6 @@
 #include "base/containers/flat_set.h"
 #include "base/macros.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "components/performance_manager/graph/frame_node_impl.h"
 #include "components/performance_manager/graph/node_base.h"
diff --git a/components/performance_manager/graph/graph_impl_operations_unittest.cc b/components/performance_manager/graph/graph_impl_operations_unittest.cc
index 3acf894..03098a7 100644
--- a/components/performance_manager/graph/graph_impl_operations_unittest.cc
+++ b/components/performance_manager/graph/graph_impl_operations_unittest.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 
 #include "base/bind.h"
-#include "base/stl_util.h"
 #include "components/performance_manager/test_support/graph_test_harness.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/performance_manager/graph/page_node_impl.cc b/components/performance_manager/graph/page_node_impl.cc
index 5c279f27..41c33d18 100644
--- a/components/performance_manager/graph/page_node_impl.cc
+++ b/components/performance_manager/graph/page_node_impl.cc
@@ -8,7 +8,6 @@
 
 #include "base/bind.h"
 #include "base/check_op.h"
-#include "base/stl_util.h"
 #include "base/time/default_tick_clock.h"
 #include "components/performance_manager/graph/frame_node_impl.h"
 #include "components/performance_manager/graph/graph_impl.h"
diff --git a/components/performance_manager/performance_manager_registry_impl.cc b/components/performance_manager/performance_manager_registry_impl.cc
index 9f797a1..a90c9e9 100644
--- a/components/performance_manager/performance_manager_registry_impl.cc
+++ b/components/performance_manager/performance_manager_registry_impl.cc
@@ -7,7 +7,6 @@
 #include <iterator>
 #include <utility>
 
-#include "base/stl_util.h"
 #include "components/performance_manager/embedder/binders.h"
 #include "components/performance_manager/performance_manager_tab_helper.h"
 #include "components/performance_manager/public/mojom/coordination_unit.mojom.h"
diff --git a/components/performance_manager/v8_memory/v8_detailed_memory_unittest.cc b/components/performance_manager/v8_memory/v8_detailed_memory_unittest.cc
index abe7b8fd..8c6ddbf 100644
--- a/components/performance_manager/v8_memory/v8_detailed_memory_unittest.cc
+++ b/components/performance_manager/v8_memory/v8_detailed_memory_unittest.cc
@@ -1346,13 +1346,7 @@
   memory_request.RemoveObserver(&observer);
 }
 
-// TODO(crbug.com/1203439) Sometimes timing out on Windows.
-#if defined(OS_WIN)
-#define MAYBE_SingleProcessRequest DISABLED_SingleProcessRequest
-#else
-#define MAYBE_SingleProcessRequest SingleProcessRequest
-#endif
-TEST_F(V8DetailedMemoryDecoratorTest, MAYBE_SingleProcessRequest) {
+TEST_F(V8DetailedMemoryDecoratorTest, SingleProcessRequest) {
   // Create 2 renderer processes. Create one request that measures both of
   // them, and one request that measures only one.
   constexpr RenderProcessHostId kProcessId1 = RenderProcessHostId(0xFAB);
@@ -1696,7 +1690,13 @@
   run_loop2.Run();
 }
 
-TEST_F(V8DetailedMemoryRequestAnySeqTest, SingleProcessRequest) {
+// TODO(crbug.com/1203439) Sometimes timing out on Windows.
+#if defined(OS_WIN)
+#define MAYBE_SingleProcessRequest DISABLED_SingleProcessRequest
+#else
+#define MAYBE_SingleProcessRequest SingleProcessRequest
+#endif
+TEST_F(V8DetailedMemoryRequestAnySeqTest, MAYBE_SingleProcessRequest) {
   CreateCrossProcessChildFrame();
 
   V8DetailedMemoryProcessData expected_process_data1;
diff --git a/components/performance_manager/v8_memory/web_memory_aggregator.cc b/components/performance_manager/v8_memory/web_memory_aggregator.cc
index 522c9fa2..57ec450da 100644
--- a/components/performance_manager/v8_memory/web_memory_aggregator.cc
+++ b/components/performance_manager/v8_memory/web_memory_aggregator.cc
@@ -10,7 +10,6 @@
 #include "base/bind.h"
 #include "base/check.h"
 #include "base/containers/stack.h"
-#include "base/stl_util.h"
 #include "components/performance_manager/public/graph/frame_node.h"
 #include "components/performance_manager/public/graph/page_node.h"
 #include "components/performance_manager/public/graph/worker_node.h"
diff --git a/components/plugins/renderer/webview_plugin.cc b/components/plugins/renderer/webview_plugin.cc
index 330c99f8..8ba1accd 100644
--- a/components/plugins/renderer/webview_plugin.cc
+++ b/components/plugins/renderer/webview_plugin.cc
@@ -310,6 +310,18 @@
 void WebViewPlugin::WebViewHelper::UpdateTooltipUnderCursor(
     const std::u16string& tooltip_text,
     base::i18n::TextDirection hint) {
+  UpdateTooltip(tooltip_text);
+}
+
+void WebViewPlugin::WebViewHelper::UpdateTooltipFromKeyboard(
+    const std::u16string& tooltip_text,
+    base::i18n::TextDirection hint,
+    const gfx::Rect& bounds) {
+  UpdateTooltip(tooltip_text);
+}
+
+void WebViewPlugin::WebViewHelper::UpdateTooltip(
+    const std::u16string& tooltip_text) {
   if (plugin_->container_) {
     plugin_->container_->GetElement().SetAttribute(
         "title", WebString::FromUTF16(tooltip_text));
diff --git a/components/plugins/renderer/webview_plugin.h b/components/plugins/renderer/webview_plugin.h
index 6607978..1c93d362 100644
--- a/components/plugins/renderer/webview_plugin.h
+++ b/components/plugins/renderer/webview_plugin.h
@@ -186,6 +186,9 @@
     void SetCursor(const ui::Cursor& cursor) override;
     void UpdateTooltipUnderCursor(const std::u16string& tooltip_text,
                                   base::i18n::TextDirection hint) override;
+    void UpdateTooltipFromKeyboard(const std::u16string& tooltip_text,
+                                   base::i18n::TextDirection hint,
+                                   const gfx::Rect& bounds) override;
     void TextInputStateChanged(ui::mojom::TextInputStatePtr state) override {}
     void SelectionBoundsChanged(const gfx::Rect& anchor_rect,
                                 base::i18n::TextDirection anchor_dir,
@@ -203,6 +206,10 @@
         mojo::PendingRemote<cc::mojom::RenderFrameMetadataObserver>
             render_frame_metadata_observer) override {}
 
+    // This function sets the "title" attribute to the text value passed by
+    // parameter on the container's element, if possible.
+    void UpdateTooltip(const std::u16string& tooltip_text);
+
    private:
     WebViewPlugin* plugin_;
     blink::WebNavigationControl* frame_ = nullptr;
diff --git a/components/policy/core/browser/url_blocklist_manager.cc b/components/policy/core/browser/url_blocklist_manager.cc
index 09e3f8a..a4a9c33 100644
--- a/components/policy/core/browser/url_blocklist_manager.cc
+++ b/components/policy/core/browser/url_blocklist_manager.cc
@@ -18,7 +18,6 @@
 #include "base/location.h"
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/task/post_task.h"
diff --git a/components/policy/core/common/cloud/external_policy_data_fetcher.cc b/components/policy/core/common/cloud/external_policy_data_fetcher.cc
index 69fbb61d9..de3283f 100644
--- a/components/policy/core/common/cloud/external_policy_data_fetcher.cc
+++ b/components/policy/core/common/cloud/external_policy_data_fetcher.cc
@@ -12,7 +12,6 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/sequenced_task_runner.h"
-#include "base/stl_util.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
diff --git a/components/policy/core/common/policy_map.cc b/components/policy/core/common/policy_map.cc
index fe7815a..f32d4f51 100644
--- a/components/policy/core/common/policy_map.cc
+++ b/components/policy/core/common/policy_map.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/callback.h"
-#include "base/stl_util.h"
 #include "base/strings/strcat.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index b1d649a0..07fc774 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -25983,7 +25983,38 @@
 
       If this policy is set to <ph name="POLICY_VALUE_NONE">'none'</ph> or not set, managed accounts have no restrictions. This may result in a managed account being a secondary account, which disables its ability to receive policies set on the account by the admin.
     ''',
-    }
+    },
+    {
+      'name': 'LockIconInAddressBarEnabled',
+      'owners': ['meacer@chromium.org', 'trusty-transport@chromium.org'],
+      'type': 'main',
+      'schema': { 'type': 'boolean' },
+      'items': [
+        {
+          'value': True,
+          'caption': 'Use lock icon for secure connections',
+        },
+        {
+          'value': False,
+          'caption': 'Use default icons for secure connections',
+        },
+      ],
+      'future_on': ['chrome.*', 'chrome_os', 'android'],
+      # TODO(crbug.com/1210228): Support dynamic_refresh: True
+      'features': {
+        'dynamic_refresh': False,
+        'per_profile': True,
+      },
+      'default': False,
+      'example_value': True,
+      'id': 861,
+      'caption': '''Enable lock icon in the omnibox for secure connections''',
+      'tags': [],
+      'desc': '''This policy controls the treatment for lock icon in the omnibox.
+       From Chrome M93, there is a new omnibox icon for secure connections.
+       If the policy is Enabled, Chrome will use the existing lock icon for secure connections.
+       If the policy is Disabled or not set, Chrome will use the default icon for secure connections.''',
+    },
   ],
   'messages': {
     # Messages that are not associated to any policies.
@@ -26915,6 +26946,6 @@
   'placeholders': [],
   'deleted_policy_ids': [114, 115, 204, 205, 206, 412, 476, 544, 546, 562, 569, 578, 583, 585, 586, 587, 588, 589, 590, 591, 600, 668, 669],
   'deleted_atomic_policy_group_ids': [19],
-  'highest_id_currently_used': 860,
+  'highest_id_currently_used': 861,
   'highest_atomic_group_id_currently_used': 40
 }
diff --git a/components/prefs/pref_service.cc b/components/prefs/pref_service.cc
index 3f1474a..77a8b38 100644
--- a/components/prefs/pref_service.cc
+++ b/components/prefs/pref_service.cc
@@ -18,7 +18,6 @@
 #include "base/metrics/histogram.h"
 #include "base/notreached.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/components/prefs/segregated_pref_store.cc b/components/prefs/segregated_pref_store.cc
index 65f2c80..aabbd9a 100644
--- a/components/prefs/segregated_pref_store.cc
+++ b/components/prefs/segregated_pref_store.cc
@@ -12,42 +12,40 @@
 #include "base/notreached.h"
 #include "base/values.h"
 
-SegregatedPrefStore::AggregatingObserver::AggregatingObserver(
+SegregatedPrefStore::UnderlyingPrefStoreObserver::UnderlyingPrefStoreObserver(
     SegregatedPrefStore* outer)
-    : outer_(outer),
-      failed_sub_initializations_(0),
-      successful_sub_initializations_(0) {}
+    : outer_(outer) {
+  DCHECK(outer_);
+}
 
-void SegregatedPrefStore::AggregatingObserver::OnPrefValueChanged(
+void SegregatedPrefStore::UnderlyingPrefStoreObserver::OnPrefValueChanged(
     const std::string& key) {
-  // There is no need to tell clients about changes if they have not yet been
-  // told about initialization.
-  if (failed_sub_initializations_ + successful_sub_initializations_ < 2)
+  // Notify Observers only after all underlying PrefStores of the outer
+  // SegregatedPrefStore are initialized.
+  if (!outer_->IsInitializationComplete())
     return;
 
   for (auto& observer : outer_->observers_)
     observer.OnPrefValueChanged(key);
 }
 
-void SegregatedPrefStore::AggregatingObserver::OnInitializationCompleted(
-    bool succeeded) {
-  if (succeeded)
-    ++successful_sub_initializations_;
-  else
-    ++failed_sub_initializations_;
+void SegregatedPrefStore::UnderlyingPrefStoreObserver::
+    OnInitializationCompleted(bool succeeded) {
+  initialization_succeeded_ = succeeded;
 
-  DCHECK_LE(failed_sub_initializations_ + successful_sub_initializations_, 2);
+  // Notify Observers only after all underlying PrefStores of the outer
+  // SegregatedPrefStore are initialized.
+  if (!outer_->IsInitializationComplete())
+    return;
 
-  if (failed_sub_initializations_ + successful_sub_initializations_ == 2) {
-    if (successful_sub_initializations_ == 2 && outer_->read_error_delegate_) {
-      PersistentPrefStore::PrefReadError read_error = outer_->GetReadError();
-      if (read_error != PersistentPrefStore::PREF_READ_ERROR_NONE)
-        outer_->read_error_delegate_->OnError(read_error);
-    }
-
-    for (auto& observer : outer_->observers_)
-      observer.OnInitializationCompleted(successful_sub_initializations_ == 2);
+  if (outer_->read_error_delegate_) {
+    PersistentPrefStore::PrefReadError read_error = outer_->GetReadError();
+    if (read_error != PersistentPrefStore::PREF_READ_ERROR_NONE)
+      outer_->read_error_delegate_->OnError(read_error);
   }
+
+  for (auto& observer : outer_->observers_)
+    observer.OnInitializationCompleted(outer_->IsInitializationSuccessful());
 }
 
 SegregatedPrefStore::SegregatedPrefStore(
@@ -57,9 +55,10 @@
     : default_pref_store_(std::move(default_pref_store)),
       selected_pref_store_(std::move(selected_pref_store)),
       selected_preference_names_(std::move(selected_pref_names)),
-      aggregating_observer_(this) {
-  default_pref_store_->AddObserver(&aggregating_observer_);
-  selected_pref_store_->AddObserver(&aggregating_observer_);
+      default_observer_(this),
+      selected_observer_(this) {
+  default_pref_store_->AddObserver(&default_observer_);
+  selected_pref_store_->AddObserver(&selected_observer_);
 }
 
 void SegregatedPrefStore::AddObserver(Observer* observer) {
@@ -79,6 +78,11 @@
          selected_pref_store_->IsInitializationComplete();
 }
 
+bool SegregatedPrefStore::IsInitializationSuccessful() const {
+  return default_observer_.initialization_succeeded() &&
+         selected_observer_.initialization_succeeded();
+}
+
 bool SegregatedPrefStore::GetValue(const std::string& key,
                                    const base::Value** result) const {
   return StoreForKey(key)->GetValue(key, result);
@@ -206,8 +210,8 @@
 }
 
 SegregatedPrefStore::~SegregatedPrefStore() {
-  default_pref_store_->RemoveObserver(&aggregating_observer_);
-  selected_pref_store_->RemoveObserver(&aggregating_observer_);
+  default_pref_store_->RemoveObserver(&default_observer_);
+  selected_pref_store_->RemoveObserver(&selected_observer_);
 }
 
 PersistentPrefStore* SegregatedPrefStore::StoreForKey(const std::string& key) {
diff --git a/components/prefs/segregated_pref_store.h b/components/prefs/segregated_pref_store.h
index 9d9b681..6e1fdbd 100644
--- a/components/prefs/segregated_pref_store.h
+++ b/components/prefs/segregated_pref_store.h
@@ -81,26 +81,32 @@
   ~SegregatedPrefStore() override;
 
  private:
-  // Aggregates events from the underlying stores and synthesizes external
-  // events via |on_initialization|, |read_error_delegate_|, and |observers_|.
-  class AggregatingObserver : public PrefStore::Observer {
+  // Caches event state from the underlying stores and exposes the state to the
+  // provided "outer" SegregatedPrefStore to synthesize external events via
+  // |read_error_delegate_| and |observers_|.
+  class UnderlyingPrefStoreObserver : public PrefStore::Observer {
    public:
-    explicit AggregatingObserver(SegregatedPrefStore* outer);
+    explicit UnderlyingPrefStoreObserver(SegregatedPrefStore* outer);
 
     // PrefStore::Observer implementation
     void OnPrefValueChanged(const std::string& key) override;
     void OnInitializationCompleted(bool succeeded) override;
 
-   private:
-    SegregatedPrefStore* outer_;
-    int failed_sub_initializations_;
-    int successful_sub_initializations_;
+    bool initialization_succeeded() const { return initialization_succeeded_; }
 
-    DISALLOW_COPY_AND_ASSIGN(AggregatingObserver);
+   private:
+    SegregatedPrefStore* const outer_;
+    bool initialization_succeeded_ = false;
+
+    DISALLOW_COPY_AND_ASSIGN(UnderlyingPrefStoreObserver);
   };
 
-  // Returns |selected_pref_store| if |key| is selected and |default_pref_store|
-  // otherwise.
+  // Returns true only if all underlying PrefStores have initialized
+  // successfully, otherwise false.
+  bool IsInitializationSuccessful() const;
+
+  // Returns |selected_pref_store| if |key| is selected and
+  // |default_pref_store| otherwise.
   PersistentPrefStore* StoreForKey(const std::string& key);
   const PersistentPrefStore* StoreForKey(const std::string& key) const;
 
@@ -110,7 +116,8 @@
 
   std::unique_ptr<PersistentPrefStore::ReadErrorDelegate> read_error_delegate_;
   base::ObserverList<PrefStore::Observer, true>::Unchecked observers_;
-  AggregatingObserver aggregating_observer_;
+  UnderlyingPrefStoreObserver default_observer_;
+  UnderlyingPrefStoreObserver selected_observer_;
 
   DISALLOW_COPY_AND_ASSIGN(SegregatedPrefStore);
 };
diff --git a/components/prefs/segregated_pref_store_unittest.cc b/components/prefs/segregated_pref_store_unittest.cc
index 4e90ea8..bb58d5d 100644
--- a/components/prefs/segregated_pref_store_unittest.cc
+++ b/components/prefs/segregated_pref_store_unittest.cc
@@ -79,13 +79,10 @@
     selected_store_ = new TestingPrefStore;
     default_store_ = new TestingPrefStore;
 
-    std::set<std::string> selected_pref_names;
-    selected_pref_names.insert(kSelectedPref);
-    selected_pref_names.insert(kSharedPref);
-
+    selected_pref_names_.insert(kSelectedPref);
+    selected_pref_names_.insert(kSharedPref);
     segregated_store_ = new SegregatedPrefStore(default_store_, selected_store_,
-                                                selected_pref_names);
-
+                                                selected_pref_names_);
     segregated_store_->AddObserver(&observer_);
   }
 
@@ -106,6 +103,7 @@
   scoped_refptr<TestingPrefStore> selected_store_;
   scoped_refptr<SegregatedPrefStore> segregated_store_;
 
+  std::set<std::string> selected_pref_names_;
   MockReadErrorDelegate::Data read_error_delegate_data_;
 
  private:
@@ -230,6 +228,33 @@
   observer_.VerifyAndResetChangedKey(kUnselectedPref);
 }
 
+TEST_F(SegregatedPrefStoreTest,
+       ObserverAfterConstructionAfterSubInitialization) {
+  // Ensure that underlying PrefStores are initialized first.
+  default_store_->ReadPrefs();
+  selected_store_->ReadPrefs();
+  EXPECT_TRUE(default_store_->IsInitializationComplete());
+  EXPECT_TRUE(selected_store_->IsInitializationComplete());
+
+  // Create a new SegregatedPrefStore based on the initialized PrefStores.
+  segregated_store_->RemoveObserver(&observer_);
+  segregated_store_ = base::MakeRefCounted<SegregatedPrefStore>(
+      default_store_, selected_store_, selected_pref_names_);
+  segregated_store_->AddObserver(&observer_);
+  EXPECT_TRUE(segregated_store_->IsInitializationComplete());
+
+  // The Observer should receive notifications from the SegregatedPrefStore.
+  EXPECT_TRUE(observer_.changed_keys.empty());
+  segregated_store_->SetValue(kSelectedPref,
+                              std::make_unique<base::Value>(kValue1),
+                              WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+  observer_.VerifyAndResetChangedKey(kSelectedPref);
+  segregated_store_->SetValue(kUnselectedPref,
+                              std::make_unique<base::Value>(kValue2),
+                              WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+  observer_.VerifyAndResetChangedKey(kUnselectedPref);
+}
+
 TEST_F(SegregatedPrefStoreTest, SelectedPrefReadNoFileError) {
   // PREF_READ_ERROR_NO_FILE for the selected prefs file is silently converted
   // to PREF_READ_ERROR_NONE.
diff --git a/components/prefs/value_map_pref_store.cc b/components/prefs/value_map_pref_store.cc
index b089f61..5f44733 100644
--- a/components/prefs/value_map_pref_store.cc
+++ b/components/prefs/value_map_pref_store.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 #include <utility>
 
-#include "base/stl_util.h"
 #include "base/values.h"
 
 ValueMapPrefStore::ValueMapPrefStore() {}
diff --git a/components/safe_browsing/core/db/v4_get_hash_protocol_manager_unittest.cc b/components/safe_browsing/core/db/v4_get_hash_protocol_manager_unittest.cc
index c6aa0c7..2a05e2a 100644
--- a/components/safe_browsing/core/db/v4_get_hash_protocol_manager_unittest.cc
+++ b/components/safe_browsing/core/db/v4_get_hash_protocol_manager_unittest.cc
@@ -10,7 +10,6 @@
 #include "base/base64.h"
 #include "base/bind.h"
 #include "base/run_loop.h"
-#include "base/stl_util.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/simple_test_clock.h"
 #include "base/time/time.h"
diff --git a/components/safe_browsing/core/password_protection/password_protection_service_base.cc b/components/safe_browsing/core/password_protection/password_protection_service_base.cc
index 35cd3ea..891639b 100644
--- a/components/safe_browsing/core/password_protection/password_protection_service_base.cc
+++ b/components/safe_browsing/core/password_protection/password_protection_service_base.cc
@@ -12,7 +12,6 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
diff --git a/components/safe_browsing/core/triggers/trigger_manager_unittest.cc b/components/safe_browsing/core/triggers/trigger_manager_unittest.cc
index d4770d3..fd14cca 100644
--- a/components/safe_browsing/core/triggers/trigger_manager_unittest.cc
+++ b/components/safe_browsing/core/triggers/trigger_manager_unittest.cc
@@ -5,7 +5,6 @@
 #include "components/safe_browsing/core/triggers/trigger_manager.h"
 
 #include "base/run_loop.h"
-#include "base/stl_util.h"
 #include "base/test/scoped_feature_list.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
diff --git a/components/safe_search_api/safe_search/safe_search_url_checker_client.cc b/components/safe_search_api/safe_search/safe_search_url_checker_client.cc
index 36bd061..41fcbbca 100644
--- a/components/safe_search_api/safe_search/safe_search_url_checker_client.cc
+++ b/components/safe_search_api/safe_search/safe_search_url_checker_client.cc
@@ -9,7 +9,6 @@
 #include "base/callback.h"
 #include "base/json/json_reader.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
diff --git a/components/safe_search_api/url_checker.cc b/components/safe_search_api/url_checker.cc
index 28af58c2..3d3ab51 100644
--- a/components/safe_search_api/url_checker.cc
+++ b/components/safe_search_api/url_checker.cc
@@ -14,7 +14,6 @@
 #include "base/json/json_reader.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/time/time.h"
diff --git a/components/security_interstitials/content/certificate_error_report.cc b/components/security_interstitials/content/certificate_error_report.cc
index 5b682f2..6803608 100644
--- a/components/security_interstitials/content/certificate_error_report.cc
+++ b/components/security_interstitials/content/certificate_error_report.cc
@@ -6,7 +6,6 @@
 
 #include <vector>
 
-#include "base/stl_util.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
 #include "base/time/time.h"
diff --git a/components/segmentation_platform/internal/scheduler/model_execution_scheduler.h b/components/segmentation_platform/internal/scheduler/model_execution_scheduler.h
index 6eee659..08b1a4b 100644
--- a/components/segmentation_platform/internal/scheduler/model_execution_scheduler.h
+++ b/components/segmentation_platform/internal/scheduler/model_execution_scheduler.h
@@ -5,9 +5,9 @@
 #ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SCHEDULER_MODEL_EXECUTION_SCHEDULER_H_
 #define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SCHEDULER_MODEL_EXECUTION_SCHEDULER_H_
 
-#include "base/optional.h"
 #include "components/optimization_guide/proto/models.pb.h"
 #include "components/segmentation_platform/internal/execution/model_execution_status.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 using optimization_guide::proto::OptimizationTarget;
 
diff --git a/components/segmentation_platform/internal/selection/segment_selector.h b/components/segmentation_platform/internal/selection/segment_selector.h
index f05fa92..918e5f5 100644
--- a/components/segmentation_platform/internal/selection/segment_selector.h
+++ b/components/segmentation_platform/internal/selection/segment_selector.h
@@ -6,10 +6,10 @@
 #define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SELECTION_SEGMENT_SELECTOR_H_
 
 #include "base/callback.h"
-#include "base/optional.h"
 #include "components/optimization_guide/proto/models.pb.h"
 #include "components/segmentation_platform/internal/execution/model_execution_status.h"
 #include "components/segmentation_platform/internal/scheduler/model_execution_scheduler.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 using optimization_guide::proto::OptimizationTarget;
 
@@ -25,9 +25,9 @@
   virtual ~SegmentSelector() = default;
 
   using SelectedSegmentCallback =
-      base::OnceCallback<void(base::Optional<OptimizationTarget>)>;
+      base::OnceCallback<void(absl::optional<OptimizationTarget>)>;
   using SingleSegmentResultCallback =
-      base::OnceCallback<void(base::Optional<float>)>;
+      base::OnceCallback<void(absl::optional<float>)>;
 
   // Called to initialize the selector. Reads results from last session into
   // memory. Must be invoked before calling any other method.
diff --git a/components/segmentation_platform/internal/selection/segment_selector_impl.cc b/components/segmentation_platform/internal/selection/segment_selector_impl.cc
index 536989e..dc6cdb3 100644
--- a/components/segmentation_platform/internal/selection/segment_selector_impl.cc
+++ b/components/segmentation_platform/internal/selection/segment_selector_impl.cc
@@ -23,7 +23,7 @@
 
 void SegmentSelectorImpl::Initialize(base::OnceClosure callback) {
   // Read selected segment from prefs.
-  base::Optional<SelectedSegment> selected_segment =
+  absl::optional<SelectedSegment> selected_segment =
       result_prefs_->ReadSegmentationResultFromPref();
   if (selected_segment.has_value())
     selected_segment_last_session_ = selected_segment->segment_id;
@@ -49,7 +49,7 @@
     SingleSegmentResultCallback callback) {
   DCHECK(initialized_);
 
-  base::Optional<float> score;
+  absl::optional<float> score;
   auto iter = segment_score_last_session_.find(segment_id);
   if (iter != segment_score_last_session_.end())
     score = iter->second;
@@ -106,7 +106,7 @@
 
 void SegmentSelectorImpl::UpdateSelectedSegment(
     OptimizationTarget new_selection) {
-  base::Optional<SelectedSegment> previous_selection =
+  absl::optional<SelectedSegment> previous_selection =
       result_prefs_->ReadSegmentationResultFromPref();
 
   bool skip_updating_prefs = false;
@@ -122,9 +122,9 @@
     return;
 
   // Write result to prefs.
-  base::Optional<SelectedSegment> updated_selection;
+  absl::optional<SelectedSegment> updated_selection;
   if (new_selection != OptimizationTarget::OPTIMIZATION_TARGET_UNKNOWN) {
-    updated_selection = base::make_optional<SelectedSegment>(new_selection);
+    updated_selection = absl::make_optional<SelectedSegment>(new_selection);
     updated_selection->selection_time = base::Time::Now();
   }
   result_prefs_->SaveSegmentationResultToPref(updated_selection);
diff --git a/components/segmentation_platform/internal/selection/segment_selector_impl.h b/components/segmentation_platform/internal/selection/segment_selector_impl.h
index 3e28146a7..a02d7b6 100644
--- a/components/segmentation_platform/internal/selection/segment_selector_impl.h
+++ b/components/segmentation_platform/internal/selection/segment_selector_impl.h
@@ -85,7 +85,7 @@
 
   // These values are read from prefs or db on init and used for serving the
   // clients in the current session.
-  base::Optional<OptimizationTarget> selected_segment_last_session_;
+  absl::optional<OptimizationTarget> selected_segment_last_session_;
   std::map<OptimizationTarget, float> segment_score_last_session_;
 
   // Whether the initialization is complete through an Initialize call.
diff --git a/components/segmentation_platform/internal/selection/segment_selector_unittest.cc b/components/segmentation_platform/internal/selection/segment_selector_unittest.cc
index aca25b98..103cf7a 100644
--- a/components/segmentation_platform/internal/selection/segment_selector_unittest.cc
+++ b/components/segmentation_platform/internal/selection/segment_selector_unittest.cc
@@ -24,8 +24,8 @@
   MockSegmentationResultPrefs() = default;
   MOCK_METHOD(void,
               SaveSegmentationResultToPref,
-              (const base::Optional<SelectedSegment>&));
-  MOCK_METHOD(base::Optional<SelectedSegment>,
+              (const absl::optional<SelectedSegment>&));
+  MOCK_METHOD(absl::optional<SelectedSegment>,
               ReadSegmentationResultFromPref,
               ());
 };
@@ -65,7 +65,7 @@
                                                      score, metadata);
   }
 
-  void GetSelectedSegment(base::Optional<OptimizationTarget> expected) {
+  void GetSelectedSegment(absl::optional<OptimizationTarget> expected) {
     base::RunLoop loop;
     segment_selector_->GetSelectedSegment(base::BindOnce(
         &SegmentSelectorTest::OnGetSelectedSegment, base::Unretained(this),
@@ -74,8 +74,8 @@
   }
 
   void OnGetSelectedSegment(base::RepeatingClosure closure,
-                            base::Optional<OptimizationTarget> expected,
-                            base::Optional<OptimizationTarget> actual) {
+                            absl::optional<OptimizationTarget> expected,
+                            absl::optional<OptimizationTarget> actual) {
     ASSERT_EQ(expected.has_value(), actual.has_value());
     ASSERT_EQ(expected.value(), actual.value());
     std::move(closure).Run();
@@ -125,7 +125,7 @@
   segment_database_->AddPredictionResult(segment_id, 0.6, result_timestamp);
   segment_database_->AddPredictionResult(segment_id2, 0.5, result_timestamp);
 
-  base::Optional<SelectedSegment> selected_segment;
+  absl::optional<SelectedSegment> selected_segment;
   EXPECT_CALL(*prefs_, SaveSegmentationResultToPref(_))
       .Times(1)
       .WillOnce(SaveArg<0>(&selected_segment));
@@ -144,7 +144,7 @@
   base::Time result_timestamp = base::Time::Now();
   segment_database_->AddPredictionResult(segment_id1, 0.6, result_timestamp);
 
-  base::Optional<SelectedSegment> selected_segment;
+  absl::optional<SelectedSegment> selected_segment;
   EXPECT_CALL(*prefs_, SaveSegmentationResultToPref(_))
       .Times(1)
       .WillOnce(SaveArg<0>(&selected_segment));
@@ -193,7 +193,7 @@
   base::Time result_timestamp = base::Time::Now();
   segment_database_->AddPredictionResult(segment_id1, 0.6, result_timestamp);
 
-  base::Optional<SelectedSegment> selected_segment;
+  absl::optional<SelectedSegment> selected_segment;
   EXPECT_CALL(*prefs_, SaveSegmentationResultToPref(_))
       .Times(1)
       .WillOnce(SaveArg<0>(&selected_segment));
diff --git a/components/segmentation_platform/internal/selection/segmentation_result_prefs.h b/components/segmentation_platform/internal/selection/segmentation_result_prefs.h
index 8926c84..93487a3 100644
--- a/components/segmentation_platform/internal/selection/segmentation_result_prefs.h
+++ b/components/segmentation_platform/internal/selection/segmentation_result_prefs.h
@@ -5,9 +5,9 @@
 #ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SELECTION_SEGMENTATION_RESULT_PREFS_H_
 #define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SELECTION_SEGMENTATION_RESULT_PREFS_H_
 
-#include "base/optional.h"
 #include "base/time/time.h"
 #include "components/optimization_guide/proto/models.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 using optimization_guide::proto::OptimizationTarget;
 
@@ -35,10 +35,10 @@
   // Writes the selected segment to prefs. Deletes the previous results if
   // |selected_segment| is empty.
   virtual void SaveSegmentationResultToPref(
-      const base::Optional<SelectedSegment>& selected_segment) = 0;
+      const absl::optional<SelectedSegment>& selected_segment) = 0;
 
   // Reads the selected segment from pref, if any.
-  virtual base::Optional<SelectedSegment> ReadSegmentationResultFromPref() = 0;
+  virtual absl::optional<SelectedSegment> ReadSegmentationResultFromPref() = 0;
 };
 
 }  // namespace segmentation_platform
diff --git a/components/services/app_service/public/cpp/protocol_handler_info.h b/components/services/app_service/public/cpp/protocol_handler_info.h
index 99cf266e7..5cefeb6 100644
--- a/components/services/app_service/public/cpp/protocol_handler_info.h
+++ b/components/services/app_service/public/cpp/protocol_handler_info.h
@@ -6,6 +6,7 @@
 #define COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_PROTOCOL_HANDLER_INFO_H_
 
 #include <string>
+#include <vector>
 
 #include "url/gurl.h"
 
@@ -20,6 +21,7 @@
   std::string protocol;
   GURL url;
 };
+using ProtocolHandlers = std::vector<ProtocolHandlerInfo>;
 
 bool operator==(const ProtocolHandlerInfo& handler1,
                 const ProtocolHandlerInfo& handler2);
diff --git a/components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.cc b/components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.cc
index edbc92b..6db2153 100644
--- a/components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.cc
+++ b/components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.cc
@@ -18,7 +18,6 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/stringprintf.h"
diff --git a/components/sessions/core/tab_restore_service_helper.cc b/components/sessions/core/tab_restore_service_helper.cc
index afd9e20..10f1d8d 100644
--- a/components/sessions/core/tab_restore_service_helper.cc
+++ b/components/sessions/core/tab_restore_service_helper.cc
@@ -18,7 +18,6 @@
 #include "base/metrics/histogram.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
diff --git a/components/sessions/core/tab_restore_service_impl.cc b/components/sessions/core/tab_restore_service_impl.cc
index 6d5f241..ac99ffa 100644
--- a/components/sessions/core/tab_restore_service_impl.cc
+++ b/components/sessions/core/tab_restore_service_impl.cc
@@ -20,7 +20,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "base/time/time.h"
 #include "components/history/core/common/pref_names.h"
 #include "components/prefs/pref_service.h"
diff --git a/components/signin/public/identity_manager/identity_manager_unittest.cc b/components/signin/public/identity_manager/identity_manager_unittest.cc
index 9206820..0674271 100644
--- a/components/signin/public/identity_manager/identity_manager_unittest.cc
+++ b/components/signin/public/identity_manager/identity_manager_unittest.cc
@@ -15,7 +15,6 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/run_loop.h"
 #include "base/scoped_observation.h"
-#include "base/stl_util.h"
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
diff --git a/components/signin/public/webdata/token_web_data.cc b/components/signin/public/webdata/token_web_data.cc
index a213d159..0f239c1 100644
--- a/components/signin/public/webdata/token_web_data.cc
+++ b/components/signin/public/webdata/token_web_data.cc
@@ -9,7 +9,6 @@
 #include "base/bind.h"
 #include "base/memory/ref_counted_delete_on_sequence.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "components/signin/public/webdata/token_service_table.h"
 #include "components/webdata/common/web_database_service.h"
 
diff --git a/components/spellcheck/browser/spelling_service_client.cc b/components/spellcheck/browser/spelling_service_client.cc
index 9c47f2251..19dbe8a 100644
--- a/components/spellcheck/browser/spelling_service_client.cc
+++ b/components/spellcheck/browser/spelling_service_client.cc
@@ -15,7 +15,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/components/spellcheck/renderer/spellcheck.cc b/components/spellcheck/renderer/spellcheck.cc
index 8a268689..16546275 100644
--- a/components/spellcheck/renderer/spellcheck.cc
+++ b/components/spellcheck/renderer/spellcheck.cc
@@ -17,7 +17,6 @@
 #include "base/macros.h"
 #include "base/notreached.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
diff --git a/components/storage_monitor/storage_info_utils.cc b/components/storage_monitor/storage_info_utils.cc
index 49fefa1..d616e494 100644
--- a/components/storage_monitor/storage_info_utils.cc
+++ b/components/storage_monitor/storage_info_utils.cc
@@ -7,7 +7,6 @@
 #include <string>
 
 #include "base/files/file_path.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h
index af0819d..7641002 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h
+++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h
@@ -13,7 +13,6 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
-#include "base/stl_util.h"
 #include "base/supports_user_data.h"
 #include "components/safe_browsing/core/db/database_manager.h"
 #include "components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.h"
diff --git a/components/subresource_redirect/common/subresource_redirect_result.h b/components/subresource_redirect/common/subresource_redirect_result.h
index 0454aeb3c..dae817b 100644
--- a/components/subresource_redirect/common/subresource_redirect_result.h
+++ b/components/subresource_redirect/common/subresource_redirect_result.h
@@ -65,8 +65,11 @@
   // got disabled.
   kIneligibleFirstKDisableSubresourceRedirect = 12,
 
-  kMaxValue =
-      SubresourceRedirectResult::kIneligibleFirstKDisableSubresourceRedirect
+  // Because the subresource redirection was disabled, where only metrics are
+  // recorded and the actual subresource redirection does not happen.
+  kIneligibleCompressionDisabled = 13,
+
+  kMaxValue = SubresourceRedirectResult::kIneligibleCompressionDisabled
 };
 
 }  // namespace subresource_redirect
diff --git a/components/sync/engine/loopback_server/loopback_server.cc b/components/sync/engine/loopback_server/loopback_server.cc
index fc3dabb5..9a4bbd2c 100644
--- a/components/sync/engine/loopback_server/loopback_server.cc
+++ b/components/sync/engine/loopback_server/loopback_server.cc
@@ -17,7 +17,6 @@
 #include "base/rand_util.h"
 #include "base/sequence_checker.h"
 #include "base/sequenced_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
diff --git a/components/sync/engine/syncer_unittest.cc b/components/sync/engine/syncer_unittest.cc
index 5a83934..ae73b03 100644
--- a/components/sync/engine/syncer_unittest.cc
+++ b/components/sync/engine/syncer_unittest.cc
@@ -20,7 +20,6 @@
 #include "base/callback_helpers.h"
 #include "base/compiler_specific.h"
 #include "base/location.h"
-#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
diff --git a/components/sync/test/fake_server/fake_server.cc b/components/sync/test/fake_server/fake_server.cc
index 6f9e8a5..714ede8 100644
--- a/components/sync/test/fake_server/fake_server.cc
+++ b/components/sync/test/fake_server/fake_server.cc
@@ -14,7 +14,6 @@
 #include "base/hash/hash.h"
 #include "base/json/json_writer.h"
 #include "base/logging.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
diff --git a/components/sync_user_events/user_event_service_impl.cc b/components/sync_user_events/user_event_service_impl.cc
index 37414f8..37a0cd19 100644
--- a/components/sync_user_events/user_event_service_impl.cc
+++ b/components/sync_user_events/user_event_service_impl.cc
@@ -8,7 +8,6 @@
 
 #include "base/metrics/histogram_functions.h"
 #include "base/rand_util.h"
-#include "base/stl_util.h"
 #include "base/time/time.h"
 #include "components/sync_user_events/user_event_sync_bridge.h"
 
diff --git a/components/tracing/common/graphics_memory_dump_provider_android.cc b/components/tracing/common/graphics_memory_dump_provider_android.cc
index 9927d06c..bf0c58f4 100644
--- a/components/tracing/common/graphics_memory_dump_provider_android.cc
+++ b/components/tracing/common/graphics_memory_dump_provider_android.cc
@@ -15,7 +15,6 @@
 #include "base/files/scoped_file.h"
 #include "base/logging.h"
 #include "base/posix/eintr_wrapper.h"
-#include "base/stl_util.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
diff --git a/components/translate/core/browser/translate_language_list.cc b/components/translate/core/browser/translate_language_list.cc
index 2b356fd7..a97a581 100644
--- a/components/translate/core/browser/translate_language_list.cc
+++ b/components/translate/core/browser/translate_language_list.cc
@@ -14,7 +14,6 @@
 #include "base/json/json_reader.h"
 #include "base/lazy_instance.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc
index 2403966..44ea9f56 100644
--- a/components/translate/core/browser/translate_manager.cc
+++ b/components/translate/core/browser/translate_manager.cc
@@ -15,7 +15,6 @@
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
diff --git a/components/update_client/update_engine.cc b/components/update_client/update_engine.cc
index b0a84ca..c4171bdd 100644
--- a/components/update_client/update_engine.cc
+++ b/components/update_client/update_engine.cc
@@ -13,7 +13,6 @@
 #include "base/check_op.h"
 #include "base/guid.h"
 #include "base/location.h"
-#include "base/stl_util.h"
 #include "base/strings/strcat.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/prefs/pref_service.h"
diff --git a/components/url_formatter/url_formatter.cc b/components/url_formatter/url_formatter.cc
index f8f57f2..7c28e01 100644
--- a/components/url_formatter/url_formatter.cc
+++ b/components/url_formatter/url_formatter.cc
@@ -10,7 +10,6 @@
 
 #include "base/lazy_instance.h"
 #include "base/numerics/safe_conversions.h"
-#include "base/stl_util.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
diff --git a/components/variations/net/variations_http_headers.cc b/components/variations/net/variations_http_headers.cc
index 26e6aef7..62e512f 100644
--- a/components/variations/net/variations_http_headers.cc
+++ b/components/variations/net/variations_http_headers.cc
@@ -11,7 +11,6 @@
 #include "base/macros.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "components/google/core/common/google_util.h"
 #include "components/variations/net/omnibox_http_headers.h"
diff --git a/components/viz/common/quads/render_pass_io.cc b/components/viz/common/quads/render_pass_io.cc
index 80ab3245..33fcfb23 100644
--- a/components/viz/common/quads/render_pass_io.cc
+++ b/components/viz/common/quads/render_pass_io.cc
@@ -11,7 +11,6 @@
 #include "base/base64.h"
 #include "base/bit_cast.h"
 #include "base/containers/span.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_tokenizer.h"
 #include "cc/paint/paint_op_reader.h"
diff --git a/components/viz/service/display/direct_renderer.cc b/components/viz/service/display/direct_renderer.cc
index 71261f1..b58bdb39 100644
--- a/components/viz/service/display/direct_renderer.cc
+++ b/components/viz/service/display/direct_renderer.cc
@@ -15,7 +15,6 @@
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/numerics/safe_conversions.h"
-#include "base/stl_util.h"
 #include "base/timer/elapsed_timer.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
diff --git a/components/viz/service/display/display_resource_provider.cc b/components/viz/service/display/display_resource_provider.cc
index d0738b30..31b42663 100644
--- a/components/viz/service/display/display_resource_provider.cc
+++ b/components/viz/service/display/display_resource_provider.cc
@@ -9,7 +9,6 @@
 
 #include "base/atomic_sequence_num.h"
 #include "base/numerics/safe_math.h"
-#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/memory_dump_manager.h"
diff --git a/components/viz/service/display/scoped_gpu_memory_buffer_texture.cc b/components/viz/service/display/scoped_gpu_memory_buffer_texture.cc
index 2ae1a77d..becf3a7 100644
--- a/components/viz/service/display/scoped_gpu_memory_buffer_texture.cc
+++ b/components/viz/service/display/scoped_gpu_memory_buffer_texture.cc
@@ -6,7 +6,6 @@
 
 #include "base/bits.h"
 #include "base/check.h"
-#include "base/stl_util.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "components/viz/common/resources/resource_format.h"
 #include "components/viz/common/resources/resource_format_utils.h"
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc
index bf18b59..72613289b 100644
--- a/components/viz/service/display/surface_aggregator.cc
+++ b/components/viz/service/display/surface_aggregator.cc
@@ -16,7 +16,6 @@
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/numerics/ranges.h"
-#include "base/stl_util.h"
 #include "base/timer/elapsed_timer.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/base/math_util.h"
@@ -147,6 +146,7 @@
       needs_surface_damage_rect_list_(needs_surface_damage_rect_list),
       de_jelly_enabled_(DeJellyEnabled()) {
   DCHECK(manager_);
+  DCHECK(provider_);
 }
 
 SurfaceAggregator::~SurfaceAggregator() {
@@ -581,12 +581,8 @@
   }
 
   referenced_surfaces_.insert(surface_id);
-  // TODO(vmpstr): provider check is a hack for unittests that don't set up a
-  // resource provider.
-  std::unordered_map<ResourceId, ResourceId, ResourceIdHasher> empty_map;
   const auto& child_to_parent_map =
-      provider_ ? provider_->GetChildToParentMap(ChildIdForSurface(surface))
-                : empty_map;
+      provider_->GetChildToParentMap(ChildIdForSurface(surface));
   gfx::Transform combined_transform = scaled_quad_to_target_transform;
   combined_transform.ConcatTransform(target_transform);
 
@@ -1196,12 +1192,8 @@
 
   ++stats_->copied_surface_count;
 
-  // TODO(vmpstr): provider check is a hack for unittests that don't set up a
-  // resource provider.
-  std::unordered_map<ResourceId, ResourceId, ResourceIdHasher> empty_map;
   const auto& child_to_parent_map =
-      provider_ ? provider_->GetChildToParentMap(ChildIdForSurface(surface))
-                : empty_map;
+      provider_->GetChildToParentMap(ChildIdForSurface(surface));
 
   const gfx::Transform surface_transform =
       IsRootSurface(surface) ? root_surface_transform_ : gfx::Transform();
@@ -1542,10 +1534,6 @@
     Surface* surface,
     const std::vector<TransferableResource>& resource_list,
     const CompositorRenderPassList& render_passes) {
-  // |provider_| may be null in tests.
-  if (!provider_)
-    return true;
-
   int child_id = ChildIdForSurface(surface);
 
   // Ref the resources in the surface, and let the provider know we've received
diff --git a/components/viz/service/display/surface_aggregator_unittest.cc b/components/viz/service/display/surface_aggregator_unittest.cc
index 3b15867..a28599a 100644
--- a/components/viz/service/display/surface_aggregator_unittest.cc
+++ b/components/viz/service/display/surface_aggregator_unittest.cc
@@ -32,6 +32,7 @@
 #include "components/viz/common/quads/surface_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/yuv_video_draw_quad.h"
+#include "components/viz/common/resources/resource_id.h"
 #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
 #include "components/viz/common/surfaces/subtree_capture_id.h"
 #include "components/viz/service/display/aggregated_frame.h"
@@ -80,6 +81,29 @@
   return gfx::Rect();
 }
 
+// Populate valid looking TransferableResources for `frame` based on DrawQuad
+// ResourceIds.
+void PopulateTransferableResources(CompositorFrame& frame) {
+  DCHECK(frame.resource_list.empty());
+
+  std::set<ResourceId> resources_added;
+  for (auto& render_pass : frame.render_pass_list) {
+    for (auto* quad : render_pass->quad_list) {
+      for (ResourceId resource_id : quad->resources) {
+        if (resource_id == kInvalidResourceId)
+          continue;
+
+        // Adds a TransferableResource the first time seeing a ResourceId.
+        if (resources_added.insert(resource_id).second) {
+          frame.resource_list.push_back(TransferableResource::MakeSoftware(
+              SharedBitmap::GenerateId(), quad->rect.size(), RGBA_8888));
+          frame.resource_list.back().id = resource_id;
+        }
+      }
+    }
+  }
+}
+
 class MockAggregatedDamageCallback {
  public:
   MockAggregatedDamageCallback() {}
@@ -131,7 +155,7 @@
             kArbitraryRootFrameSinkId,
             kRootIsRoot)),
         aggregator_(manager_.surface_manager(),
-                    nullptr,
+                    &resource_provider_,
                     use_damage_rect,
                     true) {
     manager_.surface_manager()->AddObserver(&observer_);
@@ -430,14 +454,15 @@
     auto* quad = pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
     quad->SetNew(shared_state, output_rect, output_rect, false,
                  gfx::RectF(output_rect), gfx::RectF(), output_rect.size(),
-                 gfx::Size(), kInvalidResourceId, kInvalidResourceId,
-                 kInvalidResourceId, kInvalidResourceId,
-                 gfx::ColorSpace::CreateREC709(), 0, 1.0, 8);
+                 gfx::Size(), ResourceId(1), ResourceId(2), ResourceId(3),
+                 kInvalidResourceId, gfx::ColorSpace::CreateREC709(), 0, 1.0,
+                 8);
   }
 
  protected:
   ServerSharedBitmapManager shared_bitmap_manager_;
   FrameSinkManagerImpl manager_;
+  DisplayResourceProviderSoftware resource_provider_{&shared_bitmap_manager_};
   FakeSurfaceObserver observer_;
   FakeCompositorFrameSinkClient fake_client_;
   std::unique_ptr<CompositorFrameSinkSupport> root_sink_;
@@ -5350,23 +5375,13 @@
   }
 }
 
-class SurfaceAggregatorWithResourcesTest : public testing::Test,
-                                           public DisplayTimeSource {
+class SurfaceAggregatorWithResourcesTest : public SurfaceAggregatorTest {
  public:
-  SurfaceAggregatorWithResourcesTest() : manager_(&shared_bitmap_manager_) {}
-
-  void SetUp() override {
-    resource_provider_ = std::make_unique<DisplayResourceProviderSoftware>(
-        &shared_bitmap_manager_);
-
-    aggregator_ = std::make_unique<SurfaceAggregator>(
-        manager_.surface_manager(), resource_provider_.get(), false, false);
-    aggregator_->set_output_is_secure(true);
-  }
-
-  AggregatedFrame AggregateFrame(const SurfaceId& surface_id) {
-    return aggregator_->Aggregate(surface_id, GetNextDisplayTimeAndIncrement(),
-                                  gfx::OVERLAY_TRANSFORM_NONE);
+  SurfaceAggregatorWithResourcesTest() : SurfaceAggregatorTest(false) {
+    // BuildCompositorFrameWithResources() sets secure_output_only=true on
+    // TextureDrawQuads so this will ensure they aren't dropped from the
+    // AggregatedFrame.
+    aggregator_.set_output_is_secure(true);
   }
 
   void SendBeginFrame(CompositorFrameSinkSupport* support, uint64_t id) {
@@ -5374,12 +5389,6 @@
         CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, id);
     support->OnBeginFrame(args);
   }
-
- protected:
-  ServerSharedBitmapManager shared_bitmap_manager_;
-  FrameSinkManagerImpl manager_;
-  std::unique_ptr<DisplayResourceProvider> resource_provider_;
-  std::unique_ptr<SurfaceAggregator> aggregator_;
 };
 
 CompositorFrame BuildCompositorFrameWithResources(
@@ -5444,31 +5453,28 @@
 }
 
 TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) {
-  FakeCompositorFrameSinkClient client;
-  auto support = std::make_unique<CompositorFrameSinkSupport>(
-      &client, &manager_, kArbitraryRootFrameSinkId, kRootIsRoot);
   LocalSurfaceId local_surface_id(7u, base::UnguessableToken::Create());
-  SurfaceId surface_id(support->frame_sink_id(), local_surface_id);
+  SurfaceId surface_id(root_sink_->frame_sink_id(), local_surface_id);
 
   std::vector<ResourceId> ids = {ResourceId(11), ResourceId(12),
                                  ResourceId(13)};
-  SubmitCompositorFrameWithResources(ids, true, SurfaceId(), support.get(),
+  SubmitCompositorFrameWithResources(ids, true, SurfaceId(), root_sink_.get(),
                                      surface_id);
 
   auto frame = AggregateFrame(surface_id);
 
   // Nothing should be available to be returned yet.
-  EXPECT_TRUE(client.returned_resources().empty());
+  EXPECT_TRUE(fake_client_.returned_resources().empty());
 
-  SubmitCompositorFrameWithResources({}, true, SurfaceId(), support.get(),
+  SubmitCompositorFrameWithResources({}, true, SurfaceId(), root_sink_.get(),
                                      surface_id);
 
   frame = AggregateFrame(surface_id);
 
-  ASSERT_EQ(3u, client.returned_resources().size());
+  ASSERT_EQ(3u, fake_client_.returned_resources().size());
   ResourceId returned_ids[3];
   for (size_t i = 0; i < 3; ++i) {
-    returned_ids[i] = client.returned_resources()[i].id;
+    returned_ids[i] = fake_client_.returned_resources()[i].id;
   }
   EXPECT_THAT(returned_ids,
               testing::WhenSorted(testing::ElementsAreArray(ids)));
@@ -5478,47 +5484,41 @@
 // ID, and a new display frame is generated, then the resources of the old
 // surface are returned to the appropriate client.
 TEST_F(SurfaceAggregatorWithResourcesTest, ReturnResourcesAsSurfacesChange) {
-  FakeCompositorFrameSinkClient client;
-  auto support = std::make_unique<CompositorFrameSinkSupport>(
-      &client, &manager_, kArbitraryRootFrameSinkId, kRootIsRoot);
   LocalSurfaceId local_surface_id1(7u, base::UnguessableToken::Create());
   LocalSurfaceId local_surface_id2(8u, base::UnguessableToken::Create());
-  SurfaceId surface_id1(support->frame_sink_id(), local_surface_id1);
-  SurfaceId surface_id2(support->frame_sink_id(), local_surface_id2);
+  SurfaceId surface_id1(root_sink_->frame_sink_id(), local_surface_id1);
+  SurfaceId surface_id2(root_sink_->frame_sink_id(), local_surface_id2);
 
   std::vector<ResourceId> ids = {ResourceId(11), ResourceId(12),
                                  ResourceId(13)};
-  SubmitCompositorFrameWithResources(ids, true, SurfaceId(), support.get(),
+  SubmitCompositorFrameWithResources(ids, true, SurfaceId(), root_sink_.get(),
                                      surface_id1);
 
   auto frame = AggregateFrame(surface_id1);
 
   // Nothing should be available to be returned yet.
-  EXPECT_TRUE(client.returned_resources().empty());
+  EXPECT_TRUE(fake_client_.returned_resources().empty());
 
   // Submitting a CompositorFrame to |surface_id2| should cause the surface
   // associated with |surface_id1| to get garbage collected.
-  SubmitCompositorFrameWithResources({}, true, SurfaceId(), support.get(),
+  SubmitCompositorFrameWithResources({}, true, SurfaceId(), root_sink_.get(),
                                      surface_id2);
   manager_.surface_manager()->GarbageCollectSurfaces();
 
   frame = AggregateFrame(surface_id2);
 
-  ASSERT_EQ(3u, client.returned_resources().size());
+  ASSERT_EQ(3u, fake_client_.returned_resources().size());
   ResourceId returned_ids[3];
   for (size_t i = 0; i < 3; ++i) {
-    returned_ids[i] = client.returned_resources()[i].id;
+    returned_ids[i] = fake_client_.returned_resources()[i].id;
   }
   EXPECT_THAT(returned_ids,
               testing::WhenSorted(testing::ElementsAreArray(ids)));
 }
 
 TEST_F(SurfaceAggregatorWithResourcesTest, TakeInvalidResources) {
-  FakeCompositorFrameSinkClient client;
-  auto support = std::make_unique<CompositorFrameSinkSupport>(
-      &client, &manager_, kArbitraryRootFrameSinkId, kRootIsRoot);
   LocalSurfaceId local_surface_id(7u, base::UnguessableToken::Create());
-  SurfaceId surface_id(support->frame_sink_id(), local_surface_id);
+  SurfaceId surface_id(root_sink_->frame_sink_id(), local_surface_id);
 
   TransferableResource resource;
   resource.id = ResourceId(11);
@@ -5530,25 +5530,25 @@
                               .AddDefaultRenderPass()
                               .AddTransferableResource(resource)
                               .Build();
-  support->SubmitCompositorFrame(local_surface_id, std::move(frame));
+  root_sink_->SubmitCompositorFrame(local_surface_id, std::move(frame));
 
   auto returned_frame = AggregateFrame(surface_id);
 
   // Nothing should be available to be returned yet.
-  EXPECT_TRUE(client.returned_resources().empty());
+  EXPECT_TRUE(fake_client_.returned_resources().empty());
 
-  SubmitCompositorFrameWithResources({}, true, SurfaceId(), support.get(),
+  SubmitCompositorFrameWithResources({}, true, SurfaceId(), root_sink_.get(),
                                      surface_id);
-  ASSERT_EQ(1u, client.returned_resources().size());
-  EXPECT_EQ(ResourceId(11u), client.returned_resources()[0].id);
+  ASSERT_EQ(1u, fake_client_.returned_resources().size());
+  EXPECT_EQ(ResourceId(11u), fake_client_.returned_resources()[0].id);
 }
 
 TEST_F(SurfaceAggregatorWithResourcesTest, TwoSurfaces) {
   FakeCompositorFrameSinkClient client;
   auto support1 = std::make_unique<CompositorFrameSinkSupport>(
-      &client, &manager_, FrameSinkId(1, 1), kChildIsRoot);
+      &client, &manager_, FrameSinkId(3, 1), kChildIsRoot);
   auto support2 = std::make_unique<CompositorFrameSinkSupport>(
-      &client, &manager_, FrameSinkId(2, 2), kChildIsRoot);
+      &client, &manager_, FrameSinkId(4, 2), kChildIsRoot);
   LocalSurfaceId local_frame1_id(7u, base::UnguessableToken::Create());
   SurfaceId surface1_id(support1->frame_sink_id(), local_frame1_id);
 
@@ -5582,19 +5582,17 @@
   }
   EXPECT_THAT(returned_ids,
               testing::WhenSorted(testing::ElementsAreArray(ids)));
-  EXPECT_EQ(3u, resource_provider_->num_resources());
+  EXPECT_EQ(3u, resource_provider_.num_resources());
 }
 
 // Ensure that aggregator completely ignores Surfaces that reference invalid
 // resources.
 TEST_F(SurfaceAggregatorWithResourcesTest, InvalidChildSurface) {
-  auto root_support = std::make_unique<CompositorFrameSinkSupport>(
-      nullptr, &manager_, kArbitraryRootFrameSinkId, kRootIsRoot);
   auto middle_support = std::make_unique<CompositorFrameSinkSupport>(
       nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot);
   auto child_support = std::make_unique<CompositorFrameSinkSupport>(
       nullptr, &manager_, kArbitraryFrameSinkId1, kChildIsRoot);
-  TestSurfaceIdAllocator root_surface_id(root_support->frame_sink_id());
+  TestSurfaceIdAllocator root_surface_id(root_sink_->frame_sink_id());
   TestSurfaceIdAllocator middle_surface_id(middle_support->frame_sink_id());
   TestSurfaceIdAllocator child_surface_id(child_support->frame_sink_id());
 
@@ -5611,7 +5609,7 @@
   std::vector<ResourceId> ids3 = {ResourceId(20), ResourceId(21),
                                   ResourceId(22)};
   SubmitCompositorFrameWithResources(ids3, true, middle_surface_id,
-                                     root_support.get(), root_surface_id);
+                                     root_sink_.get(), root_surface_id);
 
   auto frame = AggregateFrame(root_surface_id);
 
@@ -5632,9 +5630,9 @@
 
 TEST_F(SurfaceAggregatorWithResourcesTest, SecureOutputTexture) {
   auto support1 = std::make_unique<CompositorFrameSinkSupport>(
-      nullptr, &manager_, FrameSinkId(1, 1), kChildIsRoot);
+      nullptr, &manager_, FrameSinkId(3, 1), kChildIsRoot);
   auto support2 = std::make_unique<CompositorFrameSinkSupport>(
-      nullptr, &manager_, FrameSinkId(2, 2), kChildIsRoot);
+      nullptr, &manager_, FrameSinkId(4, 2), kChildIsRoot);
   support2->set_allow_copy_output_requests_for_testing();
   LocalSurfaceId local_frame1_id(7u, base::UnguessableToken::Create());
   SurfaceId surface1_id(support1->frame_sink_id(), local_frame1_id);
@@ -5690,7 +5688,7 @@
   EXPECT_EQ(DrawQuad::Material::kTextureContent,
             render_pass->quad_list.front()->material);
 
-  aggregator_->set_output_is_secure(false);
+  aggregator_.set_output_is_secure(false);
 
   frame = AggregateFrame(surface2_id);
   render_pass = frame.render_pass_list.back().get();
@@ -6564,6 +6562,7 @@
   CompositorFrame child_surface_frame = MakeEmptyCompositorFrame();
   AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
             &child_surface_frame.metadata.referenced_surfaces);
+  PopulateTransferableResources(child_surface_frame);
 
   TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
   child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
@@ -6613,7 +6612,7 @@
             aggregated_frame.surface_damage_rect_list_[0]);
 
   // Video quad(10, 0, 80, 80) is damaged.
-  EXPECT_TRUE(video_sqs->overlay_damage_index.has_value());
+  ASSERT_TRUE(video_sqs->overlay_damage_index.has_value());
   auto index = video_sqs->overlay_damage_index.value();
   EXPECT_EQ(1U, index);
   EXPECT_EQ(gfx::Rect(10, 0, 80, 80),
@@ -6624,6 +6623,7 @@
     CompositorFrame child_surface_frame = MakeEmptyCompositorFrame();
     AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
               &child_surface_frame.metadata.referenced_surfaces);
+    PopulateTransferableResources(child_surface_frame);
     child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
                                        std::move(child_surface_frame));
 
@@ -8505,44 +8505,40 @@
 }
 
 TEST_F(SurfaceAggregatorWithResourcesTest, TransitionDirectiveFrameBehind) {
-  FakeCompositorFrameSinkClient client;
-  auto support = std::make_unique<CompositorFrameSinkSupport>(
-      &client, &manager_, kArbitraryRootFrameSinkId, kRootIsRoot);
-
   LocalSurfaceId local_surface_id(7u, base::UnguessableToken::Create());
-  SurfaceId surface_id(support->frame_sink_id(), local_surface_id);
+  SurfaceId surface_id(root_sink_->frame_sink_id(), local_surface_id);
 
   // Create and submit a 'save' frame.
-  SendBeginFrame(support.get(), 1);
+  SendBeginFrame(root_sink_.get(), 1);
   {
     auto frame = BuildCompositorFrameWithResources({}, true, SurfaceId());
     frame.metadata.transition_directives.emplace_back(
         1, CompositorFrameTransitionDirective::Type::kSave,
         CompositorFrameTransitionDirective::Effect::kCoverLeft);
 
-    support->SubmitCompositorFrame(local_surface_id, std::move(frame));
-    auto* surface = support->GetLastCreatedSurfaceForTesting();
+    root_sink_->SubmitCompositorFrame(local_surface_id, std::move(frame));
+    auto* surface = root_sink_->GetLastCreatedSurfaceForTesting();
     ASSERT_TRUE(surface);
     surface->GetSurfaceSavedFrameStorage()->CompleteForTesting();
   }
   AggregateFrame(surface_id);
 
   // Create and submit an 'animate' frame.
-  SendBeginFrame(support.get(), 2);
+  SendBeginFrame(root_sink_.get(), 2);
   {
     auto frame = BuildCompositorFrameWithResources({}, true, SurfaceId());
     frame.metadata.transition_directives.emplace_back(
         2, CompositorFrameTransitionDirective::Type::kAnimate);
-    support->SubmitCompositorFrame(local_surface_id, std::move(frame));
+    root_sink_->SubmitCompositorFrame(local_surface_id, std::move(frame));
   }
   AggregateFrame(surface_id);
 
   // Create and submit a frame with some resources.
-  SendBeginFrame(support.get(), 3);
+  SendBeginFrame(root_sink_.get(), 3);
   {
     std::vector<ResourceId> ids = {ResourceId(11), ResourceId(12),
                                    ResourceId(13)};
-    SubmitCompositorFrameWithResources(ids, true, SurfaceId(), support.get(),
+    SubmitCompositorFrameWithResources(ids, true, SurfaceId(), root_sink_.get(),
                                        surface_id);
   }
   auto frame = AggregateFrame(surface_id);
@@ -8562,13 +8558,13 @@
 
   // At this point we will interpolate with the above frame (resources 11, 12,
   // 13).
-  SendBeginFrame(support.get(), 4);
+  SendBeginFrame(root_sink_.get(), 4);
   {
     std::vector<ResourceId> ids = {ResourceId(15), ResourceId(16),
                                    ResourceId(17)};
     // This will cause an activation which will unref 11, 12, 13. So, the
     // activation must also interpolate a new frame.
-    SubmitCompositorFrameWithResources(ids, true, SurfaceId(), support.get(),
+    SubmitCompositorFrameWithResources(ids, true, SurfaceId(), root_sink_.get(),
                                        surface_id);
   }
   // Ensure that the interpolated frame is not using unreffed resources
@@ -8578,10 +8574,10 @@
   // ones) from the original frame).
   EXPECT_EQ(count_textures(frame), 4u);
 
-  ASSERT_EQ(3u, client.returned_resources().size());
+  ASSERT_EQ(3u, fake_client_.returned_resources().size());
   ResourceId returned_ids[3];
   for (size_t i = 0; i < 3; ++i) {
-    returned_ids[i] = client.returned_resources()[i].id;
+    returned_ids[i] = fake_client_.returned_resources()[i].id;
   }
   // We expect that 11, 12, and 13 are now returned.
   EXPECT_THAT(returned_ids,
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
index 45bcf71..2bed9bb 100644
--- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
+++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
@@ -13,7 +13,6 @@
 #include "base/callback_helpers.h"
 #include "base/memory/read_only_shared_memory_region.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/time/default_tick_clock.h"
diff --git a/components/viz/service/frame_sinks/video_detector_unittest.cc b/components/viz/service/frame_sinks/video_detector_unittest.cc
index cd475dd..f0c462a 100644
--- a/components/viz/service/frame_sinks/video_detector_unittest.cc
+++ b/components/viz/service/frame_sinks/video_detector_unittest.cc
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <algorithm>
 #include <memory>
 #include <set>
+#include <utility>
 
 #include "base/compiler_specific.h"
 #include "base/containers/circular_deque.h"
@@ -12,6 +14,7 @@
 #include "base/time/time.h"
 #include "components/viz/common/quads/surface_draw_quad.h"
 #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
+#include "components/viz/service/display/display_resource_provider_software.h"
 #include "components/viz/service/display/surface_aggregator.h"
 #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
 #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
@@ -78,9 +81,8 @@
 class VideoDetectorTest : public testing::Test {
  public:
   VideoDetectorTest()
-      : frame_sink_manager_(&shared_bitmap_manager_),
-        surface_aggregator_(frame_sink_manager_.surface_manager(),
-                            nullptr,
+      : surface_aggregator_(frame_sink_manager_.surface_manager(),
+                            &resource_provider_,
                             false,
                             false) {}
 
@@ -205,7 +207,8 @@
   }
 
   ServerSharedBitmapManager shared_bitmap_manager_;
-  FrameSinkManagerImpl frame_sink_manager_;
+  FrameSinkManagerImpl frame_sink_manager_{&shared_bitmap_manager_};
+  DisplayResourceProviderSoftware resource_provider_{&shared_bitmap_manager_};
   FakeCompositorFrameSinkClient frame_sink_client_;
   SurfaceIdAllocatorSet allocators_;
   SurfaceAggregator surface_aggregator_;
diff --git a/components/webcrypto/algorithms/aes_gcm.cc b/components/webcrypto/algorithms/aes_gcm.cc
index f75c461..0f3f70c 100644
--- a/components/webcrypto/algorithms/aes_gcm.cc
+++ b/components/webcrypto/algorithms/aes_gcm.cc
@@ -8,7 +8,6 @@
 #include <memory>
 #include <vector>
 
-#include "base/stl_util.h"
 #include "components/webcrypto/algorithms/aes.h"
 #include "components/webcrypto/algorithms/util.h"
 #include "components/webcrypto/blink_key_handle.h"
diff --git a/components/webcrypto/algorithms/ecdh_unittest.cc b/components/webcrypto/algorithms/ecdh_unittest.cc
index 1a5b92b..693efce 100644
--- a/components/webcrypto/algorithms/ecdh_unittest.cc
+++ b/components/webcrypto/algorithms/ecdh_unittest.cc
@@ -5,7 +5,6 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "base/stl_util.h"
 #include "components/webcrypto/algorithm_dispatch.h"
 #include "components/webcrypto/algorithms/ec.h"
 #include "components/webcrypto/algorithms/test_helpers.h"
diff --git a/components/webcrypto/algorithms/ecdsa_unittest.cc b/components/webcrypto/algorithms/ecdsa_unittest.cc
index 1f56bf0e..dd1bf41 100644
--- a/components/webcrypto/algorithms/ecdsa_unittest.cc
+++ b/components/webcrypto/algorithms/ecdsa_unittest.cc
@@ -5,7 +5,6 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "base/stl_util.h"
 #include "components/webcrypto/algorithm_dispatch.h"
 #include "components/webcrypto/algorithms/test_helpers.h"
 #include "components/webcrypto/crypto_data.h"
diff --git a/components/webcrypto/algorithms/pbkdf2.cc b/components/webcrypto/algorithms/pbkdf2.cc
index 3c73173..41f5d88 100644
--- a/components/webcrypto/algorithms/pbkdf2.cc
+++ b/components/webcrypto/algorithms/pbkdf2.cc
@@ -6,7 +6,6 @@
 
 #include <memory>
 
-#include "base/stl_util.h"
 #include "components/webcrypto/algorithm_implementation.h"
 #include "components/webcrypto/algorithms/secret_key_util.h"
 #include "components/webcrypto/algorithms/util.h"
diff --git a/components/webcrypto/algorithms/rsa_pss_unittest.cc b/components/webcrypto/algorithms/rsa_pss_unittest.cc
index 5f917e2..8e313bc 100644
--- a/components/webcrypto/algorithms/rsa_pss_unittest.cc
+++ b/components/webcrypto/algorithms/rsa_pss_unittest.cc
@@ -5,7 +5,6 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "base/stl_util.h"
 #include "components/webcrypto/algorithm_dispatch.h"
 #include "components/webcrypto/algorithms/test_helpers.h"
 #include "components/webcrypto/crypto_data.h"
diff --git a/components/webcrypto/status_unittest.cc b/components/webcrypto/status_unittest.cc
index ad12820..27dd89d 100644
--- a/components/webcrypto/status_unittest.cc
+++ b/components/webcrypto/status_unittest.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "components/webcrypto/status.h"
-#include "base/stl_util.h"
 #include "components/webcrypto/algorithm_dispatch.h"
 #include "components/webcrypto/algorithms/test_helpers.h"
 #include "components/webcrypto/crypto_data.h"
diff --git a/components/webdata/common/web_data_request_manager.cc b/components/webdata/common/web_data_request_manager.cc
index 7080a5f..349bd72 100644
--- a/components/webdata/common/web_data_request_manager.cc
+++ b/components/webdata/common/web_data_request_manager.cc
@@ -9,7 +9,6 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/sequenced_task_runner_handle.h"
diff --git a/components/webdata/common/web_database.cc b/components/webdata/common/web_database.cc
index f05381e..410cd48 100644
--- a/components/webdata/common/web_database.cc
+++ b/components/webdata/common/web_database.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 
 #include "base/logging.h"
-#include "base/stl_util.h"
 #include "sql/transaction.h"
 
 // Current version number.  Note: when changing the current version number,
diff --git a/components/webdata/common/web_database_migration_unittest.cc b/components/webdata/common/web_database_migration_unittest.cc
index f87805c..7d27357 100644
--- a/components/webdata/common/web_database_migration_unittest.cc
+++ b/components/webdata/common/web_database_migration_unittest.cc
@@ -9,7 +9,6 @@
 #include "base/guid.h"
 #include "base/macros.h"
 #include "base/path_service.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
index c8f85d6..80dbec96 100644
--- a/content/browser/accessibility/browser_accessibility.cc
+++ b/content/browser/accessibility/browser_accessibility.cc
@@ -2325,11 +2325,8 @@
   DCHECK(PlatformChildCount());
 
   int start_offset = 0;
-  for (BrowserAccessibility::PlatformChildIterator it = PlatformChildrenBegin();
-       it != PlatformChildrenEnd(); ++it) {
-    BrowserAccessibility* child = it.get();
-    DCHECK(child);
-    ui::TextAttributeList attributes(child->ComputeTextAttributes());
+  for (const auto& child : PlatformChildren()) {
+    ui::TextAttributeList attributes(child.ComputeTextAttributes());
 
     if (attributes_map.empty()) {
       attributes_map[start_offset] = attributes;
@@ -2347,12 +2344,12 @@
       }
     }
 
-    if (child->IsText()) {
+    if (child.IsText()) {
       const ui::TextAttributeMap spelling_attributes =
-          child->GetSpellingAndGrammarAttributes();
+          child.GetSpellingAndGrammarAttributes();
       MergeSpellingAndGrammarIntoTextAttributes(spelling_attributes,
                                                 start_offset, &attributes_map);
-      start_offset += child->GetHypertext().length();
+      start_offset += child.GetHypertext().length();
     } else {
       start_offset += 1;
     }
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h
index a24e5562..c1e651e 100644
--- a/content/browser/accessibility/browser_accessibility.h
+++ b/content/browser/accessibility/browser_accessibility.h
@@ -124,6 +124,7 @@
   virtual BrowserAccessibility* PlatformGetNextSibling() const;
   virtual BrowserAccessibility* PlatformGetPreviousSibling() const;
 
+  // Iterator over platform children.
   class CONTENT_EXPORT PlatformChildIterator : public ChildIterator {
    public:
     PlatformChildIterator(const BrowserAccessibility* parent,
@@ -153,6 +154,26 @@
         platform_iterator;
   };
 
+  // C++ range implementation for platform children, see PlatformChildren().
+  class PlatformChildrenRange {
+   public:
+    explicit PlatformChildrenRange(const BrowserAccessibility* parent)
+        : parent_(parent) {}
+    PlatformChildrenRange(const PlatformChildrenRange&) = default;
+
+    PlatformChildIterator begin() { return parent_->PlatformChildrenBegin(); }
+    PlatformChildIterator end() { return parent_->PlatformChildrenEnd(); }
+
+   private:
+    const BrowserAccessibility* const parent_;
+  };
+
+  // Returns a range for platform children which can be used in range-based for
+  // loops, for example, for (const auto& child : PlatformChildren()) {}.
+  PlatformChildrenRange PlatformChildren() const {
+    return PlatformChildrenRange(this);
+  }
+
   PlatformChildIterator PlatformChildrenBegin() const;
   PlatformChildIterator PlatformChildrenEnd() const;
   // Return a pointer to the first ancestor that is a selection container
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc
index 13e390be..725c325 100644
--- a/content/browser/accessibility/browser_accessibility_android.cc
+++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -420,11 +420,10 @@
     return this;
 
   const BrowserAccessibilityAndroid* sole_interesting_node = nullptr;
-  for (PlatformChildIterator it = PlatformChildrenBegin();
-       it != PlatformChildrenEnd(); ++it) {
+  for (const auto& child : PlatformChildren()) {
     const BrowserAccessibilityAndroid* interesting_node =
-        static_cast<const BrowserAccessibilityAndroid*>(it.get())
-            ->GetSoleInterestingNodeFromSubtree();
+        static_cast<const BrowserAccessibilityAndroid&>(child)
+            .GetSoleInterestingNodeFromSubtree();
     if (interesting_node && sole_interesting_node) {
       // If there are two interesting nodes, return nullptr.
       return nullptr;
@@ -745,12 +744,11 @@
   // Count the number of children and selected children.
   int child_count = 0;
   int selected_count = 0;
-  for (PlatformChildIterator it = PlatformChildrenBegin();
-       it != PlatformChildrenEnd(); ++it) {
+  for (const auto& child : PlatformChildren()) {
     child_count++;
-    BrowserAccessibilityAndroid* child =
-        static_cast<BrowserAccessibilityAndroid*>(it.get());
-    if (child->IsSelected())
+    const BrowserAccessibilityAndroid& android_child =
+        static_cast<const BrowserAccessibilityAndroid&>(child);
+    if (android_child.IsSelected())
       selected_count++;
   }
 
@@ -869,12 +867,11 @@
   //
   // Find child input node:
   const BrowserAccessibilityAndroid* input_node = nullptr;
-  for (PlatformChildIterator it = PlatformChildrenBegin();
-       it != PlatformChildrenEnd(); ++it) {
-    const BrowserAccessibilityAndroid* child_node =
-        static_cast<BrowserAccessibilityAndroid*>(it.get());
-    if (child_node->IsTextField()) {
-      input_node = child_node;
+  for (const auto& child : PlatformChildren()) {
+    const BrowserAccessibilityAndroid& android_child =
+        static_cast<const BrowserAccessibilityAndroid&>(child);
+    if (android_child.IsTextField()) {
+      input_node = &android_child;
       break;
     }
   }
@@ -932,14 +929,13 @@
 
   // Check for child nodes that are collections.
   int child_collection_count = 0;
-  BrowserAccessibilityAndroid* collection_node = nullptr;
-  for (PlatformChildIterator it = PlatformChildrenBegin();
-       it != PlatformChildrenEnd(); ++it) {
-    BrowserAccessibilityAndroid* child =
-        static_cast<BrowserAccessibilityAndroid*>(it.get());
-    if (child->IsCollection()) {
+  const BrowserAccessibilityAndroid* collection_node = nullptr;
+  for (const auto& child : PlatformChildren()) {
+    const auto& android_child =
+        static_cast<const BrowserAccessibilityAndroid&>(child);
+    if (android_child.IsCollection()) {
       child_collection_count++;
-      collection_node = child;
+      collection_node = &android_child;
     }
   }
 
@@ -1666,11 +1662,10 @@
 int BrowserAccessibilityAndroid::GetSelectedItemCount() const {
   // Count the number of selected children.
   int selected_count = 0;
-  for (PlatformChildIterator it = PlatformChildrenBegin();
-       it != PlatformChildrenEnd(); ++it) {
-    BrowserAccessibilityAndroid* child =
-        static_cast<BrowserAccessibilityAndroid*>(it.get());
-    if (child->IsSelected())
+  for (const auto& child : PlatformChildren()) {
+    const BrowserAccessibilityAndroid& android_child =
+        static_cast<const BrowserAccessibilityAndroid&>(child);
+    if (android_child.IsSelected())
       selected_count++;
   }
 
@@ -2366,9 +2361,8 @@
 int BrowserAccessibilityAndroid::CountChildrenWithRole(
     ax::mojom::Role role) const {
   int count = 0;
-  for (PlatformChildIterator it = PlatformChildrenBegin();
-       it != PlatformChildrenEnd(); ++it) {
-    if (it->GetRole() == role)
+  for (const auto& child : PlatformChildren()) {
+    if (child.GetRole() == role)
       count++;
   }
   return count;
diff --git a/content/browser/accessibility/web_contents_accessibility_android.cc b/content/browser/accessibility/web_contents_accessibility_android.cc
index ee23d97..91a0a2c 100644
--- a/content/browser/accessibility/web_contents_accessibility_android.cc
+++ b/content/browser/accessibility/web_contents_accessibility_android.cc
@@ -781,11 +781,10 @@
 
   // Build a vector of child ids
   std::vector<int> child_ids;
-  for (BrowserAccessibility::PlatformChildIterator it =
-           node->PlatformChildrenBegin();
-       it != node->PlatformChildrenEnd(); ++it) {
-    auto* android_node = static_cast<BrowserAccessibilityAndroid*>(it.get());
-    child_ids.push_back(android_node->unique_id());
+  for (const auto& child : node->PlatformChildren()) {
+    const auto& android_node =
+        static_cast<const BrowserAccessibilityAndroid&>(child);
+    child_ids.push_back(android_node.unique_id());
   }
   if (child_ids.size()) {
     Java_WebContentsAccessibilityImpl_addAccessibilityNodeInfoChildren(
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h
index e803917b..458bed2 100644
--- a/content/browser/bad_message.h
+++ b/content/browser/bad_message.h
@@ -24,7 +24,7 @@
 // end. Items may be renamed but do not change the values. We rely on the enum
 // values in histograms.
 enum BadMessageReason {
-  NC_IN_PAGE_NAVIGATION = 0,
+  OBSOLETE_NC_IN_PAGE_NAVIGATION = 0,
   RFH_CAN_COMMIT_URL_BLOCKED = 1,
   RFH_CAN_ACCESS_FILES_OF_PAGE_STATE = 2,
   RFH_SANDBOX_FLAGS = 3,
diff --git a/content/browser/devtools/network_service_devtools_observer.cc b/content/browser/devtools/network_service_devtools_observer.cc
index 5791453..3997bf60 100644
--- a/content/browser/devtools/network_service_devtools_observer.cc
+++ b/content/browser/devtools/network_service_devtools_observer.cc
@@ -212,6 +212,54 @@
       ftn->current_frame_host(), issue.get());
 }
 
+void NetworkServiceDevToolsObserver::OnSubresourceWebBundleMetadata(
+    const std::string& devtools_request_id,
+    const std::vector<GURL>& urls) {
+  auto* host = GetDevToolsAgentHost();
+  if (!host)
+    return;
+  DispatchToAgents(host,
+                   &protocol::NetworkHandler::OnSubresourceWebBundleMetadata,
+                   devtools_request_id, urls);
+}
+
+void NetworkServiceDevToolsObserver::OnSubresourceWebBundleMetadataError(
+    const std::string& devtools_request_id,
+    const std::string& error_message) {
+  auto* host = GetDevToolsAgentHost();
+  if (!host)
+    return;
+  DispatchToAgents(
+      host, &protocol::NetworkHandler::OnSubresourceWebBundleMetadataError,
+      devtools_request_id, error_message);
+}
+
+void NetworkServiceDevToolsObserver::OnSubresourceWebBundleInnerResponse(
+    const std::string& inner_request_devtools_id,
+    const GURL& url,
+    const absl::optional<std::string>& bundle_request_devtools_id) {
+  auto* host = GetDevToolsAgentHost();
+  if (!host)
+    return;
+  DispatchToAgents(
+      host, &protocol::NetworkHandler::OnSubresourceWebBundleInnerResponse,
+      inner_request_devtools_id, url, bundle_request_devtools_id);
+}
+
+void NetworkServiceDevToolsObserver::OnSubresourceWebBundleInnerResponseError(
+    const std::string& inner_request_devtools_id,
+    const GURL& url,
+    const std::string& error_message,
+    const absl::optional<std::string>& bundle_request_devtools_id) {
+  auto* host = GetDevToolsAgentHost();
+  if (!host)
+    return;
+  DispatchToAgents(
+      host, &protocol::NetworkHandler::OnSubresourceWebBundleInnerResponseError,
+      inner_request_devtools_id, url, error_message,
+      bundle_request_devtools_id);
+}
+
 void NetworkServiceDevToolsObserver::Clone(
     mojo::PendingReceiver<network::mojom::DevToolsObserver> observer) {
   mojo::MakeSelfOwnedReceiver(
diff --git a/content/browser/devtools/network_service_devtools_observer.h b/content/browser/devtools/network_service_devtools_observer.h
index b270917..be9ebed 100644
--- a/content/browser/devtools/network_service_devtools_observer.h
+++ b/content/browser/devtools/network_service_devtools_observer.h
@@ -71,6 +71,20 @@
                    const absl::optional<::url::Origin>& initiator_origin,
                    const GURL& url,
                    const network::CorsErrorStatus& status) override;
+  void OnSubresourceWebBundleMetadata(const std::string& devtools_request_id,
+                                      const std::vector<GURL>& urls) override;
+  void OnSubresourceWebBundleMetadataError(
+      const std::string& devtools_request_id,
+      const std::string& error_message) override;
+  void OnSubresourceWebBundleInnerResponse(
+      const std::string& inner_request_devtools_id,
+      const GURL& url,
+      const absl::optional<std::string>& bundle_request_devtools_id) override;
+  void OnSubresourceWebBundleInnerResponseError(
+      const std::string& inner_request_devtools_id,
+      const GURL& url,
+      const std::string& error_message,
+      const absl::optional<std::string>& bundle_request_devtools_id) override;
   void Clone(mojo::PendingReceiver<network::mojom::DevToolsObserver> listener)
       override;
 
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc
index dcaa4b4..dc6ac138f 100644
--- a/content/browser/devtools/protocol/network_handler.cc
+++ b/content/browser/devtools/protocol/network_handler.cc
@@ -2867,6 +2867,59 @@
       result.issued_token_count);
 }
 
+void NetworkHandler::OnSubresourceWebBundleMetadata(
+    const std::string& devtools_request_id,
+    const std::vector<GURL>& urls) {
+  if (!enabled_)
+    return;
+
+  auto new_urls = std::make_unique<protocol::Array<protocol::String>>();
+  for (const auto& url : urls) {
+    new_urls->push_back(url.spec());
+  }
+  frontend()->SubresourceWebBundleMetadataReceived(devtools_request_id,
+                                                   std::move(new_urls));
+}
+
+void NetworkHandler::OnSubresourceWebBundleMetadataError(
+    const std::string& devtools_request_id,
+    const std::string& error_message) {
+  if (!enabled_)
+    return;
+
+  frontend()->SubresourceWebBundleMetadataError(devtools_request_id,
+                                                error_message);
+}
+
+void NetworkHandler::OnSubresourceWebBundleInnerResponse(
+    const std::string& inner_request_devtools_id,
+    const GURL& url,
+    const absl::optional<std::string>& bundle_request_devtools_id) {
+  if (!enabled_)
+    return;
+
+  frontend()->SubresourceWebBundleInnerResponseParsed(
+      inner_request_devtools_id, url.spec(),
+      bundle_request_devtools_id.has_value()
+          ? Maybe<std::string>(*bundle_request_devtools_id)
+          : Maybe<std::string>());
+}
+
+void NetworkHandler::OnSubresourceWebBundleInnerResponseError(
+    const std::string& inner_request_devtools_id,
+    const GURL& url,
+    const std::string& error_message,
+    const absl::optional<std::string>& bundle_request_devtools_id) {
+  if (!enabled_)
+    return;
+
+  frontend()->SubresourceWebBundleInnerResponseError(
+      inner_request_devtools_id, url.spec(), error_message,
+      bundle_request_devtools_id.has_value()
+          ? Maybe<std::string>(*bundle_request_devtools_id)
+          : Maybe<std::string>());
+}
+
 String NetworkHandler::BuildPrivateNetworkRequestPolicy(
     network::mojom::PrivateNetworkRequestPolicy policy) {
   switch (policy) {
diff --git a/content/browser/devtools/protocol/network_handler.h b/content/browser/devtools/protocol/network_handler.h
index baf9b08..cfb2f1f 100644
--- a/content/browser/devtools/protocol/network_handler.h
+++ b/content/browser/devtools/protocol/network_handler.h
@@ -229,6 +229,20 @@
   void OnTrustTokenOperationDone(
       const std::string& devtools_request_id,
       const network::mojom::TrustTokenOperationResult& result);
+  void OnSubresourceWebBundleMetadata(const std::string& devtools_request_id,
+                                      const std::vector<GURL>& urls);
+  void OnSubresourceWebBundleMetadataError(
+      const std::string& devtools_request_id,
+      const std::string& error_message);
+  void OnSubresourceWebBundleInnerResponse(
+      const std::string& inner_request_devtools_id,
+      const GURL& url,
+      const absl::optional<std::string>& bundle_request_devtools_id);
+  void OnSubresourceWebBundleInnerResponseError(
+      const std::string& inner_request_devtools_id,
+      const GURL& url,
+      const std::string& error_message,
+      const absl::optional<std::string>& bundle_request_devtools_id);
 
   bool enabled() const { return enabled_; }
 
diff --git a/content/browser/devtools/protocol_config.json b/content/browser/devtools/protocol_config.json
index 4ac51e5..d9514199 100644
--- a/content/browser/devtools/protocol_config.json
+++ b/content/browser/devtools/protocol_config.json
@@ -54,7 +54,7 @@
             {
                 "domain": "Network",
                 "include": ["enable", "disable", "clearBrowserCache", "clearBrowserCookies", "getCookies", "getAllCookies", "deleteCookies", "setCookie", "setCookies", "setExtraHTTPHeaders", "canEmulateNetworkConditions", "emulateNetworkConditions", "setBypassServiceWorker", "setRequestInterception", "continueInterceptedRequest", "getResponseBodyForInterception", "setCacheDisabled", "takeResponseBodyForInterceptionAsStream", "getSecurityIsolationStatus", "loadNetworkResource", "setAcceptedEncodings", "clearAcceptedEncodingsOverride"],
-                "include_events": ["requestWillBeSent", "responseReceived", "loadingFinished", "loadingFailed", "requestIntercepted", "signedExchangeReceived", "requestWillBeSentExtraInfo", "responseReceivedExtraInfo", "trustTokenOperationDone"],
+                "include_events": ["requestWillBeSent", "responseReceived", "loadingFinished", "loadingFailed", "requestIntercepted", "signedExchangeReceived", "requestWillBeSentExtraInfo", "responseReceivedExtraInfo", "trustTokenOperationDone", "subresourceWebBundleMetadataReceived", "subresourceWebBundleMetadataError", "subresourceWebBundleInnerResponseParsed", "subresourceWebBundleInnerResponseError"],
                 "async": ["clearBrowserCookies", "clearBrowserCache", "getCookies", "getAllCookies", "deleteCookies", "setCookie", "setCookies", "continueInterceptedRequest", "getResponseBodyForInterception", "takeResponseBodyForInterceptionAsStream", "loadNetworkResource"]
             },
             {
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc
index d288bb3..2c21208 100644
--- a/content/browser/renderer_host/navigation_controller_impl.cc
+++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -2061,8 +2061,9 @@
       // (https://crbug.com/373041).
       // TODO(creis): For now, restrict this check to HTTP(S) origins, because
       // about:blank, file, and unique origins are more subtle to get right.
-      // We'll abstract out the relevant checks from IsURLSameDocumentNavigation
-      // and share them here.  See https://crbug.com/618104.
+      // We should use checks similar to RenderFrameHostImpl's
+      // CanCommitUrlAndOrigin on the main frame during subframe commits.
+      // See https://crbug.com/1209092.
       const GURL& dest_top_url = GetEntryAtIndex(entry_index)->GetURL();
       const GURL& current_top_url = GetLastCommittedEntry()->GetURL();
       if (current_top_url.SchemeIsHTTPOrHTTPS() &&
@@ -2113,70 +2114,6 @@
   return -1;
 }
 
-// There are two general cases where a navigation is "same-document":
-// 1. A fragment navigation, in which the url is kept the same except for the
-//    reference fragment.
-// 2. A history API navigation (pushState and replaceState). This case is
-//    always same-document, but the urls are not guaranteed to match excluding
-//    the fragment. The relevant spec allows pushState/replaceState to any URL
-//    on the same origin.
-// However, due to reloads, even identical urls are *not* guaranteed to be
-// same-document navigations, we have to trust the renderer almost entirely.
-// The one thing we do know is that cross-origin navigations will *never* be
-// same-document. Therefore, trust the renderer if the URLs are on the same
-// origin, and assume the renderer is malicious if a cross-origin navigation
-// claims to be same-document.
-//
-// TODO(creis): Clean up and simplify the about:blank and origin checks below,
-// which are likely redundant with each other.  Be careful about data URLs vs
-// about:blank, both of which are unique origins and thus not considered equal.
-bool NavigationControllerImpl::IsURLSameDocumentNavigation(
-    const GURL& url,
-    const url::Origin& origin,
-    bool renderer_says_same_document,
-    RenderFrameHost* rfh) {
-  RenderFrameHostImpl* rfhi = static_cast<RenderFrameHostImpl*>(rfh);
-  GURL last_committed_url;
-  // For cases that can't compare against the main frame's URL in the last
-  // committed entry, use the FrameTreeNode's current_url(). Note that it is
-  // possible to get same-document commits in the initial empty document when
-  // there is no last committed entry (e.g., about:blank#foo).
-  // TODO(creis): It would be simpler to always get the URL from the FTN rather
-  // than ever looking at GetLastCommittedEntry here. We're limiting the change
-  // in behavior for a merge and will clean it up further afterward.
-  if (rfh->GetParent() || !GetLastCommittedEntry()) {
-    // Use the FrameTreeNode's current_url and not rfh->GetLastCommittedURL(),
-    // which might be empty in a new RenderFrameHost after a process swap.
-    // Here, we care about the last committed URL in the FrameTreeNode,
-    // regardless of which process it is in.
-    last_committed_url = rfhi->frame_tree_node()->current_url();
-  } else {
-    last_committed_url = GetLastCommittedEntry()->GetURL();
-  }
-
-  auto prefs = rfhi->GetOrCreateWebPreferences();
-  const url::Origin& committed_origin =
-      rfhi->frame_tree_node()->current_origin();
-  bool is_same_origin = last_committed_url.is_empty() ||
-                        // TODO(japhet): We should only permit navigations
-                        // originating from about:blank to be in-page if the
-                        // about:blank is the first document that frame loaded.
-                        // We don't have sufficient information to identify
-                        // that case at the moment, so always allow about:blank
-                        // for now.
-                        last_committed_url == url::kAboutBlankURL ||
-                        last_committed_url.GetOrigin() == url.GetOrigin() ||
-                        committed_origin == origin ||
-                        !prefs.web_security_enabled ||
-                        (prefs.allow_universal_access_from_file_urls &&
-                         committed_origin.scheme() == url::kFileScheme);
-  if (!is_same_origin && renderer_says_same_document) {
-    bad_message::ReceivedBadMessage(rfh->GetProcess(),
-                                    bad_message::NC_IN_PAGE_NAVIGATION);
-  }
-  return is_same_origin && renderer_says_same_document;
-}
-
 void NavigationControllerImpl::CopyStateFrom(NavigationController* temp,
                                              bool needs_reload) {
   NavigationControllerImpl* source =
diff --git a/content/browser/renderer_host/navigation_controller_impl.h b/content/browser/renderer_host/navigation_controller_impl.h
index 06c50be..336dd425 100644
--- a/content/browser/renderer_host/navigation_controller_impl.h
+++ b/content/browser/renderer_host/navigation_controller_impl.h
@@ -262,27 +262,6 @@
   // so that we know to load URLs that were pending as "lazy" loads.
   void SetActive(bool is_active);
 
-  // Returns true if the given URL would be a same-document navigation (e.g., if
-  // the reference fragment is different, or after a pushState) from the last
-  // committed URL in the specified frame.
-  //
-  // Special note: if the URLs are the same, it does NOT automatically count as
-  // a same-document navigation. Neither does an input URL that has no ref, even
-  // if the rest is the same. This may seem weird, but when we're considering
-  // whether a navigation happened without loading anything, the same URL could
-  // be a reload, while only a different ref would be in-page (pages can't clear
-  // refs without reload, only change to "#" which we don't count as empty).
-  //
-  // The situation is made murkier by history.replaceState(), which could
-  // provide the same URL as part of a same-document navigation, not a reload.
-  // So we need to let the (untrustworthy) renderer resolve the ambiguity, but
-  // only when the URLs are on the same origin. We rely on |origin|, which
-  // matters in cases like about:blank that otherwise look cross-origin.
-  bool IsURLSameDocumentNavigation(const GURL& url,
-                                   const url::Origin& origin,
-                                   bool renderer_says_same_document,
-                                   RenderFrameHost* rfh);
-
   // Sets the SessionStorageNamespace for the given |partition_id|. This is
   // used during initialization of a new NavigationController to allow
   // pre-population of the SessionStorageNamespace objects. Session restore,
diff --git a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
index fd886a88..99834e68 100644
--- a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
+++ b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
@@ -2789,8 +2789,7 @@
     EXPECT_FALSE(capturer.did_replace_entry());
 
     // Check both NavigationHandle and LoadCommittedDetails for whether this was
-    // considered same-document, as these have diverged in the past (since only
-    // the latter is affected by IsURLSameDocumentNavigation).
+    // considered same-document, as these have diverged in the past.
     // See https://crbug.com/1193134.
     EXPECT_EQ(expect_same_document, capturer.is_same_document());
     EXPECT_EQ(expect_same_document,
@@ -3126,8 +3125,7 @@
     EXPECT_TRUE(controller.GetLastCommittedEntry());
 
     // Check both NavigationHandle and LoadCommittedDetails for whether this was
-    // considered same-document, as these have diverged in the past (since only
-    // the latter is affected by IsURLSameDocumentNavigation).
+    // considered same-document, as these have diverged in the past.
     // See https://crbug.com/1193134.
     EXPECT_TRUE(capturer.is_same_document());
     EXPECT_TRUE(load_details_observer.load_details().is_same_document);
diff --git a/content/browser/renderer_host/navigation_controller_impl_unittest.cc b/content/browser/renderer_host/navigation_controller_impl_unittest.cc
index 93f398b..62ae44ba 100644
--- a/content/browser/renderer_host/navigation_controller_impl_unittest.cc
+++ b/content/browser/renderer_host/navigation_controller_impl_unittest.cc
@@ -2300,6 +2300,7 @@
   params->did_create_new_entry = false;
   params->should_replace_current_entry = true;
   params->url = url2;
+  params->origin = url::Origin::Create(url2);
   params->referrer = blink::mojom::Referrer::New();
   params->transition = ui::PAGE_TRANSITION_LINK;
   params->should_update_history = true;
@@ -2898,149 +2899,6 @@
   }
 }
 
-// Tests that IsURLSameDocumentNavigation returns appropriate results.
-// Prevents regression for bug 1126349.
-TEST_F(NavigationControllerTest, IsSameDocumentNavigation) {
-  NavigationControllerImpl& controller = controller_impl();
-  const GURL url("http://www.google.com/home.html");
-
-  // If the renderer claims it performed an same-document navigation from
-  // about:blank, trust the renderer.
-  // This can happen when an iframe is created and populated via
-  // document.write(), then tries to perform a fragment navigation.
-  // TODO(japhet): We should only trust the renderer if the about:blank
-  // was the first document in the given frame, but we don't have enough
-  // information to identify that case currently.
-  // TODO(creis): Update this to verify that the origin of the about:blank page
-  // matches if the URL doesn't look same-origin.
-  const GURL blank_url(url::kAboutBlankURL);
-  const url::Origin blank_origin;
-  NavigationSimulator::NavigateAndCommitFromDocument(blank_url,
-                                                     main_test_rfh());
-  EXPECT_TRUE(controller.IsURLSameDocumentNavigation(
-      url, url::Origin::Create(url), true, main_test_rfh()));
-
-  // Navigate to URL with no refs.
-  NavigationSimulator::NavigateAndCommitFromDocument(url, main_test_rfh());
-
-  // Reloading the page is not a same-document navigation.
-  EXPECT_FALSE(controller.IsURLSameDocumentNavigation(
-      url, url::Origin::Create(url), false, main_test_rfh()));
-  const GURL other_url("http://www.google.com/add.html");
-  EXPECT_FALSE(controller.IsURLSameDocumentNavigation(
-      other_url, url::Origin::Create(other_url), false, main_test_rfh()));
-  const GURL url_with_ref("http://www.google.com/home.html#my_ref");
-  EXPECT_TRUE(controller.IsURLSameDocumentNavigation(
-      url_with_ref, url::Origin::Create(url_with_ref), true, main_test_rfh()));
-
-  // Navigate to URL with refs.
-  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url_with_ref);
-
-  // Reloading the page is not a same-document navigation.
-  EXPECT_FALSE(controller.IsURLSameDocumentNavigation(
-      url_with_ref, url::Origin::Create(url_with_ref), false, main_test_rfh()));
-  EXPECT_FALSE(controller.IsURLSameDocumentNavigation(
-      url, url::Origin::Create(url), false, main_test_rfh()));
-  EXPECT_FALSE(controller.IsURLSameDocumentNavigation(
-      other_url, url::Origin::Create(other_url), false, main_test_rfh()));
-  const GURL other_url_with_ref("http://www.google.com/home.html#my_other_ref");
-  EXPECT_TRUE(controller.IsURLSameDocumentNavigation(
-      other_url_with_ref, url::Origin::Create(other_url_with_ref), true,
-      main_test_rfh()));
-
-  // Going to the same url again will be considered same-document navigation
-  // if the renderer says it is even if the navigation type isn't SAME_DOCUMENT.
-  EXPECT_TRUE(controller.IsURLSameDocumentNavigation(
-      url_with_ref, url::Origin::Create(url_with_ref), true, main_test_rfh()));
-
-  // Going back to the non ref url will be considered same-document navigation
-  // if the navigation type is SAME_DOCUMENT.
-  EXPECT_TRUE(controller.IsURLSameDocumentNavigation(
-      url, url::Origin::Create(url), true, main_test_rfh()));
-
-  // If the renderer says this is a same-origin same-document navigation,
-  // believe it. This is the pushState/replaceState case.
-  EXPECT_TRUE(controller.IsURLSameDocumentNavigation(
-      other_url, url::Origin::Create(other_url), true, main_test_rfh()));
-
-  // Don't believe the renderer if it claims a cross-origin navigation is
-  // a same-document navigation.
-  const GURL different_origin_url("http://www.example.com");
-  MockRenderProcessHost* rph = main_test_rfh()->GetProcess();
-  EXPECT_EQ(0, rph->bad_msg_count());
-  EXPECT_FALSE(controller.IsURLSameDocumentNavigation(
-      different_origin_url, url::Origin::Create(different_origin_url), true,
-      main_test_rfh()));
-  EXPECT_EQ(1, rph->bad_msg_count());
-}
-
-// Tests that IsURLSameDocumentNavigation behaves properly with the
-// allow_universal_access_from_file_urls flag.
-TEST_F(NavigationControllerTest,
-       IsSameDocumentNavigationWithUniversalFileAccess) {
-  NavigationControllerImpl& controller = controller_impl();
-
-  // Test allow_universal_access_from_file_urls flag.
-  const GURL different_origin_url("http://www.example.com");
-  MockRenderProcessHost* rph = main_test_rfh()->GetProcess();
-  auto prefs = controller.GetWebContents()->GetOrCreateWebPreferences();
-  prefs.allow_universal_access_from_file_urls = true;
-  controller.GetWebContents()->SetWebPreferences(prefs);
-  prefs = controller.GetWebContents()->GetOrCreateWebPreferences();
-  EXPECT_TRUE(prefs.allow_universal_access_from_file_urls);
-
-  // Allow same-document navigation to be cross-origin if existing URL is file
-  // scheme.
-  const GURL file_url("file:///foo/index.html");
-  const url::Origin file_origin = url::Origin::Create(file_url);
-  NavigationSimulator::NavigateAndCommitFromDocument(file_url, main_test_rfh());
-  EXPECT_TRUE(
-      file_origin.IsSameOriginWith(main_test_rfh()->GetLastCommittedOrigin()));
-  EXPECT_EQ(0, rph->bad_msg_count());
-  EXPECT_TRUE(controller.IsURLSameDocumentNavigation(
-      different_origin_url, url::Origin::Create(different_origin_url), true,
-      main_test_rfh()));
-  EXPECT_EQ(0, rph->bad_msg_count());
-
-  // Doing a replaceState to a cross-origin URL is thus allowed.
-  auto params = mojom::DidCommitProvisionalLoadParams::New();
-  params->did_create_new_entry = false;
-  params->url = different_origin_url;
-  params->referrer = blink::mojom::Referrer::New();
-  params->origin = file_origin;
-  params->transition = ui::PAGE_TRANSITION_LINK;
-  params->gesture = NavigationGestureUser;
-  params->page_state = blink::PageState::CreateFromURL(different_origin_url);
-  params->method = "GET";
-  params->post_id = -1;
-  params->should_update_history = true;
-  main_test_rfh()->SendRendererInitiatedNavigationRequest(different_origin_url,
-                                                          false);
-  main_test_rfh()->PrepareForCommit();
-  contents()->GetMainFrame()->SendNavigateWithParams(
-      std::move(params), true /* was_within_same_document */);
-
-  // At this point, we should still consider the current origin to be file://,
-  // so that a file URL would still be a same-document navigation.  See
-  // https://crbug.com/553418.
-  EXPECT_TRUE(
-      file_origin.IsSameOriginWith(main_test_rfh()->GetLastCommittedOrigin()));
-  EXPECT_TRUE(controller.IsURLSameDocumentNavigation(
-      file_url, url::Origin::Create(file_url), true, main_test_rfh()));
-  EXPECT_EQ(0, rph->bad_msg_count());
-
-  // Don't honor allow_universal_access_from_file_urls if actual URL is
-  // not file scheme.
-  const GURL url("http://www.google.com/home.html");
-  TestRenderFrameHost* new_rfh = static_cast<TestRenderFrameHost*>(
-      NavigationSimulator::NavigateAndCommitFromDocument(url, main_test_rfh()));
-  rph = new_rfh->GetProcess();
-  EXPECT_FALSE(controller.IsURLSameDocumentNavigation(
-      different_origin_url, url::Origin::Create(different_origin_url), true,
-      new_rfh));
-  EXPECT_EQ(1, rph->bad_msg_count());
-}
-
 // This test verifies that a subframe navigation that would qualify as
 // same-document within the main frame, given its URL, has no impact on the
 // main frame.
diff --git a/content/browser/renderer_host/navigator.cc b/content/browser/renderer_host/navigator.cc
index 62eb048d..73fb9cc 100644
--- a/content/browser/renderer_host/navigator.cc
+++ b/content/browser/renderer_host/navigator.cc
@@ -358,15 +358,14 @@
   base::WeakPtr<RenderFrameHostImpl> old_frame_host =
       frame_tree_node->render_manager()->current_frame_host()->GetWeakPtr();
 
-  bool is_same_document_navigation = controller_.IsURLSameDocumentNavigation(
-      params.url, params.origin, was_within_same_document, render_frame_host);
   // If a frame claims the navigation was same-document, it must be the current
   // frame, not a pending one.
-  if (is_same_document_navigation &&
-      render_frame_host != old_frame_host.get()) {
+  // TODO(creis): This check should be moved to RenderFrameHostImpl, allowing an
+  // early return.  See https://crbug.com/1209097.
+  if (was_within_same_document && render_frame_host != old_frame_host.get()) {
     bad_message::ReceivedBadMessage(render_frame_host->GetProcess(),
                                     bad_message::NI_IN_PAGE_NAVIGATION);
-    is_same_document_navigation = false;
+    was_within_same_document = false;
   }
   // At this point we have already chosen a SiteInstance for this navigation, so
   // set |origin_isolation_request| to kNone in the conversion to UrlInfo
@@ -387,7 +386,7 @@
   if (ui::PageTransitionIsMainFrame(params.transition)) {
     if (delegate_) {
       // Run tasks that must execute just before the commit.
-      delegate_->DidNavigateMainFramePreCommit(is_same_document_navigation);
+      delegate_->DidNavigateMainFramePreCommit(was_within_same_document);
     }
   }
 
@@ -398,7 +397,7 @@
   // frame's origin.  See https://crbug.com/825283.
   frame_tree_node->render_manager()->DidNavigateFrame(
       render_frame_host, params.gesture == NavigationGestureUser,
-      is_same_document_navigation,
+      was_within_same_document,
       navigation_request->coop_status()
           .require_browsing_instance_swap() /* clear_proxies_on_commit */,
       navigation_request->commit_params().frame_policy);
@@ -416,7 +415,7 @@
   bool previous_document_was_activated =
       frame_tree->root()->HasStickyUserActivation();
 
-  if (!is_same_document_navigation) {
+  if (!was_within_same_document) {
     // Navigating to a new location means a new, fresh set of http headers
     // and/or <meta> elements - we need to reset Permissions Policy.
     frame_tree_node->ResetForNavigation();
@@ -453,9 +452,9 @@
   LoadCommittedDetails details;
   base::TimeTicks start = base::TimeTicks::Now();
   bool did_navigate = controller_.RendererDidNavigate(
-      render_frame_host, params, &details, is_same_document_navigation,
+      render_frame_host, params, &details, was_within_same_document,
       previous_document_was_activated, navigation_request.get());
-  if (!is_same_document_navigation) {
+  if (!was_within_same_document) {
     base::UmaHistogramTimes(
         base::StrCat(
             {"Navigation.RendererDidNavigateTime.",
@@ -482,24 +481,10 @@
 
   // Navigations that activate an existing bfcached or prerendered document do
   // not create a new document.
-  //
-  // |was_within_same_document| (controlled by the renderer) also needs to be
-  // considered: in some cases, the browser and renderer can disagree. While
-  // this is usually a bad message kill, there are some situations where this
-  // can legitimately happen. When a new frame is created (e.g. with
-  // <iframe src="...">), the initial about:blank document doesn't have a
-  // corresponding entry in the browser process. As a result, the browser
-  // process incorrectly determines that the navigation is cross-document when
-  // in reality it's same-document.
-  //
-  // TODO(crbug/1099264): Remove |was_within_same_document| from this logic
-  // once all same-document navigations have a NavigationEntry. Once this
-  // happens there should be no cases where the browser and renderer
-  // legitimately disagree as described above.
   bool did_create_new_document =
       !navigation_request->IsServedFromBackForwardCache() &&
       !navigation_request->IsPrerenderedPageActivation() &&
-      !is_same_document_navigation && !was_within_same_document;
+      !was_within_same_document;
 
   // Store some information for recording WebPlatform security metrics. These
   // metrics depends on information present in the NavigationRequest. However
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 9b6ebbfd..2a94194 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -6453,13 +6453,11 @@
 
 CanCommitStatus RenderFrameHostImpl::CanCommitOriginAndUrl(
     const url::Origin& origin,
-    const GURL& url) {
-  // If the --disable-web-security flag is specified, all bets are off and the
-  // renderer process can send any origin it wishes.
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kDisableWebSecurity)) {
-    return CanCommitStatus::CAN_COMMIT_ORIGIN_AND_URL;
-  }
+    const GURL& url,
+    bool is_same_document_navigation) {
+  // Note that callers are responsible for avoiding this function in modes that
+  // can bypass these rules, such as --disable-web-security or certain Android
+  // WebView features like universal access from file URLs.
 
   // Renderer-debug URLs can never be committed.
   if (blink::IsRendererDebugURL(url)) {
@@ -6499,6 +6497,14 @@
     }
   }
 
+  // Same-document navigations cannot change origins, as long as these checks
+  // aren't being bypassed in unusual modes. This check must be after the MHTML
+  // check, as shown by NavigationMhtmlBrowserTest.IframeAboutBlankNotFound.
+  if (is_same_document_navigation && origin != GetLastCommittedOrigin()) {
+    LogCanCommitOriginAndUrlFailureReason("cross_origin_same_document");
+    return CanCommitStatus::CANNOT_COMMIT_ORIGIN;
+  }
+
   // Give the client a chance to disallow URLs from committing.
   if (!GetContentClient()->browser()->CanCommitURL(GetProcess(), url)) {
     LogCanCommitOriginAndUrlFailureReason(
@@ -6506,6 +6512,7 @@
     return CanCommitStatus::CANNOT_COMMIT_URL;
   }
 
+  // Check with ChildProcessSecurityPolicy, which enforces Site Isolation, etc.
   auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
   const CanCommitStatus can_commit_status = policy->CanCommitOriginAndUrl(
       GetProcess()->GetID(), GetSiteInstance()->GetIsolationContext(), origin,
@@ -9219,6 +9226,12 @@
       bypass_checks_for_file_scheme = true;
   }
 
+  // If the --disable-web-security flag is specified, all bets are off and the
+  // renderer process can send any origin it wishes.
+  bool bypass_checks_for_disable_web_security =
+      base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kDisableWebSecurity);
+
   // WebView's loadDataWithBaseURL API is allowed to bypass normal commit
   // checks because it is allowed to commit anything into its unlocked process
   // and its data: URL and non-opaque origin would fail the normal commit
@@ -9240,11 +9253,12 @@
   }
 
   if (!bypass_checks_for_error_page && !bypass_checks_for_file_scheme &&
-      !bypass_checks_for_webview) {
+      !bypass_checks_for_disable_web_security && !bypass_checks_for_webview) {
     // Attempts to commit certain off-limits URL should be caught more strictly
     // than our FilterURL checks.  If a renderer violates this policy, it
     // should be killed.
-    switch (CanCommitOriginAndUrl(params->origin, params->url)) {
+    switch (CanCommitOriginAndUrl(params->origin, params->url,
+                                  is_same_document_navigation)) {
       case CanCommitStatus::CAN_COMMIT_ORIGIN_AND_URL:
         // The origin and URL are safe to commit.
         break;
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h
index 622c5697..d3ce59a 100644
--- a/content/browser/renderer_host/render_frame_host_impl.h
+++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -2425,7 +2425,8 @@
   // RenderProcessHost::FilterURL, since it will be used to kill processes that
   // commit unauthorized origins.
   CanCommitStatus CanCommitOriginAndUrl(const url::Origin& origin,
-                                        const GURL& url);
+                                        const GURL& url,
+                                        bool is_same_document_navigation);
 
   // Asserts that the given RenderFrameHostImpl is part of the same browser
   // context (and crashes if not), then returns whether the given frame is
diff --git a/content/browser/renderer_host/render_frame_host_manager_browsertest.cc b/content/browser/renderer_host/render_frame_host_manager_browsertest.cc
index f1c520a..ae62c82 100644
--- a/content/browser/renderer_host/render_frame_host_manager_browsertest.cc
+++ b/content/browser/renderer_host/render_frame_host_manager_browsertest.cc
@@ -3779,12 +3779,27 @@
   web_contents->SetWebPreferences(prefs);
 
   GURL file_url = GetTestUrl("", "title1.html");
+  ASSERT_TRUE(file_url.SchemeIsFile());
   ASSERT_TRUE(NavigateToURL(shell(), file_url));
   EXPECT_EQ(1, web_contents->GetController().GetEntryCount());
-  EXPECT_TRUE(ExecuteScript(
-      root, "window.history.pushState({}, '', 'https://chromium.org');"));
+  EXPECT_TRUE(
+      ExecJs(root, "history.pushState({}, '', 'https://chromium.org');"));
+  ASSERT_TRUE(web_contents->GetMainFrame()->IsRenderFrameLive());
   EXPECT_EQ(2, web_contents->GetController().GetEntryCount());
-  EXPECT_TRUE(web_contents->GetMainFrame()->IsRenderFrameLive());
+
+  // At this point, we should still consider the current origin to be file://,
+  // so that subsequent web or file URLs would still be legal for same-document
+  // navigations.  See https://crbug.com/553418.
+  const url::Origin file_origin = url::Origin::Create(file_url);
+  EXPECT_TRUE(file_origin.IsSameOriginWith(
+      web_contents->GetMainFrame()->GetLastCommittedOrigin()));
+  EXPECT_TRUE(ExecJs(root, "history.pushState({}, '', 'https://foo.com');"));
+  ASSERT_TRUE(web_contents->GetMainFrame()->IsRenderFrameLive());
+  EXPECT_EQ(3, web_contents->GetController().GetEntryCount());
+  EXPECT_TRUE(
+      ExecJs(root, JsReplace("history.pushState({}, '', $1);", file_url)));
+  ASSERT_TRUE(web_contents->GetMainFrame()->IsRenderFrameLive());
+  EXPECT_EQ(4, web_contents->GetController().GetEntryCount());
 }
 
 // Ensure that navigating back from a sad tab to an existing process works
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index b38b11e..ecd1a27 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -121,6 +121,7 @@
 #include "third_party/blink/public/mojom/page/drag.mojom.h"
 #include "ui/base/clipboard/clipboard_constants.h"
 #include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
+#include "ui/base/ui_base_features.h"
 #include "ui/base/ui_base_switches.h"
 #include "ui/display/display_switches.h"
 #include "ui/display/screen.h"
@@ -323,6 +324,37 @@
   }
 };
 
+std::u16string GetWrappedTooltipText(
+    const std::u16string& tooltip_text,
+    base::i18n::TextDirection text_direction_hint) {
+  // First, add directionality marks around tooltip text if necessary.
+  // A naive solution would be to simply always wrap the text. However, on
+  // windows, Unicode directional embedding characters can't be displayed on
+  // systems that lack RTL fonts and are instead displayed as empty squares.
+  //
+  // To get around this we only wrap the string when we deem it necessary i.e.
+  // when the locale direction is different than the tooltip direction hint.
+  //
+  // Currently, we use element's directionality as the tooltip direction hint.
+  // An alternate solution would be to set the overall directionality based on
+  // trying to detect the directionality from the tooltip text rather than the
+  // element direction.  One could argue that would be a preferable solution
+  // but we use the current approach to match Fx & IE's behavior.
+  std::u16string wrapped_tooltip_text = tooltip_text;
+  if (!tooltip_text.empty()) {
+    if (text_direction_hint == base::i18n::LEFT_TO_RIGHT) {
+      // Force the tooltip to have LTR directionality.
+      wrapped_tooltip_text =
+          base::i18n::GetDisplayStringInLTRDirectionality(wrapped_tooltip_text);
+    } else if (text_direction_hint == base::i18n::RIGHT_TO_LEFT &&
+               !base::i18n::IsRTL()) {
+      // Force the tooltip to have RTL directionality.
+      base::i18n::WrapStringWithRTLFormatting(&wrapped_tooltip_text);
+    }
+  }
+  return wrapped_tooltip_text;
+}
+
 base::LazyInstance<UnboundWidgetInputHandler>::Leaky g_unbound_input_handler =
     LAZY_INSTANCE_INITIALIZER;
 
@@ -2480,32 +2512,19 @@
   if (!GetView())
     return;
 
-  // First, add directionality marks around tooltip text if necessary.
-  // A naive solution would be to simply always wrap the text. However, on
-  // windows, Unicode directional embedding characters can't be displayed on
-  // systems that lack RTL fonts and are instead displayed as empty squares.
-  //
-  // To get around this we only wrap the string when we deem it necessary i.e.
-  // when the locale direction is different than the tooltip direction hint.
-  //
-  // Currently, we use element's directionality as the tooltip direction hint.
-  // An alternate solution would be to set the overall directionality based on
-  // trying to detect the directionality from the tooltip text rather than the
-  // element direction.  One could argue that would be a preferable solution
-  // but we use the current approach to match Fx & IE's behavior.
-  std::u16string wrapped_tooltip_text = tooltip_text;
-  if (!tooltip_text.empty()) {
-    if (text_direction_hint == base::i18n::LEFT_TO_RIGHT) {
-      // Force the tooltip to have LTR directionality.
-      wrapped_tooltip_text =
-          base::i18n::GetDisplayStringInLTRDirectionality(wrapped_tooltip_text);
-    } else if (text_direction_hint == base::i18n::RIGHT_TO_LEFT &&
-               !base::i18n::IsRTL()) {
-      // Force the tooltip to have RTL directionality.
-      base::i18n::WrapStringWithRTLFormatting(&wrapped_tooltip_text);
-    }
-  }
-  view_->UpdateTooltipUnderCursor(wrapped_tooltip_text);
+  view_->UpdateTooltipUnderCursor(
+      GetWrappedTooltipText(tooltip_text, text_direction_hint));
+}
+
+void RenderWidgetHostImpl::UpdateTooltipFromKeyboard(
+    const std::u16string& tooltip_text,
+    base::i18n::TextDirection text_direction_hint,
+    const gfx::Rect& bounds) {
+  if (!GetView())
+    return;
+
+  view_->UpdateTooltipFromKeyboard(
+      GetWrappedTooltipText(tooltip_text, text_direction_hint), bounds);
 }
 
 void RenderWidgetHostImpl::OnUpdateScreenRectsAck() {
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index ce8aa5b..5116122 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -306,6 +306,9 @@
   void UpdateTooltipUnderCursor(
       const std::u16string& tooltip_text,
       base::i18n::TextDirection text_direction_hint) override;
+  void UpdateTooltipFromKeyboard(const std::u16string& tooltip_text,
+                                 base::i18n::TextDirection text_direction_hint,
+                                 const gfx::Rect& bounds) override;
   void TextInputStateChanged(ui::mojom::TextInputStatePtr state) override;
   void SelectionBoundsChanged(const gfx::Rect& anchor_rect,
                               base::i18n::TextDirection anchor_dir,
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index e222138..d7887ac 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -1083,6 +1083,12 @@
   // Tooltips don't make sense on Android.
 }
 
+void RenderWidgetHostViewAndroid::UpdateTooltipFromKeyboard(
+    const std::u16string& tooltip_text,
+    const gfx::Rect& bounds) {
+  // Tooltips don't makes sense on Android.
+}
+
 void RenderWidgetHostViewAndroid::UpdateBackgroundColor() {
   DCHECK(RenderWidgetHostViewBase::GetBackgroundColor());
 
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index e15d846..58d8083 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -139,6 +139,8 @@
   void RenderProcessGone() override;
   void Destroy() override;
   void UpdateTooltipUnderCursor(const std::u16string& tooltip_text) override;
+  void UpdateTooltipFromKeyboard(const std::u16string& tooltip_text,
+                                 const gfx::Rect& bounds) override;
   void TransformPointToRootSurface(gfx::PointF* point) override;
   gfx::Rect GetBoundsInRootWindow() override;
   void ProcessAckedTouchEvent(
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index b8ae3c5..d8365d0 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -765,7 +765,8 @@
     const std::u16string& tooltip_text) {
   SetTooltipText(tooltip_text);
 
-  auto* tooltip_client = wm::GetTooltipClient(window_->GetRootWindow());
+  wm::TooltipClient* tooltip_client =
+      wm::GetTooltipClient(window_->GetRootWindow());
   if (tooltip_client) {
     // Content tooltips should be visible indefinitely.
     tooltip_client->SetHideTooltipTimeout(window_, {});
@@ -773,6 +774,20 @@
   }
 }
 
+void RenderWidgetHostViewAura::UpdateTooltipFromKeyboard(
+    const std::u16string& tooltip_text,
+    const gfx::Rect& bounds) {
+  SetTooltipText(tooltip_text);
+
+  wm::TooltipClient* tooltip_client =
+      wm::GetTooltipClient(window_->GetRootWindow());
+  if (tooltip_client) {
+    // Content tooltips should be visible indefinitely.
+    tooltip_client->SetHideTooltipTimeout(window_, {});
+    tooltip_client->UpdateTooltipFromKeyboard(bounds, window_);
+  }
+}
+
 uint32_t RenderWidgetHostViewAura::GetCaptureSequenceNumber() const {
   return latest_capture_sequence_number_;
 }
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index fa9154a..b881bdc 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -131,6 +131,8 @@
   void Destroy() override;
   void UpdateTooltipUnderCursor(const std::u16string& tooltip_text) override;
   void UpdateTooltip(const std::u16string& tooltip_text) override;
+  void UpdateTooltipFromKeyboard(const std::u16string& tooltip_text,
+                                 const gfx::Rect& bounds) override;
   uint32_t GetCaptureSequenceNumber() const override;
   bool IsSurfaceAvailableForCopy() override;
   void CopyFromSurface(
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h
index 1bfa563..9e207025 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -455,6 +455,13 @@
   // An empty string will clear a visible tooltip.
   virtual void UpdateTooltip(const std::u16string& tooltip_text) {}
 
+  // Updates the tooltip text and its position and displays the requested
+  // tooltip on the screen. The |bounds| parameter corresponds to the bounds of
+  // the renderer-side element (in widget-relative DIPS) on which the tooltip
+  // should appear to be anchored.
+  virtual void UpdateTooltipFromKeyboard(const std::u16string& tooltip_text,
+                                         const gfx::Rect& bounds) {}
+
   // Transforms |point| to be in the coordinate space of browser compositor's
   // surface. This is in DIP.
   virtual void TransformPointToRootSurface(gfx::PointF* point);
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
index df0bae1..14a83f94 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -417,6 +417,23 @@
     root_view->UpdateTooltip(tooltip_text);
 }
 
+void RenderWidgetHostViewChildFrame::UpdateTooltipFromKeyboard(
+    const std::u16string& tooltip_text,
+    const gfx::Rect& bounds) {
+  if (!frame_connector_)
+    return;
+
+  auto* root_view = frame_connector_->GetRootRenderWidgetHostView();
+  if (!root_view)
+    return;
+
+  // TODO(bebeaudr): Keyboard-triggered tooltips are not positioned correctly
+  // when set for an element in an OOPIF. See https://crbug.com/1210269.
+  gfx::Rect adjusted_bounds(TransformPointToRootCoordSpace(bounds.origin()),
+                            bounds.size());
+  root_view->UpdateTooltipFromKeyboard(tooltip_text, adjusted_bounds);
+}
+
 RenderWidgetHostViewBase* RenderWidgetHostViewChildFrame::GetParentView() {
   if (!frame_connector_)
     return nullptr;
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.h b/content/browser/renderer_host/render_widget_host_view_child_frame.h
index 0c5ad30..a32e3e0 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.h
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.h
@@ -107,6 +107,8 @@
   void RenderProcessGone() override;
   void Destroy() override;
   void UpdateTooltipUnderCursor(const std::u16string& tooltip_text) override;
+  void UpdateTooltipFromKeyboard(const std::u16string& tooltip_text,
+                                 const gfx::Rect& bounds) override;
   void GestureEventAck(const blink::WebGestureEvent& event,
                        blink::mojom::InputEventResultState ack_result) override;
   // Since the URL of content rendered by this class is not displayed in
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index d2a187e5..25f748e 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -485,6 +485,87 @@
   EXPECT_EQ(bad_message::RFH_INVALID_ORIGIN_ON_COMMIT, kill_waiter.Wait());
 }
 
+// Test that same-document navigations cannot go cross-origin (even within the
+// same site).
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
+                       CrossOriginSameDocumentCommit) {
+  GURL start_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), start_url));
+
+  // Do a same-document navigation to a cross-origin URL/Origin (which match
+  // each other, unlike the MismatchedOriginOnCommit), using an interceptor that
+  // replaces the origin and URL. This intentionally uses a cross-origin but
+  // same-site destination, to avoid failing Site Isolation checks.
+  GURL dest_url(embedded_test_server()->GetURL("bar.foo.com", "/title2.html"));
+  PwnCommitIPC(shell()->web_contents(), start_url, dest_url,
+               url::Origin::Create(dest_url));
+  RenderProcessHostBadIpcMessageWaiter kill_waiter(
+      shell()->web_contents()->GetMainFrame()->GetProcess());
+  // ExecJs will sometimes finish before the renderer gets killed, so we must
+  // ignore the result.
+  ignore_result(ExecJs(shell()->web_contents()->GetMainFrame(),
+                       "history.pushState({}, '', location.href);"));
+  EXPECT_EQ(bad_message::RFH_INVALID_ORIGIN_ON_COMMIT, kill_waiter.Wait());
+}
+
+// Test that same-document navigations cannot go cross-origin from about:blank
+// (even within the same site). Uses a subframe to inherit an existing origin.
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
+                       CrossOriginSameDocumentCommitFromAboutBlank) {
+  GURL start_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), start_url));
+
+  // Create an about:blank iframe that inherits the origin.
+  RenderFrameHost* subframe =
+      CreateSubframe(static_cast<WebContentsImpl*>(shell()->web_contents()),
+                     "child1", GURL(), false /* wait_for_navigation */);
+  EXPECT_EQ(url::Origin::Create(start_url), subframe->GetLastCommittedOrigin());
+
+  // Do a same-document navigation to another about:blank URL, but using a
+  // different origin. This intentionally uses a cross-origin but same-site
+  // origin to avoid triggering Site Isolation checks.
+  GURL blank_url("about:blank#foo");
+  GURL fake_url(embedded_test_server()->GetURL("bar.foo.com", "/"));
+  PwnCommitIPC(shell()->web_contents(), blank_url, blank_url,
+               url::Origin::Create(fake_url));
+  RenderProcessHostBadIpcMessageWaiter kill_waiter(subframe->GetProcess());
+  // ExecJs will sometimes finish before the renderer gets killed, so we must
+  // ignore the result.
+  ignore_result(ExecJs(subframe, "location.hash='foo';"));
+  EXPECT_EQ(bad_message::RFH_INVALID_ORIGIN_ON_COMMIT, kill_waiter.Wait());
+}
+
+// Test that same-document navigations cannot go cross-origin (even within the
+// same site), in the case that allow_universal_access_from_file_urls is enabled
+// but the last committed origin is not a file URL.  See also
+// RenderFrameHostManagerTest.EnsureUniversalAccessFromFileSchemeSucceeds for
+// the intended case that file URLs are allowed to go cross-origin.
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
+                       CrossOriginSameDocumentCommitUniversalAccessNonFile) {
+  auto prefs = shell()->web_contents()->GetOrCreateWebPreferences();
+  prefs.allow_universal_access_from_file_urls = true;
+  shell()->web_contents()->SetWebPreferences(prefs);
+
+  GURL start_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), start_url));
+
+  // Do a same-document navigation to a cross-origin URL, using an interceptor
+  // that replaces the URL but not the origin (to simulate the universal access
+  // case, but for a non-file committed origin). This intentionally uses a
+  // cross-origin but same-site destination, to avoid failing Site Isolation
+  // checks.
+  GURL dest_url(embedded_test_server()->GetURL("bar.foo.com", "/title2.html"));
+  PwnCommitIPC(shell()->web_contents(), start_url, dest_url,
+               url::Origin::Create(start_url));
+  RenderProcessHostBadIpcMessageWaiter kill_waiter(
+      shell()->web_contents()->GetMainFrame()->GetProcess());
+  // ExecJs will sometimes finish before the renderer gets killed, so we must
+  // ignore the result.
+  ignore_result(ExecJs(shell()->web_contents()->GetMainFrame(),
+                       "history.pushState({}, '', location.href);"));
+  EXPECT_EQ(bad_message::RFH_INVALID_ORIGIN_ON_COMMIT, kill_waiter.Wait());
+}
+
 namespace {
 
 // Interceptor that replaces |interface_params| with the specified
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 3fe7849..54f4424 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -4432,7 +4432,7 @@
   RenderFrameHost* source_render_frame_host = RenderFrameHost::FromID(
       params.source_render_process_id, params.source_render_frame_id);
 
-  // Prevent frams that are not active from opening new windows, tabs, popups,
+  // Prevent frames that are not active from opening new windows, tabs, popups,
   // etc.
   if (params.disposition != WindowOpenDisposition::CURRENT_TAB &&
       source_render_frame_host && !source_render_frame_host->IsCurrent()) {
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
index 84d1ce1..fbd1220d 100644
--- a/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -7083,7 +7083,7 @@
       ->ReplaceDefaultDiscoveryFactoryForTesting(
           std::make_unique<DiscoveryFactory>(std::move(discovery)));
 
-  const std::vector<uint8_t> contact_id = {1, 2, 3};
+  const std::vector<uint8_t> contact_id(/*count=*/200, /*value=*/1);
   std::unique_ptr<device::cablev2::authenticator::Transaction> transaction =
       device::cablev2::authenticator::TransactFromQRCode(
           device::cablev2::authenticator::NewMockPlatform(
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 8f744fc1..b9ab033 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -339,7 +339,6 @@
       runtimeFeatureNameToChromiumFeatureMapping[] = {
           {"AllowContentInitiatedDataUrlNavigations",
            features::kAllowContentInitiatedDataUrlNavigations},
-          {"AutofillShadowDOM", blink::features::kAutofillShadowDOM},
           {"AndroidDownloadableFontsMatching",
            features::kAndroidDownloadableFontsMatching},
           {"BlockCredentialedSubresources",
diff --git a/content/public/test/fake_render_widget_host.cc b/content/public/test/fake_render_widget_host.cc
index 4f26160..5fd79f5 100644
--- a/content/public/test/fake_render_widget_host.cc
+++ b/content/public/test/fake_render_widget_host.cc
@@ -52,6 +52,11 @@
     const std::u16string& tooltip_text,
     base::i18n::TextDirection text_direction_hint) {}
 
+void FakeRenderWidgetHost::UpdateTooltipFromKeyboard(
+    const std::u16string& tooltip_text,
+    base::i18n::TextDirection text_direction_hint,
+    const gfx::Rect& bounds) {}
+
 void FakeRenderWidgetHost::TextInputStateChanged(
     ui::mojom::TextInputStatePtr state) {}
 
diff --git a/content/public/test/fake_render_widget_host.h b/content/public/test/fake_render_widget_host.h
index 6d62b5b..6b1f4d3 100644
--- a/content/public/test/fake_render_widget_host.h
+++ b/content/public/test/fake_render_widget_host.h
@@ -58,6 +58,9 @@
   void UpdateTooltipUnderCursor(
       const std::u16string& tooltip_text,
       base::i18n::TextDirection text_direction_hint) override;
+  void UpdateTooltipFromKeyboard(const std::u16string& tooltip_text,
+                                 base::i18n::TextDirection text_direction_hint,
+                                 const gfx::Rect& bounds) override;
   void TextInputStateChanged(ui::mojom::TextInputStatePtr state) override;
   void SelectionBoundsChanged(const gfx::Rect& anchor_rect,
                               base::i18n::TextDirection anchor_dir,
diff --git a/content/renderer/render_thread_impl_browsertest.cc b/content/renderer/render_thread_impl_browsertest.cc
index 9d8369a0..c97e997 100644
--- a/content/renderer/render_thread_impl_browsertest.cc
+++ b/content/renderer/render_thread_impl_browsertest.cc
@@ -164,6 +164,7 @@
         ChildProcessHost::Create(this, ChildProcessHost::IpcMode::kNormal);
     process_host_->CreateChannelMojo();
 
+    CHECK(!process_.get());
     process_ = std::make_unique<RenderProcess>();
     test_task_counter_ = base::MakeRefCounted<TestTaskCounter>();
 
@@ -205,14 +206,13 @@
   }
 
   void TearDown() override {
-    if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-            switches::kSingleProcessTests)) {
-      // In a single-process mode, we need to avoid destructing process_
-      // because it will call _exit(0) and kill the process before the browser
-      // side is ready to exit.
-      ANNOTATE_LEAKING_OBJECT_PTR(process_.get());
-      process_.release();
-    }
+    CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
+        switches::kSingleProcessTests));
+    // In a single-process mode, we need to avoid destructing `process_`
+    // because it will call _exit(0) and kill the process before the browser
+    // side is ready to exit.
+    ANNOTATE_LEAKING_OBJECT_PTR(process_.get());
+    process_.release();
   }
 
   // ChildProcessHostDelegate implementation:
diff --git a/content/test/data/accessibility/css/alt-text-expected-blink.txt b/content/test/data/accessibility/css/alt-text-expected-blink.txt
index b412012..d8b9c9e7 100644
--- a/content/test/data/accessibility/css/alt-text-expected-blink.txt
+++ b/content/test/data/accessibility/css/alt-text-expected-blink.txt
@@ -6,36 +6,50 @@
 ++++++++++staticText name='item1item2'
 ++++++++++++inlineTextBox name='item1item2'
 ++++++++++image
+++++++++staticText name=' '
+++++++++++inlineTextBox name=' '
 ++++++++genericContainer
 ++++++++++staticText name='Some Text'
 ++++++++++++inlineTextBox name='Some Text'
 ++++++genericContainer
 ++++++++staticText name='code'
+++++++++staticText name=' '
+++++++++++inlineTextBox name=' '
 ++++++++genericContainer
 ++++++++++staticText name='Some Text'
 ++++++++++++inlineTextBox name='Some Text'
 ++++++genericContainer
 ++++++++staticText ignored
+++++++++staticText name=' '
+++++++++++inlineTextBox name=' '
 ++++++++genericContainer
 ++++++++++staticText name='Some Text'
 ++++++++++++inlineTextBox name='Some Text'
 ++++++genericContainer
 ++++++++image name='star'
+++++++++staticText name=' '
+++++++++++inlineTextBox name=' '
 ++++++++genericContainer
 ++++++++++staticText name='Some Text'
 ++++++++++++inlineTextBox name='Some Text'
 ++++++genericContainer
 ++++++++image
+++++++++staticText name=' '
+++++++++++inlineTextBox name=' '
 ++++++++genericContainer
 ++++++++++staticText name='Some Text'
 ++++++++++++inlineTextBox name='Some Text'
 ++++++genericContainer
 ++++++++staticText name='a list of items'
+++++++++staticText name=' '
+++++++++++inlineTextBox name=' '
 ++++++++genericContainer
 ++++++++++staticText name='Some Text'
 ++++++++++++inlineTextBox name='Some Text'
 ++++++genericContainer
 ++++++++image
+++++++++staticText name=' '
+++++++++++inlineTextBox name=' '
 ++++++++genericContainer
 ++++++++++staticText name='Some Text'
 ++++++++++++inlineTextBox name='Some Text'
diff --git a/content/test/data/accessibility/css/pseudo-element-alternative-text-expected-auralinux.txt b/content/test/data/accessibility/css/pseudo-element-alternative-text-expected-auralinux.txt
index 72823ca..0e4a219 100644
--- a/content/test/data/accessibility/css/pseudo-element-alternative-text-expected-auralinux.txt
+++ b/content/test/data/accessibility/css/pseudo-element-alternative-text-expected-auralinux.txt
@@ -1,5 +1,7 @@
 [document web]
 ++[section]
 ++++[image] name='alternative text'
+++++[static] name=' '
 ++++[static] name='DOM text'
+++++[static] name=' '
 ++++[image]
diff --git a/content/test/data/accessibility/css/pseudo-element-alternative-text-expected-blink.txt b/content/test/data/accessibility/css/pseudo-element-alternative-text-expected-blink.txt
index 086ff87..09f91d9 100644
--- a/content/test/data/accessibility/css/pseudo-element-alternative-text-expected-blink.txt
+++ b/content/test/data/accessibility/css/pseudo-element-alternative-text-expected-blink.txt
@@ -3,6 +3,10 @@
 ++++genericContainer ignored
 ++++++genericContainer
 ++++++++image name='alternative text'
+++++++++staticText name=' '
+++++++++++inlineTextBox name=' '
 ++++++++staticText name='DOM text'
 ++++++++++inlineTextBox name='DOM text'
+++++++++staticText name=' '
+++++++++++inlineTextBox name=' '
 ++++++++image
diff --git a/content/test/test_render_view_host.h b/content/test/test_render_view_host.h
index 29bf243..5482020 100644
--- a/content/test/test_render_view_host.h
+++ b/content/test/test_render_view_host.h
@@ -107,6 +107,8 @@
   void RenderProcessGone() override;
   void Destroy() override;
   void UpdateTooltipUnderCursor(const std::u16string& tooltip_text) override {}
+  void UpdateTooltipFromKeyboard(const std::u16string& tooltip_text,
+                                 const gfx::Rect& bounds) override {}
   gfx::Rect GetBoundsInRootWindow() override;
   blink::mojom::PointerLockResult LockMouse(bool) override;
   blink::mojom::PointerLockResult ChangeMouseLock(bool) override;
diff --git a/dbus/bus.cc b/dbus/bus.cc
index aab05d13..0a17df7e 100644
--- a/dbus/bus.cc
+++ b/dbus/bus.cc
@@ -12,7 +12,6 @@
 #include "base/files/file_descriptor_watcher_posix.h"
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
-#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "base/threading/sequenced_task_runner_handle.h"
diff --git a/device/fido/cable/v2_authenticator.cc b/device/fido/cable/v2_authenticator.cc
index de9077e..7f4a7baf 100644
--- a/device/fido/cable/v2_authenticator.cc
+++ b/device/fido/cable/v2_authenticator.cc
@@ -370,11 +370,18 @@
         }
 
         // It should be the case that all post-handshake messages fall into
-        // a single padding bucket. It doesn't have to be the smallest one, but
-        // that's currently true. If altering this, consider whether
-        // kPostHandshakeMsgPaddingGranularity needs to be increased instead.
-        DCHECK_EQ(post_handshake_msg_bytes->size(),
-                  kPostHandshakeMsgPaddingGranularity);
+        // a single padding bucket. (It doesn't have to be the smallest one.)
+        //
+        // This check should be:
+        // DCHECK_EQ(post_handshake_msg_bytes->size(),
+        //          kPostHandshakeMsgPaddingGranularity);
+        //
+        // ... but we're waiting to roll out a protocol change that allows it.
+        // For now, check that the messages fit within the future padding
+        // granularity, which will also highlight this when that constant is
+        // rename to remove "Future".
+        DCHECK_LE(post_handshake_msg_bytes->size(),
+                  kFuturePostHandshakeMsgPaddingGranularity);
 
         if (!crypter_->Encrypt(&post_handshake_msg_bytes.value())) {
           FIDO_LOG(ERROR) << "failed to encrypt post-handshake message";
diff --git a/extensions/browser/api/storage/storage_api.cc b/extensions/browser/api/storage/storage_api.cc
index a483b73..d07b98a 100644
--- a/extensions/browser/api/storage/storage_api.cc
+++ b/extensions/browser/api/storage/storage_api.cc
@@ -431,8 +431,10 @@
 
 ExtensionFunction::ResponseValue
 StorageStorageAreaClearFunction::RunInSession() {
-  // TODO(crbug.com/1185226): Implement RunInSession for
-  // chrome.storage.session.clear .
+  std::vector<SessionStorageManager::ValueChange> changes;
+  GetOrCreateSessionStorage(browser_context())->Clear(extension_id(), changes);
+
+  OnSessionSettingsChanged(std::move(changes));
   return NoArguments();
 }
 
diff --git a/fuchsia/base/mem_buffer_util.cc b/fuchsia/base/mem_buffer_util.cc
index 2a84d0a..e22af8be 100644
--- a/fuchsia/base/mem_buffer_util.cc
+++ b/fuchsia/base/mem_buffer_util.cc
@@ -14,7 +14,6 @@
 #include "base/files/file_util.h"
 #include "base/files/memory_mapped_file.h"
 #include "base/fuchsia/fuchsia_logging.h"
-#include "base/stl_util.h"
 #include "base/threading/thread_restrictions.h"
 
 namespace cr_fuchsia {
diff --git a/fuchsia/engine/BUILD.gn b/fuchsia/engine/BUILD.gn
index 950a10f..52bc13e 100644
--- a/fuchsia/engine/BUILD.gn
+++ b/fuchsia/engine/BUILD.gn
@@ -102,6 +102,7 @@
     "//base",
     "//base:base_static",
     "//base/util/memory_pressure",
+    "//components/cast/message_port:message_port_fuchsia",
     "//components/cast_streaming/browser",
     "//components/cast_streaming/mojo:mojom",
     "//components/cast_streaming/renderer",
@@ -190,8 +191,6 @@
     "browser/accessibility_bridge.h",
     "browser/ax_tree_converter.cc",
     "browser/ax_tree_converter.h",
-    "browser/cast_streaming_session_client.cc",
-    "browser/cast_streaming_session_client.h",
     "browser/content_directory_loader_factory.cc",
     "browser/content_directory_loader_factory.h",
     "browser/context_impl.cc",
@@ -218,6 +217,8 @@
     "browser/navigation_policy_handler.h",
     "browser/navigation_policy_throttle.cc",
     "browser/navigation_policy_throttle.h",
+    "browser/receiver_session_client.cc",
+    "browser/receiver_session_client.h",
     "browser/theme_manager.cc",
     "browser/theme_manager.h",
     "browser/url_request_rewrite_rules_manager.cc",
diff --git a/fuchsia/engine/browser/DEPS b/fuchsia/engine/browser/DEPS
index ae216e2..62d3f783 100644
--- a/fuchsia/engine/browser/DEPS
+++ b/fuchsia/engine/browser/DEPS
@@ -21,6 +21,7 @@
   "+services/metrics/public/cpp/ukm_source_id.h",
   "+services/network/public/mojom",
   "+third_party/blink/public",
+  "+third_party/openscreen/src",
   "+third_party/widevine/cdm",
   "+ui/accessibility",
   "+ui/aura",
diff --git a/fuchsia/engine/browser/cast_streaming_browsertest.cc b/fuchsia/engine/browser/cast_streaming_browsertest.cc
index b2e1d01..2da750c 100644
--- a/fuchsia/engine/browser/cast_streaming_browsertest.cc
+++ b/fuchsia/engine/browser/cast_streaming_browsertest.cc
@@ -112,31 +112,6 @@
   navigation_listener_.RunUntilTitleEquals("error");
 }
 
-// Check that the Cast Streaming MessagePort gets properly set on the Frame.
-IN_PROC_BROWSER_TEST_F(CastStreamingTest, FrameMessagePort) {
-  fuchsia::web::FramePtr frame = CreateFrame();
-
-  FrameImpl* frame_impl = context_impl()->GetFrameImplForTest(&frame);
-  ASSERT_TRUE(frame_impl);
-  EXPECT_FALSE(frame_impl->cast_streaming_session_client_for_test());
-
-  fuchsia::web::MessagePortPtr cast_streaming_message_port;
-
-  base::RunLoop run_loop;
-  cr_fuchsia::ResultReceiver<fuchsia::web::Frame_PostMessage_Result>
-      post_result(run_loop.QuitClosure());
-  frame->PostMessage(
-      "cast-streaming:receiver",
-      cr_fuchsia::CreateWebMessageWithMessagePortRequest(
-          cast_streaming_message_port.NewRequest(),
-          cr_fuchsia::MemBufferFromString("hi", "test")),
-      cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback()));
-  run_loop.Run();
-  ASSERT_TRUE(post_result->is_response());
-
-  EXPECT_TRUE(frame_impl->cast_streaming_session_client_for_test());
-}
-
 // Check that attempting to load the cast streaming media source URL when the
 // command line switch is set properly succeeds.
 IN_PROC_BROWSER_TEST_F(CastStreamingTest, LoadSuccess) {
diff --git a/fuchsia/engine/browser/frame_impl.cc b/fuchsia/engine/browser/frame_impl.cc
index bfed581..d5bb190 100644
--- a/fuchsia/engine/browser/frame_impl.cc
+++ b/fuchsia/engine/browser/frame_impl.cc
@@ -40,13 +40,13 @@
 #include "fuchsia/base/mem_buffer_util.h"
 #include "fuchsia/base/message_port.h"
 #include "fuchsia/engine/browser/accessibility_bridge.h"
-#include "fuchsia/engine/browser/cast_streaming_session_client.h"
 #include "fuchsia/engine/browser/context_impl.h"
 #include "fuchsia/engine/browser/event_filter.h"
 #include "fuchsia/engine/browser/frame_layout_manager.h"
 #include "fuchsia/engine/browser/frame_window_tree_host.h"
 #include "fuchsia/engine/browser/media_player_impl.h"
 #include "fuchsia/engine/browser/navigation_policy_handler.h"
+#include "fuchsia/engine/browser/receiver_session_client.h"
 #include "fuchsia/engine/browser/web_engine_devtools_controller.h"
 #include "fuchsia/engine/common/cast_streaming.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
@@ -554,8 +554,7 @@
     return false;
 
   fuchsia::web::Frame_PostMessage_Result result;
-  if (cast_streaming_session_client_ ||
-      !IsValidCastStreamingMessage(*message)) {
+  if (receiver_session_client_ || !IsValidCastStreamingMessage(*message)) {
     // The Cast Streaming MessagePort should only be set once and |message|
     // should be a valid Cast Streaming Message.
     result.set_err(fuchsia::web::FrameError::INVALID_ORIGIN);
@@ -563,7 +562,7 @@
     return true;
   }
 
-  cast_streaming_session_client_ = std::make_unique<CastStreamingSessionClient>(
+  receiver_session_client_ = std::make_unique<ReceiverSessionClient>(
       std::move((*message->mutable_outgoing_transfer())[0].message_port()));
   result.set_response(fuchsia::web::Frame_PostMessage_Response());
   (*callback)(std::move(result));
@@ -572,15 +571,14 @@
 
 void FrameImpl::MaybeStartCastStreaming(
     content::NavigationHandle* navigation_handle) {
-  if (!context_->has_cast_streaming_enabled() ||
-      !cast_streaming_session_client_)
+  if (!context_->has_cast_streaming_enabled() || !receiver_session_client_)
     return;
 
   mojo::AssociatedRemote<mojom::CastStreamingReceiver> cast_streaming_receiver;
   navigation_handle->GetRenderFrameHost()
       ->GetRemoteAssociatedInterfaces()
       ->GetInterface(&cast_streaming_receiver);
-  cast_streaming_session_client_->StartMojoConnection(
+  receiver_session_client_->SetCastStreamingReceiver(
       std::move(cast_streaming_receiver));
 }
 
diff --git a/fuchsia/engine/browser/frame_impl.h b/fuchsia/engine/browser/frame_impl.h
index 73f2d1c..08b2a1d 100644
--- a/fuchsia/engine/browser/frame_impl.h
+++ b/fuchsia/engine/browser/frame_impl.h
@@ -42,7 +42,7 @@
 class FromRenderFrameHost;
 }  // namespace content
 
-class CastStreamingSessionClient;
+class ReceiverSessionClient;
 class ContextImpl;
 class FrameWindowTreeHost;
 class FrameLayoutManager;
@@ -104,9 +104,6 @@
       fuchsia::accessibility::semantics::SemanticsManager* semantics_manager) {
     semantics_manager_for_test_ = semantics_manager;
   }
-  CastStreamingSessionClient* cast_streaming_session_client_for_test() {
-    return cast_streaming_session_client_.get();
-  }
   FrameWindowTreeHost* window_tree_host_for_test() {
     return window_tree_host_.get();
   }
@@ -326,7 +323,7 @@
   gfx::Size render_size_override_;
 
   std::unique_ptr<MediaPlayerImpl> media_player_;
-  std::unique_ptr<CastStreamingSessionClient> cast_streaming_session_client_;
+  std::unique_ptr<ReceiverSessionClient> receiver_session_client_;
   on_load_script_injector::OnLoadScriptInjectorHost<uint64_t> script_injector_;
 
   fidl::Binding<fuchsia::web::Frame> binding_;
diff --git a/fuchsia/engine/browser/receiver_session_client.cc b/fuchsia/engine/browser/receiver_session_client.cc
new file mode 100644
index 0000000..cd2807cb
--- /dev/null
+++ b/fuchsia/engine/browser/receiver_session_client.cc
@@ -0,0 +1,31 @@
+// Copyright 2021 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 "fuchsia/engine/browser/receiver_session_client.h"
+
+#include "base/bind.h"
+#include "components/cast/message_port/message_port_fuchsia.h"
+
+ReceiverSessionClient::ReceiverSessionClient(
+    fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request)
+    : message_port_request_(std::move(message_port_request)) {
+  DCHECK(message_port_request_);
+}
+
+ReceiverSessionClient::~ReceiverSessionClient() = default;
+
+void ReceiverSessionClient::SetCastStreamingReceiver(
+    mojo::AssociatedRemote<mojom::CastStreamingReceiver>
+        cast_streaming_receiver) {
+  DCHECK(message_port_request_);
+
+  receiver_session_ = cast_streaming::ReceiverSession::Create(base::BindOnce(
+      [](fidl::InterfaceRequest<fuchsia::web::MessagePort> port)
+          -> std::unique_ptr<cast_api_bindings::MessagePort> {
+        return cast_api_bindings::MessagePortFuchsia::Create(std::move(port));
+      },
+      std::move(message_port_request_)));
+  receiver_session_->SetCastStreamingReceiver(
+      std::move(cast_streaming_receiver));
+}
diff --git a/fuchsia/engine/browser/receiver_session_client.h b/fuchsia/engine/browser/receiver_session_client.h
new file mode 100644
index 0000000..b8f4eddd
--- /dev/null
+++ b/fuchsia/engine/browser/receiver_session_client.h
@@ -0,0 +1,39 @@
+// Copyright 2021 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 FUCHSIA_ENGINE_BROWSER_RECEIVER_SESSION_CLIENT_H_
+#define FUCHSIA_ENGINE_BROWSER_RECEIVER_SESSION_CLIENT_H_
+
+#include <fuchsia/web/cpp/fidl.h>
+
+#include "base/callback.h"
+#include "components/cast/message_port/message_port.h"
+#include "components/cast_streaming/browser/public/receiver_session.h"
+#include "third_party/openscreen/src/cast/common/public/message_port.h"
+
+// Holds a Cast Streaming Receiver Session.
+class ReceiverSessionClient {
+ public:
+  explicit ReceiverSessionClient(
+      fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request);
+  ReceiverSessionClient(const ReceiverSessionClient& other) = delete;
+
+  ~ReceiverSessionClient();
+
+  ReceiverSessionClient& operator=(const ReceiverSessionClient&) = delete;
+
+  void SetCastStreamingReceiver(
+      mojo::AssociatedRemote<mojom::CastStreamingReceiver>
+          cast_streaming_receiver);
+
+ private:
+  // Populated in the ctor, and removed when |receiver_session_| is created in
+  // SetCastStreamingReceiver().
+  fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request_;
+
+  // Created in SetCastStreamingReceiver(), and empty prior to that call.
+  std::unique_ptr<cast_streaming::ReceiverSession> receiver_session_;
+};
+
+#endif  // FUCHSIA_ENGINE_BROWSER_RECEIVER_SESSION_CLIENT_H_
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc
index da3e510..dd1f612 100644
--- a/headless/lib/browser/headless_web_contents_impl.cc
+++ b/headless/lib/browser/headless_web_contents_impl.cc
@@ -13,7 +13,6 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
diff --git a/infra/config/generated/commit-queue.cfg b/infra/config/generated/commit-queue.cfg
index 41044460..1439a26 100644
--- a/infra/config/generated/commit-queue.cfg
+++ b/infra/config/generated/commit-queue.cfg
@@ -318,6 +318,10 @@
         includable_only: true
       }
       builders {
+        name: "chromium/try/android-weblayer-10-x86-rel-tests"
+        includable_only: true
+      }
+      builders {
         name: "chromium/try/android-weblayer-marshmallow-x86-rel-tests"
         includable_only: true
       }
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index d4f24bf4..79a8608 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -29968,7 +29968,7 @@
         cmd: "luciexe"
       }
       properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.packager\",\"recipe\":\"chromium_rts/create_model\"}"
-      execution_timeout_secs: 21600
+      execution_timeout_secs: 28800
       build_numbers: YES
       service_account: "chromium-cipd-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
@@ -36729,6 +36729,71 @@
       }
     }
     builders {
+      name: "android-weblayer-10-x86-rel-tests"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builderless:1"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-18.04"
+      dimensions: "pool:luci.chromium.try"
+      dimensions: "ssd:0"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      execution_timeout_secs: 14400
+      expiration_secs: 7200
+      grace_period {
+        seconds: 120
+      }
+      caches {
+        name: "win_toolchain"
+        path: "win_toolchain"
+      }
+      build_numbers: YES
+      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
+      task_template_canary_percentage {
+        value: 5
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink"
+        value: 100
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink.junit_tests"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "try_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "gpu_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "android-weblayer-marshmallow-x86-rel-tests"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
diff --git a/infra/config/generated/luci-milo.cfg b/infra/config/generated/luci-milo.cfg
index ee1bfc5..12c43e97 100644
--- a/infra/config/generated/luci-milo.cfg
+++ b/infra/config/generated/luci-milo.cfg
@@ -13270,6 +13270,9 @@
     name: "buildbucket/luci.chromium.try/android-web-platform-pie-x86-fyi-rel"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/android-weblayer-10-x86-rel-tests"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/android-weblayer-marshmallow-x86-rel-tests"
   }
   builders {
@@ -14306,6 +14309,9 @@
     name: "buildbucket/luci.chromium.try/android-web-platform-pie-x86-fyi-rel"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/android-weblayer-10-x86-rel-tests"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/android-weblayer-marshmallow-x86-rel-tests"
   }
   builders {
diff --git a/infra/config/subprojects/chromium/ci.star b/infra/config/subprojects/chromium/ci.star
index cfb0186d..b55ea28 100644
--- a/infra/config/subprojects/chromium/ci.star
+++ b/infra/config/subprojects/chromium/ci.star
@@ -6256,7 +6256,7 @@
     executable = "recipe:chromium_rts/create_model",
     schedule = "0 7 * * *",  # at 12AM or 1AM PT (depending on DST), once a day.
     triggered_by = [],
-    execution_timeout = 6 * time.hour,
+    execution_timeout = 8 * time.hour,
     cores = None,
     console_view_entry = consoles.console_view_entry(
         category = "rts",
diff --git a/infra/config/subprojects/chromium/try.star b/infra/config/subprojects/chromium/try.star
index 7690ad17..37b7a3b 100644
--- a/infra/config/subprojects/chromium/try.star
+++ b/infra/config/subprojects/chromium/try.star
@@ -515,6 +515,10 @@
 )
 
 try_.chromium_android_builder(
+    name = "android-weblayer-10-x86-rel-tests",
+)
+
+try_.chromium_android_builder(
     name = "android-weblayer-marshmallow-x86-rel-tests",
 )
 
diff --git a/infra/config/subprojects/reclient/OWNERS b/infra/config/subprojects/reclient/OWNERS
deleted file mode 100644
index 29a7a4c..0000000
--- a/infra/config/subprojects/reclient/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-abdelaal@google.com
-foox@google.com
-kousikk@google.com
-msavigny@google.com
-rubensf@google.com
\ No newline at end of file
diff --git a/ios/chrome/app/app_startup_parameters.mm b/ios/chrome/app/app_startup_parameters.mm
index 53eb78c..0db8ba6a 100644
--- a/ios/chrome/app/app_startup_parameters.mm
+++ b/ios/chrome/app/app_startup_parameters.mm
@@ -4,7 +4,6 @@
 
 #import "ios/chrome/app/app_startup_parameters.h"
 
-#include "base/stl_util.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
 #import "net/base/mac/url_conversions.h"
 #include "net/base/url_util.h"
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 3834474f..cde0307 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1328,7 +1328,7 @@
         Off
       </message>
       <message name="IDS_IOS_OPTIONS_ACCOUNTS_SIGN_OUT_TURN_OFF_SYNC" desc="Title of the button to sign out and turn off sync. [iOS only]">
-        Sign Out and Turn Off Sync...
+        Sign Out and Turn Off Sync
       </message>
       <message name="IDS_IOS_OPTIONS_ADVANCED_TAB_LABEL" desc="The title of the Advanced section of the Settings page.  [Length: 20em] [iOS only]">
         Advanced
diff --git a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
index e4e4f8b0..192e6c68 100644
--- a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
+++ b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
@@ -12,7 +12,6 @@
 #include "base/callback_helpers.h"
 #include "base/check_op.h"
 #include "base/command_line.h"
-#include "base/stl_util.h"
 #include "base/task/post_task.h"
 #include "components/net_log/chrome_net_log.h"
 #include "components/prefs/pref_service.h"
diff --git a/ios/chrome/browser/metrics/first_user_action_recorder_unittest.cc b/ios/chrome/browser/metrics/first_user_action_recorder_unittest.cc
index e41d2130..b0ad3e5 100644
--- a/ios/chrome/browser/metrics/first_user_action_recorder_unittest.cc
+++ b/ios/chrome/browser/metrics/first_user_action_recorder_unittest.cc
@@ -7,7 +7,6 @@
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
 #include "base/run_loop.h"
-#include "base/stl_util.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/time/time.h"
 #include "ios/chrome/browser/metrics/first_user_action_recorder.h"
diff --git a/ios/chrome/browser/metrics/metrics_app_interface.mm b/ios/chrome/browser/metrics/metrics_app_interface.mm
index 448e1fb3..c6f9a0e 100644
--- a/ios/chrome/browser/metrics/metrics_app_interface.mm
+++ b/ios/chrome/browser/metrics/metrics_app_interface.mm
@@ -7,7 +7,6 @@
 #include <memory>
 #include <string>
 
-#include "base/stl_util.h"
 #include "base/strings/sys_string_conversions.h"
 #import "base/test/ios/wait_util.h"
 #include "components/metrics/demographics/demographic_metrics_test_utils.h"
diff --git a/ios/chrome/browser/snapshots/snapshot_cache.mm b/ios/chrome/browser/snapshots/snapshot_cache.mm
index 1d6545b..ea9b4fb 100644
--- a/ios/chrome/browser/snapshots/snapshot_cache.mm
+++ b/ios/chrome/browser/snapshots/snapshot_cache.mm
@@ -18,7 +18,6 @@
 #include "base/path_service.h"
 #include "base/sequence_checker.h"
 #include "base/sequenced_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
diff --git a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_default_account/consistency_default_account_view_controller.mm b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_default_account/consistency_default_account_view_controller.mm
index 3e71e25..730ba80 100644
--- a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_default_account/consistency_default_account_view_controller.mm
+++ b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_default_account/consistency_default_account_view_controller.mm
@@ -7,6 +7,7 @@
 #import "base/strings/sys_string_conversions.h"
 #import "ios/chrome/browser/ui/authentication/views/identity_button_control.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
+#import "ios/chrome/common/ui/colors/semantic_color_names.h"
 #import "ios/chrome/common/ui/util/button_util.h"
 #import "ios/chrome/common/ui/util/constraints_ui_util.h"
 #import "ios/chrome/common/ui/util/pointer_interaction_util.h"
@@ -140,6 +141,7 @@
   UILabel* label = [[UILabel alloc] init];
   label.text =
       l10n_util::GetNSString(IDS_IOS_CONSISTENCY_PROMO_DEFAULT_ACCOUNT_LABEL);
+  label.textColor = [UIColor colorNamed:kGrey700Color];
   label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline];
   label.numberOfLines = 0;
   [self.contentView addArrangedSubview:label];
@@ -148,6 +150,8 @@
   // Add IdentityButtonControl for the default identity.
   self.identityButtonControl =
       [[IdentityButtonControl alloc] initWithFrame:CGRectZero];
+  self.identityButtonControl.backgroundColor =
+      [UIColor colorNamed:kGroupedSecondaryBackgroundColor];
   self.identityButtonControl.arrowDirection = IdentityButtonControlArrowRight;
   self.identityButtonControl.avatarSize = kAvatarSize;
   self.identityButtonControl.minimumTopMargin = kMinimumTopMargin;
diff --git a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
index 5a45fa5..8bbea66 100644
--- a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
+++ b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
@@ -11,7 +11,6 @@
 #include "base/feature_list.h"
 #include "base/memory/ptr_util.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/autofill/core/browser/autofill_save_update_address_profile_delegate_ios.h"
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.mm b/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.mm
index 0c3bd50..2e891a6 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.mm
@@ -15,7 +15,6 @@
 #include "base/hash/hash.h"
 #include "base/i18n/string_compare.h"
 #include "base/metrics/user_metrics_action.h"
-#include "base/stl_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/bookmarks/browser/bookmark_model.h"
diff --git a/ios/chrome/browser/ui/infobars/modals/infobar_edit_address_profile_table_view_controller.mm b/ios/chrome/browser/ui/infobars/modals/infobar_edit_address_profile_table_view_controller.mm
index c87f012..8de37ef 100644
--- a/ios/chrome/browser/ui/infobars/modals/infobar_edit_address_profile_table_view_controller.mm
+++ b/ios/chrome/browser/ui/infobars/modals/infobar_edit_address_profile_table_view_controller.mm
@@ -7,7 +7,6 @@
 #include "base/mac/foundation_util.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
-#include "base/stl_util.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/strings/grit/components_strings.h"
 #include "ios/chrome/browser/infobars/infobar_metrics_recorder.h"
diff --git a/ios/chrome/browser/ui/settings/google_services/BUILD.gn b/ios/chrome/browser/ui/settings/google_services/BUILD.gn
index 3812c06..b9b5708 100644
--- a/ios/chrome/browser/ui/settings/google_services/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/google_services/BUILD.gn
@@ -191,6 +191,7 @@
     "//ios/chrome/browser/ui/table_view",
     "//ios/chrome/browser/ui/table_view/cells",
     "//ios/public/provider/chrome/browser/signin:fake_chrome_identity",
+    "//ios/public/provider/chrome/browser/signin:test_support",
     "//ios/web/public/test",
     "//ios/web/public/test",
     "//testing/gtest",
diff --git a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm
index 6f7a4d3ea..da0f1f81 100644
--- a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm
+++ b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm
@@ -75,6 +75,8 @@
 @property(nonatomic, strong) TableViewImageItem* encryptionItem;
 // Sync error item.
 @property(nonatomic, strong) TableViewItem* syncErrorItem;
+// Sign out and turn off sync item.
+@property(nonatomic, strong) TableViewItem* signOutAndTurnOffSyncItem;
 // Returns YES if the sync data items should be enabled.
 @property(nonatomic, assign, readonly) BOOL shouldSyncDataItemEnabled;
 // Returns whether the Sync settings should be disabled because of a Sync error.
@@ -305,20 +307,47 @@
     return;
   }
 
+  // Creates the sign-out item and its section.
+  TableViewModel* model = self.consumer.tableViewModel;
+  [model addSectionWithIdentifier:SignOutSectionIdentifier];
+  TableViewTextItem* item =
+      [[TableViewTextItem alloc] initWithType:SignOutItemType];
+  item.text = GetNSString(IDS_IOS_OPTIONS_ACCOUNTS_SIGN_OUT_TURN_OFF_SYNC);
+  item.textColor = [UIColor colorNamed:kRedColor];
+  self.signOutAndTurnOffSyncItem = item;
+
   // The user must be signed-in and syncing.
-  if (!self.isAuthenticated || !self.syncSetupService->IsSyncEnabled()) {
+  if (!self.shouldDisplaySignoutSection) {
+    return;
+  }
+  [model addItem:self.signOutAndTurnOffSyncItem
+      toSectionWithIdentifier:SignOutSectionIdentifier];
+}
+
+- (void)updateSignOutSection {
+  // The sign-out section will only apply to kMobileIdentityConsistency.
+  if (!base::FeatureList::IsEnabled(signin::kMobileIdentityConsistency)) {
     return;
   }
 
+  BOOL hasModelUpdate = NO;
   TableViewModel* model = self.consumer.tableViewModel;
-  [model addSectionWithIdentifier:SignOutSectionIdentifier];
+  if (self.shouldDisplaySignoutSection) {
+    DCHECK(self.signOutAndTurnOffSyncItem);
+    [model addItem:self.signOutAndTurnOffSyncItem
+        toSectionWithIdentifier:SignOutSectionIdentifier];
+    hasModelUpdate = YES;
+  } else if ([model hasItem:self.signOutAndTurnOffSyncItem]) {
+    [model removeItemWithType:SignOutItemType
+        fromSectionWithIdentifier:SignOutSectionIdentifier];
+    hasModelUpdate = YES;
+  }
 
-  TableViewTextItem* signOutItem =
-      [[TableViewTextItem alloc] initWithType:SignOutItemType];
-  signOutItem.text =
-      GetNSString(IDS_IOS_OPTIONS_ACCOUNTS_SIGN_OUT_TURN_OFF_SYNC);
-  signOutItem.textColor = [UIColor colorNamed:kRedColor];
-  [model addItem:signOutItem toSectionWithIdentifier:SignOutSectionIdentifier];
+  if (hasModelUpdate) {
+    NSUInteger sectionIndex =
+        [model sectionForSectionIdentifier:SignOutSectionIdentifier];
+    [self.consumer reloadSections:[NSIndexSet indexSetWithIndex:sectionIndex]];
+  }
 }
 
 #pragma mark - Private
@@ -405,6 +434,12 @@
          !self.disabledBecauseOfSyncError;
 }
 
+- (BOOL)shouldDisplaySignoutSection {
+  return self.isAuthenticated &&
+         self.syncSetupService->IsFirstSetupComplete() &&
+         self.syncSetupService->IsSyncEnabled();
+}
+
 #pragma mark - ManageSyncSettingsTableViewControllerModelDelegate
 
 - (void)manageSyncSettingsTableViewControllerLoadModel:
@@ -433,6 +468,7 @@
   [self updateSyncEverythingItemNotifyConsumer:YES];
   [self updateSyncItemsNotifyConsumer:YES];
   [self updateEncryptionItem:YES];
+  [self updateSignOutSection];
 }
 
 #pragma mark - IdentityManagerObserverBridgeDelegate
diff --git a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator_unittest.mm b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator_unittest.mm
index bdc9ad5..402c8be 100644
--- a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator_unittest.mm
@@ -25,6 +25,8 @@
 #import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_table_view_controller.h"
 #import "ios/chrome/browser/ui/table_view/cells/table_view_image_item.h"
 #import "ios/chrome/browser/ui/table_view/table_view_model.h"
+#import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h"
+#import "ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h"
 #import "ios/web/public/test/web_task_environment.h"
 #import "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -61,6 +63,12 @@
   void SetUp() override {
     PlatformTest::SetUp();
 
+    FakeChromeIdentity* identity =
+        [FakeChromeIdentity identityWithEmail:@"foo1@gmail.com"
+                                       gaiaID:@"foo1ID"
+                                         name:@"Fake Foo 1"];
+    identity_service()->AddIdentity(identity);
+
     TestChromeBrowserState::Builder builder;
     builder.AddTestingFactory(ProfileSyncServiceFactory::GetInstance(),
                               base::BindRepeating(&CreateMockSyncService));
@@ -78,8 +86,12 @@
     [consumer_ loadModel];
 
     pref_service_ = SetPrefService();
+
+    // Sign a fake identity into Chrome.
     authentication_service_ =
         AuthenticationServiceFactory::GetForBrowserState(browser_state_.get());
+    authentication_service_->SignIn(identity);
+
     sync_setup_service_mock_ = static_cast<SyncSetupServiceMock*>(
         SyncSetupServiceFactory::GetForBrowserState(browser_state_.get()));
     sync_service_mock_ = static_cast<syncer::MockSyncService*>(
@@ -94,6 +106,8 @@
   }
 
   void SetupSyncServiceInitializedExpectations() {
+    ON_CALL(*sync_service_mock_->GetMockUserSettings(), IsFirstSetupComplete())
+        .WillByDefault(Return(true));
     ON_CALL(*sync_setup_service_mock_, IsSyncEnabled())
         .WillByDefault(Return(true));
     ON_CALL(*sync_setup_service_mock_, IsSyncingAllDataTypes())
@@ -115,6 +129,10 @@
         .WillByDefault(Return(syncer::SyncService::TransportState::DISABLED));
   }
 
+  ios::FakeChromeIdentityService* identity_service() {
+    return ios::FakeChromeIdentityService::GetInstanceFromChromeProvider();
+  }
+
  protected:
   // Needed for test browser state created by TestChromeBrowserState().
   web::WebTaskEnvironment task_environment_;
@@ -140,6 +158,13 @@
 
   [mediator_ manageSyncSettingsTableViewControllerLoadModel:mediator_.consumer];
 
+  // "Turn off Sync" item only available in
+  // |signin::kMobileIdentityConsistency|.
+  ASSERT_FALSE([mediator_.consumer.tableViewModel
+      hasSectionForSectionIdentifier:SyncSettingsSectionIdentifier::
+                                         SignOutSectionIdentifier]);
+
+  // Encryption item is disabled.
   NSArray* advanced_settings_items = [mediator_.consumer.tableViewModel
       itemsInSectionWithIdentifier:SyncSettingsSectionIdentifier::
                                        AdvancedSettingsSectionIdentifier];
@@ -160,6 +185,13 @@
 
   [mediator_ manageSyncSettingsTableViewControllerLoadModel:mediator_.consumer];
 
+  // "Turn off Sync" item only available in
+  // |signin::kMobileIdentityConsistency|.
+  ASSERT_FALSE([mediator_.consumer.tableViewModel
+      hasSectionForSectionIdentifier:SyncSettingsSectionIdentifier::
+                                         SignOutSectionIdentifier]);
+
+  // Encryption item is disabled.
   NSArray* advanced_settings_items = [mediator_.consumer.tableViewModel
       itemsInSectionWithIdentifier:SyncSettingsSectionIdentifier::
                                        AdvancedSettingsSectionIdentifier];
@@ -190,7 +222,7 @@
 }
 
 // Tests that encryption is accessible when Sync is enabled.
-TEST_F(ManageSyncSettingsMediatorTest, SyncServiceEnabled) {
+TEST_F(ManageSyncSettingsMediatorTest, SyncServiceEnabledWithEncryption) {
   SetupSyncServiceInitializedExpectations();
   ON_CALL(*sync_setup_service_mock_, GetSyncServiceState())
       .WillByDefault(Return(SyncSetupService::kNoSyncServiceError));
@@ -210,6 +242,42 @@
       hasSectionForSectionIdentifier:SyncErrorsSectionIdentifier]);
 }
 
+// Tests that "Turn off Sync" is hidden when Sync is disabled.
+TEST_F(ManageSyncSettingsMediatorTest, SyncServiceDisabledWithTurnOffSync) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(signin::kMobileIdentityConsistency);
+
+  SetupSyncDisabledExpectations();
+  ON_CALL(*sync_setup_service_mock_, GetSyncServiceState())
+      .WillByDefault(Return(SyncSetupService::kNoSyncServiceError));
+
+  [mediator_ manageSyncSettingsTableViewControllerLoadModel:mediator_.consumer];
+
+  // "Turn off Sync" item is shown.
+  NSArray* sign_out_items = [mediator_.consumer.tableViewModel
+      itemsInSectionWithIdentifier:SyncSettingsSectionIdentifier::
+                                       SignOutSectionIdentifier];
+  ASSERT_EQ(0UL, sign_out_items.count);
+}
+
+// Tests that "Turn off Sync" is accessible when Sync is enabled.
+TEST_F(ManageSyncSettingsMediatorTest, SyncServiceEnabledWithTurnOffSync) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(signin::kMobileIdentityConsistency);
+
+  SetupSyncServiceInitializedExpectations();
+  ON_CALL(*sync_setup_service_mock_, GetSyncServiceState())
+      .WillByDefault(Return(SyncSetupService::kNoSyncServiceError));
+
+  [mediator_ manageSyncSettingsTableViewControllerLoadModel:mediator_.consumer];
+
+  // "Turn off Sync" item is shown.
+  NSArray* sign_out_items = [mediator_.consumer.tableViewModel
+      itemsInSectionWithIdentifier:SyncSettingsSectionIdentifier::
+                                       SignOutSectionIdentifier];
+  ASSERT_EQ(1UL, sign_out_items.count);
+}
+
 // Tests that a Sync error that occurs after the user has loaded the Settings
 // page once will update the full page.
 TEST_F(ManageSyncSettingsMediatorTest, SyncServiceSuccessThenDisabled) {
@@ -223,7 +291,7 @@
 
   // Loads the Sync page once in success state.
   [mediator_ manageSyncSettingsTableViewControllerLoadModel:mediator_.consumer];
-  // Loads the Sync page again in disabled tate.
+  // Loads the Sync page again in disabled state.
   [mediator_ onSyncStateChanged];
 
   ASSERT_TRUE([mediator_.consumer.tableViewModel
@@ -234,3 +302,38 @@
                                        SyncErrorsSectionIdentifier];
   ASSERT_EQ(1UL, error_items.count);
 }
+
+// Tests that "Turn off Sync" item transition from disabled to enabled goes from
+// hiding to showing the item.
+TEST_F(ManageSyncSettingsMediatorTest,
+       SyncServiceSetupTransitionForTurnOffSync) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(signin::kMobileIdentityConsistency);
+
+  // Set Sync disabled expectations.
+  SetupSyncDisabledExpectations();
+  ON_CALL(*sync_setup_service_mock_, GetSyncServiceState())
+      .WillByDefault(Return(SyncSetupService::kSyncSettingsNotConfirmed));
+
+  [mediator_ manageSyncSettingsTableViewControllerLoadModel:mediator_.consumer];
+
+  // "Turn off Sync" item is hidden.
+  NSArray* hidden_sign_out_items = [mediator_.consumer.tableViewModel
+      itemsInSectionWithIdentifier:SyncSettingsSectionIdentifier::
+                                       SignOutSectionIdentifier];
+  ASSERT_EQ(0UL, hidden_sign_out_items.count);
+
+  // Set Sync enabled expectations.
+  SetupSyncServiceInitializedExpectations();
+  ON_CALL(*sync_setup_service_mock_, GetSyncServiceState())
+      .WillByDefault(Return(SyncSetupService::kNoSyncServiceError));
+
+  // Loads the Sync page again in enabled state.
+  [mediator_ onSyncStateChanged];
+
+  // "Turn off Sync" item is shown.
+  NSArray* shown_sign_out_items = [mediator_.consumer.tableViewModel
+      itemsInSectionWithIdentifier:SyncSettingsSectionIdentifier::
+                                       SignOutSectionIdentifier];
+  ASSERT_EQ(1UL, shown_sign_out_items.count);
+}
diff --git a/ios/chrome/browser/web/session_state/web_session_state_cache.mm b/ios/chrome/browser/web/session_state/web_session_state_cache.mm
index ec527ef..66cd13d 100644
--- a/ios/chrome/browser/web/session_state/web_session_state_cache.mm
+++ b/ios/chrome/browser/web/session_state/web_session_state_cache.mm
@@ -17,7 +17,6 @@
 #include "base/path_service.h"
 #include "base/sequence_checker.h"
 #include "base/sequenced_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
diff --git a/ios/chrome/test/app/histogram_test_util.mm b/ios/chrome/test/app/histogram_test_util.mm
index 8b89c04..4162fc4 100644
--- a/ios/chrome/test/app/histogram_test_util.mm
+++ b/ios/chrome/test/app/histogram_test_util.mm
@@ -12,7 +12,6 @@
 #include "base/metrics/metrics_hashes.h"
 #include "base/metrics/sample_map.h"
 #include "base/metrics/statistics_recorder.h"
-#include "base/stl_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
diff --git a/ios/components/io_thread/ios_io_thread.mm b/ios/components/io_thread/ios_io_thread.mm
index 28ec8c7..169bb9c 100644
--- a/ios/components/io_thread/ios_io_thread.mm
+++ b/ios/components/io_thread/ios_io_thread.mm
@@ -18,7 +18,6 @@
 #include "base/macros.h"
 #include "base/metrics/field_trial.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
index 67d20e51..0495dbd 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-c0eff592e3b538dfc092e5ad0e21537f4906b0b8
\ No newline at end of file
+49cfba1c3cb4bc2e78772d1af34c209edd39c1c5
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
index d5219874..5ab6d1ce 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-858739cdcad8171f55e20e3cb9655941f3b46dc6
\ No newline at end of file
+e2c28706a21dffc4795f64159b27b16a3302ca53
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1
index c2dae87..514243d 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-d7f0f6f254752ad2ff2b6d76da632f037b021b99
\ No newline at end of file
+9a2d2b5274eceec684df5cf46ce5b2490570904d
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1
index d8546b7..26c964f9 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-fc8c41fb9702e4e0c1da21f1645a88021b3951d8
\ No newline at end of file
+78a8fe42f08353d0775ef6657ea1421838e4f26f
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
index 3cd4ec42..21d1b72 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-27eb0d605466f0e2bb804c8e7334d24aeac89f3e
\ No newline at end of file
+93754cd2a76bc75c58969151cf999c66c1891dde
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
index 3fcc3264..d89d0d8 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-b080ed8a7185e8596c74cac7fc58da3046d951f2
\ No newline at end of file
+25022f44c4b1a8a6b370be1c45e987e8b09d1d8c
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
index b1f22ef..0366329 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-8647da30e5dfc3c322b18ea157e9099baa5de4a2
\ No newline at end of file
+3727ff9753e5d63a8ba5f153a7509a7d0a5507b8
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
index e7572ab..1f5c2a5e 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-237116fff8711e6f3ecf77c636565c7418fcd9ad
\ No newline at end of file
+48410271aa8f13fb020aff3168808e0061a07356
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
index 1eac3ae..64677a09 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-fc82587e59b323d277945bc2c3aa180a1561a369
\ No newline at end of file
+11b543235461f5f2e32716567032310301a2b4f0
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
index 22e529b..14536d2 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-b1b0ff017042f68b27c23e63dd6b6b87b17b61d1
\ No newline at end of file
+25096602fb685c1d0a47ca055e6d5341ccf9393f
\ No newline at end of file
diff --git a/ios/web/common/user_agent.mm b/ios/web/common/user_agent.mm
index 66cc78cf..4bbc9f3 100644
--- a/ios/web/common/user_agent.mm
+++ b/ios/web/common/user_agent.mm
@@ -11,7 +11,6 @@
 #include <sys/sysctl.h>
 #include <string>
 
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/sys_string_conversions.h"
diff --git a/ios/web/web_view/content_type_util.cc b/ios/web/web_view/content_type_util.cc
index de72913..5469013 100644
--- a/ios/web/web_view/content_type_util.cc
+++ b/ios/web/web_view/content_type_util.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "ios/web/web_view/content_type_util.h"
-#include "base/stl_util.h"
 
 namespace web {
 
diff --git a/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm b/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
index c054bdc..594ada8 100644
--- a/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
+++ b/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
@@ -10,7 +10,6 @@
 #include "base/check.h"
 #include "base/memory/ptr_util.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "components/autofill/core/browser/form_data_importer.h"
 #include "components/autofill/core/browser/logging/log_router.h"
 #include "components/autofill/core/browser/payments/payments_client.h"
diff --git a/ios/web_view/internal/cwv_flags.mm b/ios/web_view/internal/cwv_flags.mm
index 81811db..e2295c98 100644
--- a/ios/web_view/internal/cwv_flags.mm
+++ b/ios/web_view/internal/cwv_flags.mm
@@ -12,7 +12,6 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "base/values.h"
 #include "components/autofill/core/common/autofill_switches.h"
 #include "components/flags_ui/feature_entry.h"
diff --git a/media/audio/alsa/alsa_output.cc b/media/audio/alsa/alsa_output.cc
index c148f26b..a3e8dbd 100644
--- a/media/audio/alsa/alsa_output.cc
+++ b/media/audio/alsa/alsa_output.cc
@@ -43,7 +43,6 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/free_deleter.h"
-#include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/default_tick_clock.h"
 #include "base/trace_event/trace_event.h"
diff --git a/media/audio/audio_opus_encoder.cc b/media/audio/audio_opus_encoder.cc
index 7a3a4510..817fcc57 100644
--- a/media/audio/audio_opus_encoder.cc
+++ b/media/audio/audio_opus_encoder.cc
@@ -9,7 +9,6 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/numerics/checked_math.h"
-#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/status.h"
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc
index 1f1b15e6..5044a50 100644
--- a/media/audio/cras/audio_manager_cras.cc
+++ b/media/audio/cras/audio_manager_cras.cc
@@ -16,7 +16,6 @@
 #include "base/environment.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/nix/xdg_util.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/system/sys_info.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/media/audio/cras/audio_manager_cras_base.cc b/media/audio/cras/audio_manager_cras_base.cc
index 5c57e1a..b7eecf40 100644
--- a/media/audio/cras/audio_manager_cras_base.cc
+++ b/media/audio/cras/audio_manager_cras_base.cc
@@ -16,7 +16,6 @@
 #include "base/environment.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/nix/xdg_util.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/system/sys_info.h"
diff --git a/media/audio/cras/cras_util.cc b/media/audio/cras/cras_util.cc
index 5b52a44..71cde269 100644
--- a/media/audio/cras/cras_util.cc
+++ b/media/audio/cras/cras_util.cc
@@ -5,7 +5,6 @@
 #include "media/audio/cras/cras_util.h"
 
 #include "base/logging.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/time/time.h"
 #include "media/audio/audio_device_description.h"
diff --git a/media/audio/pulse/audio_manager_pulse.cc b/media/audio/pulse/audio_manager_pulse.cc
index 6705e04..147246b2 100644
--- a/media/audio/pulse/audio_manager_pulse.cc
+++ b/media/audio/pulse/audio_manager_pulse.cc
@@ -11,7 +11,6 @@
 #include "base/environment.h"
 #include "base/logging.h"
 #include "base/nix/xdg_util.h"
-#include "base/stl_util.h"
 #include "build/chromeos_buildflags.h"
 #include "media/audio/audio_device_description.h"
 #include "media/audio/pulse/pulse_input.h"
diff --git a/media/base/android/media_drm_bridge_client.cc b/media/base/android/media_drm_bridge_client.cc
index cad887c4..182e43e5 100644
--- a/media/base/android/media_drm_bridge_client.cc
+++ b/media/base/android/media_drm_bridge_client.cc
@@ -5,7 +5,6 @@
 #include "media/base/android/media_drm_bridge_client.h"
 
 #include "base/check.h"
-#include "base/stl_util.h"
 
 namespace media {
 
diff --git a/media/base/cdm_key_information.cc b/media/base/cdm_key_information.cc
index 616732c..73bd18b 100644
--- a/media/base/cdm_key_information.cc
+++ b/media/base/cdm_key_information.cc
@@ -5,7 +5,6 @@
 #include "media/base/cdm_key_information.h"
 
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 
 namespace media {
diff --git a/media/base/pipeline_impl_unittest.cc b/media/base/pipeline_impl_unittest.cc
index 69a0bed..8ec8dd8 100644
--- a/media/base/pipeline_impl_unittest.cc
+++ b/media/base/pipeline_impl_unittest.cc
@@ -14,7 +14,6 @@
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/test/gmock_callback_support.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "base/test/task_environment.h"
diff --git a/media/capture/video/linux/fake_v4l2_impl.cc b/media/capture/video/linux/fake_v4l2_impl.cc
index 0964747..f761e84 100644
--- a/media/capture/video/linux/fake_v4l2_impl.cc
+++ b/media/capture/video/linux/fake_v4l2_impl.cc
@@ -12,7 +12,6 @@
 
 #include "base/bind.h"
 #include "base/bits.h"
-#include "base/stl_util.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread.h"
 #include "media/base/video_frame.h"
diff --git a/media/capture/video/win/sink_input_pin_win.cc b/media/capture/video/win/sink_input_pin_win.cc
index e38ec12..11c19d2b 100644
--- a/media/capture/video/win/sink_input_pin_win.cc
+++ b/media/capture/video/win/sink_input_pin_win.cc
@@ -12,7 +12,6 @@
 #include <stdint.h>
 
 #include "base/logging.h"
-#include "base/stl_util.h"
 #include "base/win/win_util.h"
 #include "media/base/timestamp_constants.h"
 #include "media/base/video_frame.h"
diff --git a/media/capture/video/win/video_capture_device_win.cc b/media/capture/video/win/video_capture_device_win.cc
index 5f6d211..b6269ef 100644
--- a/media/capture/video/win/video_capture_device_win.cc
+++ b/media/capture/video/win/video_capture_device_win.cc
@@ -13,7 +13,6 @@
 #include <utility>
 
 #include "base/feature_list.h"
-#include "base/stl_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/win/scoped_co_mem.h"
 #include "base/win/scoped_variant.h"
diff --git a/media/cast/sender/external_video_encoder.cc b/media/cast/sender/external_video_encoder.cc
index 3f5cc46..de32ff7f 100644
--- a/media/cast/sender/external_video_encoder.cc
+++ b/media/cast/sender/external_video_encoder.cc
@@ -15,7 +15,6 @@
 #include "base/memory/shared_memory_mapping.h"
 #include "base/memory/unsafe_shared_memory_region.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "build/build_config.h"
diff --git a/media/cast/test/cast_benchmarks.cc b/media/cast/test/cast_benchmarks.cc
index 25e535e..bfdf5d0 100644
--- a/media/cast/test/cast_benchmarks.cc
+++ b/media/cast/test/cast_benchmarks.cc
@@ -40,7 +40,6 @@
 #include "base/memory/weak_ptr.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/simple_test_tick_clock.h"
diff --git a/media/formats/mp4/box_definitions.cc b/media/formats/mp4/box_definitions.cc
index f53b934..263e913 100644
--- a/media/formats/mp4/box_definitions.cc
+++ b/media/formats/mp4/box_definitions.cc
@@ -13,7 +13,6 @@
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/numerics/safe_math.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "build/build_config.h"
diff --git a/media/gpu/android/codec_wrapper.cc b/media/gpu/android/codec_wrapper.cc
index 8083f4c..aaaa5fa 100644
--- a/media/gpu/android/codec_wrapper.cc
+++ b/media/gpu/android/codec_wrapper.cc
@@ -12,7 +12,6 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
 #include "media/base/android/media_codec_util.h"
 #include "media/base/bind_to_current_loop.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/media/gpu/android/direct_shared_image_video_provider.cc b/media/gpu/android/direct_shared_image_video_provider.cc
index 8fcc9ca..837151c 100644
--- a/media/gpu/android/direct_shared_image_video_provider.cc
+++ b/media/gpu/android/direct_shared_image_video_provider.cc
@@ -13,7 +13,6 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/task_runner_util.h"
 #include "gpu/command_buffer/service/abstract_texture.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
diff --git a/media/gpu/android/video_frame_factory_impl.cc b/media/gpu/android/video_frame_factory_impl.cc
index aae48f92..9f600d2f 100644
--- a/media/gpu/android/video_frame_factory_impl.cc
+++ b/media/gpu/android/video_frame_factory_impl.cc
@@ -13,7 +13,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/task_runner_util.h"
 #include "base/trace_event/trace_event.h"
 #include "gpu/command_buffer/service/abstract_texture.h"
diff --git a/media/gpu/h264_dpb.cc b/media/gpu/h264_dpb.cc
index 8ef3baf..e89ed45 100644
--- a/media/gpu/h264_dpb.cc
+++ b/media/gpu/h264_dpb.cc
@@ -8,7 +8,6 @@
 
 #include "base/logging.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "media/gpu/h264_dpb.h"
 
 namespace media {
diff --git a/media/gpu/ipc/service/gpu_video_decode_accelerator.cc b/media/gpu/ipc/service/gpu_video_decode_accelerator.cc
index 34432ca..5fc394b1 100644
--- a/media/gpu/ipc/service/gpu_video_decode_accelerator.cc
+++ b/media/gpu/ipc/service/gpu_video_decode_accelerator.cc
@@ -12,7 +12,6 @@
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "gpu/command_buffer/common/command_buffer.h"
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
index addf790f..55b3d6c 100644
--- a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
+++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
@@ -23,7 +23,6 @@
 #include "base/command_line.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/task/post_task.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
diff --git a/media/gpu/vaapi/vaapi_unittest.cc b/media/gpu/vaapi/vaapi_unittest.cc
index 9a9bfb9e..79f4eec 100644
--- a/media/gpu/vaapi/vaapi_unittest.cc
+++ b/media/gpu/vaapi/vaapi_unittest.cc
@@ -113,21 +113,6 @@
       /*disabled_features=*/{});
   return scoped_feature_list;
 }
-
-unsigned int ToVaRTFormat(uint32_t va_fourcc) {
-  switch (va_fourcc) {
-    case VA_FOURCC_I420:
-      return VA_RT_FORMAT_YUV420;
-    case VA_FOURCC_YUY2:
-      return VA_RT_FORMAT_YUV422;
-    case VA_FOURCC_RGBA:
-      return VA_RT_FORMAT_RGB32;
-    case VA_FOURCC_P010:
-      return VA_RT_FORMAT_YUV420_10;
-  }
-  return kInvalidVaRtFormat;
-}
-
 }  // namespace
 
 class VaapiTest : public testing::Test {
@@ -368,87 +353,6 @@
     }
   }
 }
-
-class VaapiVppTest
-    : public VaapiTest,
-      public testing::WithParamInterface<std::tuple<uint32_t, uint32_t>> {
- public:
-  VaapiVppTest() = default;
-  ~VaapiVppTest() override = default;
-
-  // Populate meaningful test suffixes instead of /0, /1, etc.
-  struct PrintToStringParamName {
-    template <class ParamType>
-    std::string operator()(
-        const testing::TestParamInfo<ParamType>& info) const {
-      std::stringstream ss;
-      ss << FourccToString(std::get<0>(info.param)) << "_to_"
-         << FourccToString(std::get<1>(info.param));
-      return ss.str();
-    }
-  };
-};
-
-TEST_P(VaapiVppTest, BlitWithVAAllocatedSurfaces) {
-  const uint32_t va_fourcc_in = std::get<0>(GetParam());
-  const uint32_t va_fourcc_out = std::get<1>(GetParam());
-
-  if (!VaapiWrapper::IsVppFormatSupported(va_fourcc_in) ||
-      !VaapiWrapper::IsVppFormatSupported(va_fourcc_out)) {
-    GTEST_SKIP() << FourccToString(va_fourcc_in) << " -> "
-                 << FourccToString(va_fourcc_out) << " not supported";
-  }
-  constexpr gfx::Size kInputSize(640, 320);
-  constexpr gfx::Size kOutputSize(320, 180);
-  ASSERT_TRUE(VaapiWrapper::IsVppResolutionAllowed(kInputSize));
-  ASSERT_TRUE(VaapiWrapper::IsVppResolutionAllowed(kOutputSize));
-
-  auto wrapper =
-      VaapiWrapper::Create(VaapiWrapper::kVideoProcess, VAProfileNone,
-                           EncryptionScheme::kUnencrypted, base::DoNothing());
-  ASSERT_TRUE(!!wrapper);
-  // Size is unnecessary for a VPP context.
-  ASSERT_TRUE(wrapper->CreateContext(gfx::Size()));
-
-  const unsigned int va_rt_format_in = ToVaRTFormat(va_fourcc_in);
-  ASSERT_NE(va_rt_format_in, kInvalidVaRtFormat);
-  const unsigned int va_rt_format_out = ToVaRTFormat(va_fourcc_out);
-  ASSERT_NE(va_rt_format_out, kInvalidVaRtFormat);
-
-  std::unique_ptr<ScopedVASurface> scoped_surface_in =
-      wrapper->CreateScopedVASurface(va_rt_format_in, kInputSize);
-  ASSERT_TRUE(!!scoped_surface_in);
-
-  std::unique_ptr<ScopedVASurface> scoped_surface_out =
-      wrapper->CreateScopedVASurface(va_rt_format_out, kOutputSize);
-  ASSERT_TRUE(!!scoped_surface_out);
-
-  scoped_refptr<VASurface> surface_in = base::MakeRefCounted<VASurface>(
-      scoped_surface_in->id(), kInputSize, va_rt_format_in, base::DoNothing());
-  scoped_refptr<VASurface> surface_out =
-      base::MakeRefCounted<VASurface>(scoped_surface_out->id(), kOutputSize,
-                                      va_rt_format_out, base::DoNothing());
-
-  ASSERT_TRUE(wrapper->BlitSurface(*surface_in, *surface_out,
-                                   gfx::Rect(kInputSize),
-                                   gfx::Rect(kOutputSize), VIDEO_ROTATION_0));
-  ASSERT_TRUE(wrapper->SyncSurface(scoped_surface_out->id()));
-  wrapper->DestroyContext();
-}
-
-// TODO(b/187852384): Consider adding more VaapiVppTest cases, e.g. crops.
-
-// Note: vaCreateSurfaces() uses the RT version of the Four CC, so we don't need
-// to consider swizzlings, since they'll end up mapped to the same RT format.
-constexpr uint32_t kVAFourCCs[] = {VA_FOURCC_I420, VA_FOURCC_YUY2,
-                                   VA_FOURCC_RGBA, VA_FOURCC_P010};
-
-INSTANTIATE_TEST_SUITE_P(,
-                         VaapiVppTest,
-                         ::testing::Combine(::testing::ValuesIn(kVAFourCCs),
-                                            ::testing::ValuesIn(kVAFourCCs)),
-                         VaapiVppTest::PrintToStringParamName());
-
 }  // namespace media
 
 int main(int argc, char** argv) {
diff --git a/media/gpu/vaapi/vaapi_wrapper.cc b/media/gpu/vaapi/vaapi_wrapper.cc
index 4333c6a..7111b242 100644
--- a/media/gpu/vaapi/vaapi_wrapper.cc
+++ b/media/gpu/vaapi/vaapi_wrapper.cc
@@ -1384,7 +1384,7 @@
 
   scoped_refptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper(mode));
   if (vaapi_wrapper->VaInitialize(report_error_to_uma_cb)) {
-    if (vaapi_wrapper->Initialize(mode, va_profile, encryption_scheme))
+    if (vaapi_wrapper->Initialize(va_profile, encryption_scheme))
       return vaapi_wrapper;
   }
   LOG(ERROR) << "Failed to create VaapiWrapper for va_profile: "
@@ -2756,11 +2756,10 @@
   Deinitialize();
 }
 
-bool VaapiWrapper::Initialize(CodecMode mode,
-                              VAProfile va_profile,
+bool VaapiWrapper::Initialize(VAProfile va_profile,
                               EncryptionScheme encryption_scheme) {
 #if DCHECK_IS_ON()
-  if (mode == kEncodeConstantQuantizationParameter) {
+  if (mode_ == kEncodeConstantQuantizationParameter) {
     DCHECK_NE(va_profile, VAProfileJPEGBaseline)
         << "JPEG Encoding doesn't support CQP bitrate control";
   }
@@ -2768,15 +2767,16 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   if (encryption_scheme != EncryptionScheme::kUnencrypted &&
-      mode != kDecodeProtected)
+      mode_ != kDecodeProtected) {
     return false;
+  }
 #endif
 
-  const VAEntrypoint entrypoint = GetDefaultVaEntryPoint(mode, va_profile);
+  const VAEntrypoint entrypoint = GetDefaultVaEntryPoint(mode_, va_profile);
 
   base::AutoLock auto_lock(*va_lock_);
   std::vector<VAConfigAttrib> required_attribs;
-  if (!GetRequiredAttribs(va_lock_, va_display_, mode, va_profile, entrypoint,
+  if (!GetRequiredAttribs(va_lock_, va_display_, mode_, va_profile, entrypoint,
                           &required_attribs)) {
     return false;
   }
diff --git a/media/gpu/vaapi/vaapi_wrapper.h b/media/gpu/vaapi/vaapi_wrapper.h
index da1e5477..e1dde83 100644
--- a/media/gpu/vaapi/vaapi_wrapper.h
+++ b/media/gpu/vaapi/vaapi_wrapper.h
@@ -489,8 +489,7 @@
   FRIEND_TEST_ALL_PREFIXES(VaapiUtilsTest, BadScopedVAImage);
   FRIEND_TEST_ALL_PREFIXES(VaapiUtilsTest, BadScopedVABufferMapping);
 
-  bool Initialize(CodecMode mode,
-                  VAProfile va_profile,
+  bool Initialize(VAProfile va_profile,
                   EncryptionScheme encryption_scheme) WARN_UNUSED_RESULT;
   void Deinitialize();
   bool VaInitialize(const ReportErrorToUMACB& report_error_to_uma_cb)
diff --git a/media/renderers/video_renderer_impl_unittest.cc b/media/renderers/video_renderer_impl_unittest.cc
index d5f94b32..7bacc304 100644
--- a/media/renderers/video_renderer_impl_unittest.cc
+++ b/media/renderers/video_renderer_impl_unittest.cc
@@ -15,7 +15,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
diff --git a/media/video/h264_level_limits.cc b/media/video/h264_level_limits.cc
index 2c6427c..f4f60c2 100644
--- a/media/video/h264_level_limits.cc
+++ b/media/video/h264_level_limits.cc
@@ -5,7 +5,6 @@
 #include "media/video/h264_level_limits.h"
 
 #include "base/logging.h"
-#include "base/stl_util.h"
 #include "media/video/h264_parser.h"
 
 namespace media {
diff --git a/net/base/mime_sniffer.cc b/net/base/mime_sniffer.cc
index de8ad1c1..78006760 100644
--- a/net/base/mime_sniffer.cc
+++ b/net/base/mime_sniffer.cc
@@ -91,7 +91,6 @@
 #include "base/check_op.h"
 #include "base/containers/span.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "url/gurl.h"
 
diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc
index 0becb8b..f391fa9 100644
--- a/net/base/mime_util.cc
+++ b/net/base/mime_util.cc
@@ -13,7 +13,6 @@
 #include "base/containers/span.h"
 #include "base/lazy_instance.h"
 #include "base/rand_util.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
diff --git a/net/base/network_interfaces_win.cc b/net/base/network_interfaces_win.cc
index ceb459a..f870733 100644
--- a/net/base/network_interfaces_win.cc
+++ b/net/base/network_interfaces_win.cc
@@ -9,7 +9,6 @@
 
 #include "base/files/file_path.h"
 #include "base/lazy_instance.h"
-#include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
diff --git a/net/base/priority_queue_unittest.cc b/net/base/priority_queue_unittest.cc
index ab9726fc..88974bce 100644
--- a/net/base/priority_queue_unittest.cc
+++ b/net/base/priority_queue_unittest.cc
@@ -7,7 +7,6 @@
 #include <cstddef>
 
 #include "base/bind.h"
-#include "base/stl_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace net {
diff --git a/net/cert/cert_verify_proc.cc b/net/cert/cert_verify_proc.cc
index 8cf304d..aa675921 100644
--- a/net/cert/cert_verify_proc.cc
+++ b/net/cert/cert_verify_proc.cc
@@ -12,7 +12,6 @@
 #include "base/metrics/histogram.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/scoped_blocking_call.h"
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc
index 681feb4..b852891 100644
--- a/net/cert/cert_verify_proc_unittest.cc
+++ b/net/cert/cert_verify_proc_unittest.cc
@@ -15,7 +15,6 @@
 #include "base/macros.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/rand_util.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
diff --git a/net/dns/dns_response_unittest.cc b/net/dns/dns_response_unittest.cc
index bb30e0d..00d95d4 100644
--- a/net/dns/dns_response_unittest.cc
+++ b/net/dns/dns_response_unittest.cc
@@ -11,7 +11,6 @@
 
 #include "base/big_endian.h"
 #include "base/check.h"
-#include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/time/time.h"
 #include "net/base/io_buffer.h"
diff --git a/net/dns/dns_session.cc b/net/dns/dns_session.cc
index 996a515f..1e54cd2 100644
--- a/net/dns/dns_session.cc
+++ b/net/dns/dns_session.cc
@@ -11,7 +11,6 @@
 
 #include "base/bind.h"
 #include "base/rand_util.h"
-#include "base/stl_util.h"
 #include "net/dns/dns_config.h"
 #include "net/dns/dns_socket_allocator.h"
 #include "net/log/net_log.h"
diff --git a/net/dns/dns_transaction.cc b/net/dns/dns_transaction.cc
index bb17713..57d5663 100644
--- a/net/dns/dns_transaction.cc
+++ b/net/dns/dns_transaction.cc
@@ -26,7 +26,6 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/rand_util.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_checker.h"
diff --git a/net/dns/host_resolver_manager_unittest.cc b/net/dns/host_resolver_manager_unittest.cc
index dd0fd46..3c50380 100644
--- a/net/dns/host_resolver_manager_unittest.cc
+++ b/net/dns/host_resolver_manager_unittest.cc
@@ -22,7 +22,6 @@
 #include "base/run_loop.h"
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
diff --git a/net/dns/mock_host_resolver.cc b/net/dns/mock_host_resolver.cc
index 6590e6ca..072373a 100644
--- a/net/dns/mock_host_resolver.cc
+++ b/net/dns/mock_host_resolver.cc
@@ -17,7 +17,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/no_destructor.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/pattern.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
diff --git a/net/http/http_auth_preferences.cc b/net/http/http_auth_preferences.cc
index f7c9cb5..64fdf4ae 100644
--- a/net/http/http_auth_preferences.cc
+++ b/net/http/http_auth_preferences.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "base/stl_util.h"
 #include "base/strings/string_split.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index af5aca2..798f85a 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -18,7 +18,6 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/sparse_histogram.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/time/time.h"
diff --git a/net/http/http_security_headers_unittest.cc b/net/http/http_security_headers_unittest.cc
index acd84f8..52fbbda 100644
--- a/net/http/http_security_headers_unittest.cc
+++ b/net/http/http_security_headers_unittest.cc
@@ -5,7 +5,6 @@
 #include <stdint.h>
 
 #include "base/base64.h"
-#include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "crypto/sha2.h"
 #include "net/base/host_port_pair.h"
diff --git a/net/http/http_server_properties_manager.cc b/net/http/http_server_properties_manager.cc
index bc0a134f..611e271 100644
--- a/net/http/http_server_properties_manager.cc
+++ b/net/http/http_server_properties_manager.cc
@@ -9,7 +9,6 @@
 #include "base/bind.h"
 #include "base/feature_list.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/time/tick_clock.h"
 #include "base/values.h"
diff --git a/net/http/http_stream_factory.cc b/net/http/http_stream_factory.cc
index 8a92dd2c..aa425ed2 100644
--- a/net/http/http_stream_factory.cc
+++ b/net/http/http_stream_factory.cc
@@ -10,7 +10,6 @@
 #include "base/check.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
diff --git a/net/http/http_stream_request.cc b/net/http/http_stream_request.cc
index 3a38169..980bc74 100644
--- a/net/http/http_stream_request.cc
+++ b/net/http/http_stream_request.cc
@@ -8,7 +8,6 @@
 
 #include "base/callback.h"
 #include "base/check.h"
-#include "base/stl_util.h"
 #include "net/http/bidirectional_stream_impl.h"
 #include "net/log/net_log_event_type.h"
 #include "net/spdy/bidirectional_stream_spdy_impl.h"
diff --git a/net/proxy_resolution/multi_threaded_proxy_resolver.cc b/net/proxy_resolution/multi_threaded_proxy_resolver.cc
index e121741..a64a298 100644
--- a/net/proxy_resolution/multi_threaded_proxy_resolver.cc
+++ b/net/proxy_resolution/multi_threaded_proxy_resolver.cc
@@ -13,7 +13,6 @@
 #include "base/containers/circular_deque.h"
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread.h"
diff --git a/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc b/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc
index b92df79..0c36dad 100644
--- a/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc
+++ b/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc
@@ -10,7 +10,6 @@
 
 #include "base/bind.h"
 #include "base/run_loop.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc b/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
index 41b4d0c..484525fc 100644
--- a/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
+++ b/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
@@ -15,7 +15,6 @@
 #include "base/run_loop.h"
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
diff --git a/net/quic/crypto_test_utils_chromium.cc b/net/quic/crypto_test_utils_chromium.cc
index d6d4dbb..0b2dd82 100644
--- a/net/quic/crypto_test_utils_chromium.cc
+++ b/net/quic/crypto_test_utils_chromium.cc
@@ -8,7 +8,6 @@
 #include "base/check.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/stl_util.h"
 #include "net/base/net_errors.h"
 #include "net/base/network_isolation_key.h"
 #include "net/base/test_completion_callback.h"
diff --git a/net/quic/quic_chromium_client_session_test.cc b/net/quic/quic_chromium_client_session_test.cc
index 58906e65..a6688ce 100644
--- a/net/quic/quic_chromium_client_session_test.cc
+++ b/net/quic/quic_chromium_client_session_test.cc
@@ -9,7 +9,6 @@
 #include "base/files/file_path.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
-#include "base/stl_util.h"
 #include "base/strings/strcat.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/net/quic/quic_connectivity_probing_manager_test.cc b/net/quic/quic_connectivity_probing_manager_test.cc
index 1bf53d6..6579f64e 100644
--- a/net/quic/quic_connectivity_probing_manager_test.cc
+++ b/net/quic/quic_connectivity_probing_manager_test.cc
@@ -6,7 +6,6 @@
 
 #include <memory>
 
-#include "base/stl_util.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "net/log/test_net_log.h"
 #include "net/quic/address_utils.h"
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index d3645f3e..e8af560 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -12,7 +12,6 @@
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
-#include "base/stl_util.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/test/metrics/histogram_tester.h"
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index 5dd509d..32240182 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -12,7 +12,6 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
-#include "base/stl_util.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
diff --git a/net/reporting/reporting_cache.h b/net/reporting/reporting_cache.h
index d8918013..a8b885c6 100644
--- a/net/reporting/reporting_cache.h
+++ b/net/reporting/reporting_cache.h
@@ -12,7 +12,6 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
-#include "base/stl_util.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "net/base/net_export.h"
diff --git a/net/reporting/reporting_cache_impl.cc b/net/reporting/reporting_cache_impl.cc
index 8b742949..eaeca970e4 100644
--- a/net/reporting/reporting_cache_impl.cc
+++ b/net/reporting/reporting_cache_impl.cc
@@ -10,7 +10,6 @@
 #include <utility>
 
 #include "base/containers/contains.h"
-#include "base/stl_util.h"
 #include "base/time/clock.h"
 #include "base/time/tick_clock.h"
 #include "net/base/url_util.h"
diff --git a/net/reporting/reporting_endpoint_manager.cc b/net/reporting/reporting_endpoint_manager.cc
index c903335..645ab993 100644
--- a/net/reporting/reporting_endpoint_manager.cc
+++ b/net/reporting/reporting_endpoint_manager.cc
@@ -15,7 +15,6 @@
 #include "base/macros.h"
 #include "base/notreached.h"
 #include "base/rand_util.h"
-#include "base/stl_util.h"
 #include "base/time/tick_clock.h"
 #include "net/base/backoff_entry.h"
 #include "net/base/network_isolation_key.h"
diff --git a/net/reporting/reporting_header_parser_unittest.cc b/net/reporting/reporting_header_parser_unittest.cc
index fe0dc053..6991ddac 100644
--- a/net/reporting/reporting_header_parser_unittest.cc
+++ b/net/reporting/reporting_header_parser_unittest.cc
@@ -10,7 +10,6 @@
 
 #include "base/bind.h"
 #include "base/json/json_reader.h"
-#include "base/stl_util.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/test/metrics/histogram_tester.h"
diff --git a/net/socket/unix_domain_server_socket_posix_unittest.cc b/net/socket/unix_domain_server_socket_posix_unittest.cc
index e3fccd42..d2a2a0d 100644
--- a/net/socket/unix_domain_server_socket_posix_unittest.cc
+++ b/net/socket/unix_domain_server_socket_posix_unittest.cc
@@ -11,7 +11,6 @@
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/run_loop.h"
-#include "base/stl_util.h"
 #include "base/test/task_environment.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index f9f04b5..7707999 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -12,7 +12,6 @@
 #include "base/compiler_specific.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/rand_util.h"
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/net/url_request/url_request_filter.cc b/net/url_request/url_request_filter.cc
index 77203dd..7ac17525 100644
--- a/net/url_request/url_request_filter.cc
+++ b/net/url_request/url_request_filter.cc
@@ -5,7 +5,6 @@
 #include "net/url_request/url_request_filter.h"
 
 #include "base/logging.h"
-#include "base/stl_util.h"
 #include "base/task/current_thread.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_job.h"
diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc
index e41a167..10fb0b2a 100644
--- a/pdf/out_of_process_instance.cc
+++ b/pdf/out_of_process_instance.cc
@@ -102,9 +102,6 @@
 constexpr char kJSPreviewPageUrl[] = "url";
 constexpr char kJSPreviewPageIndex[] = "index";
 
-// Editing forms in document (Plugin -> Page)
-constexpr char kJSSetIsEditingType[] = "setIsEditing";
-
 constexpr base::TimeDelta kFindResultCooldown =
     base::TimeDelta::FromMilliseconds(100);
 
@@ -1100,13 +1097,13 @@
     case SaveRequestType::kAnnotation:
       // In annotation mode, assume the user will make edits and prefer saving
       // using the plugin data.
-      pp::PDF::SetPluginCanSave(this, true);
+      SetPluginCanSave(true);
       SaveToBuffer(dict.Get(pp::Var(kJSToken)).AsString());
       break;
     case SaveRequestType::kOriginal:
-      pp::PDF::SetPluginCanSave(this, false);
+      SetPluginCanSave(false);
       SaveToFile(dict.Get(pp::Var(kJSToken)).AsString());
-      pp::PDF::SetPluginCanSave(this, edit_mode());
+      SetPluginCanSave(edit_mode());
       break;
     case SaveRequestType::kEdited:
       SaveToBuffer(dict.Get(pp::Var(kJSToken)).AsString());
@@ -1222,6 +1219,10 @@
   pp::PDF::SetAccessibilityViewportInfo(GetPluginInstance(), &pp_viewport_info);
 }
 
+void OutOfProcessInstance::SetPluginCanSave(bool can_save) {
+  pp::PDF::SetPluginCanSave(this, can_save);
+}
+
 base::WeakPtr<PdfViewPluginBase> OutOfProcessInstance::GetWeakPtr() {
   return weak_factory_.GetWeakPtr();
 }
@@ -1241,15 +1242,6 @@
   return is_print_preview_;
 }
 
-void OutOfProcessInstance::EnteredEditMode() {
-  set_edit_mode(true);
-  pp::PDF::SetPluginCanSave(this, true);
-
-  pp::VarDictionary message;
-  message.Set(kType, kJSSetIsEditingType);
-  PostMessage(message);
-}
-
 void OutOfProcessInstance::SetSelectedText(const std::string& selected_text) {
   pp::PDF::SetSelectedText(this, selected_text.c_str());
 }
diff --git a/pdf/out_of_process_instance.h b/pdf/out_of_process_instance.h
index 6de811b..bb43358 100644
--- a/pdf/out_of_process_instance.h
+++ b/pdf/out_of_process_instance.h
@@ -114,7 +114,6 @@
   void DocumentHasUnsupportedFeature(const std::string& feature) override;
   bool IsPrintPreview() override;
   void SelectionChanged(const gfx::Rect& left, const gfx::Rect& right) override;
-  void EnteredEditMode() override;
   void SetSelectedText(const std::string& selected_text) override;
   void SetLinkUnderCursor(const std::string& link_under_cursor) override;
   bool IsValidLink(const std::string& url) override;
@@ -152,6 +151,7 @@
   void SetAccessibilityViewportInfo(
       const AccessibilityViewportInfo& viewport_info) override;
   void SetContentRestrictions(int content_restrictions) override;
+  void SetPluginCanSave(bool can_save) override;
   void DidStartLoading() override;
   void DidStopLoading() override;
   void OnPrintPreviewLoaded() override;
diff --git a/pdf/pdf_view_plugin_base.cc b/pdf/pdf_view_plugin_base.cc
index 6b19a79e..0339dada 100644
--- a/pdf/pdf_view_plugin_base.cc
+++ b/pdf/pdf_view_plugin_base.cc
@@ -361,6 +361,15 @@
   SendMessage(std::move(message));
 }
 
+void PdfViewPluginBase::EnteredEditMode() {
+  edit_mode_ = true;
+  SetPluginCanSave(true);
+
+  base::Value message(base::Value::Type::DICTIONARY);
+  message.SetStringKey("type", "setIsEditing");
+  SendMessage(std::move(message));
+}
+
 void PdfViewPluginBase::DocumentFocusChanged(bool document_has_focus) {
   base::Value message(base::Value::Type::DICTIONARY);
   message.SetStringKey("type", "documentFocusChanged");
diff --git a/pdf/pdf_view_plugin_base.h b/pdf/pdf_view_plugin_base.h
index e6e02c4..119cc0c8 100644
--- a/pdf/pdf_view_plugin_base.h
+++ b/pdf/pdf_view_plugin_base.h
@@ -86,6 +86,7 @@
   void FormTextFieldFocusChange(bool in_focus) override;
   SkColor GetBackgroundColor() override;
   void SetIsSelecting(bool is_selecting) override;
+  void EnteredEditMode() override;
   void DocumentFocusChanged(bool document_has_focus) override;
 
   // PaintManager::Client
@@ -251,6 +252,10 @@
   // set by `chrome_pdf::ContentRestriction` enum values.
   virtual void SetContentRestrictions(int content_restrictions) = 0;
 
+  // Informs the embedder whether the plugin can handle save commands
+  // internally.
+  virtual void SetPluginCanSave(bool can_save) = 0;
+
   // Sends start/stop loading notifications to the plugin's render frame.
   // TODO(crbug.com/702993): Evaluate whether these methods are needed when the
   // plugin is moved into a renderer process.
diff --git a/pdf/pdf_view_plugin_base_unittest.cc b/pdf/pdf_view_plugin_base_unittest.cc
index d7c8b94..557b940 100644
--- a/pdf/pdf_view_plugin_base_unittest.cc
+++ b/pdf/pdf_view_plugin_base_unittest.cc
@@ -34,6 +34,7 @@
  public:
   // Public for testing.
   using PdfViewPluginBase::ConsumeSaveToken;
+  using PdfViewPluginBase::edit_mode;
   using PdfViewPluginBase::HandleMessage;
 
   MOCK_METHOD(bool, Confirm, (const std::string&), (override));
@@ -114,6 +115,8 @@
 
   MOCK_METHOD(void, SetContentRestrictions, (int), (override));
 
+  MOCK_METHOD(void, SetPluginCanSave, (bool), (override));
+
   MOCK_METHOD(void, DidStartLoading, (), (override));
 
   MOCK_METHOD(void, DidStopLoading, (), (override));
@@ -135,6 +138,16 @@
   FakePdfViewPluginBase fake_plugin_;
 };
 
+TEST_F(PdfViewPluginBaseTest, EnteredEditMode) {
+  fake_plugin_.EnteredEditMode();
+
+  base::Value expected_message(base::Value::Type::DICTIONARY);
+  expected_message.SetStringKey("type", "setIsEditing");
+
+  EXPECT_TRUE(fake_plugin_.edit_mode());
+  EXPECT_EQ(expected_message, fake_plugin_.sent_message());
+}
+
 TEST_F(PdfViewPluginBaseTest, ConsumeSaveToken) {
   const std::string kTokenString("12345678901234567890");
   fake_plugin_.ConsumeSaveToken(kTokenString);
diff --git a/pdf/pdf_view_web_plugin.cc b/pdf/pdf_view_web_plugin.cc
index ee5716b..855a5427 100644
--- a/pdf/pdf_view_web_plugin.cc
+++ b/pdf/pdf_view_web_plugin.cc
@@ -417,8 +417,6 @@
 void PdfViewWebPlugin::SelectionChanged(const gfx::Rect& left,
                                         const gfx::Rect& right) {}
 
-void PdfViewWebPlugin::EnteredEditMode() {}
-
 void PdfViewWebPlugin::SetSelectedText(const std::string& selected_text) {
   selected_text_ = blink::WebString::FromUTF8(selected_text);
   container_wrapper_->TextSelectionChanged(
@@ -566,6 +564,10 @@
   NOTIMPLEMENTED();
 }
 
+void PdfViewWebPlugin::SetPluginCanSave(bool can_save) {
+  NOTIMPLEMENTED();
+}
+
 void PdfViewWebPlugin::DidStartLoading() {
   NOTIMPLEMENTED();
 }
diff --git a/pdf/pdf_view_web_plugin.h b/pdf/pdf_view_web_plugin.h
index f594e5f..0440f8a 100644
--- a/pdf/pdf_view_web_plugin.h
+++ b/pdf/pdf_view_web_plugin.h
@@ -133,7 +133,6 @@
   void DocumentHasUnsupportedFeature(const std::string& feature) override;
   bool IsPrintPreview() override;
   void SelectionChanged(const gfx::Rect& left, const gfx::Rect& right) override;
-  void EnteredEditMode() override;
   void SetSelectedText(const std::string& selected_text) override;
   void SetLinkUnderCursor(const std::string& link_under_cursor) override;
   bool IsValidLink(const std::string& url) override;
@@ -183,6 +182,7 @@
   void SetAccessibilityViewportInfo(
       const AccessibilityViewportInfo& viewport_info) override;
   void SetContentRestrictions(int content_restrictions) override;
+  void SetPluginCanSave(bool can_save) override;
   void DidStartLoading() override;
   void DidStopLoading() override;
   void OnPrintPreviewLoaded() override;
diff --git a/ppapi/proxy/raw_var_data.cc b/ppapi/proxy/raw_var_data.cc
index d3be699..47683ff 100644
--- a/ppapi/proxy/raw_var_data.cc
+++ b/ppapi/proxy/raw_var_data.cc
@@ -10,7 +10,6 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/unsafe_shared_memory_region.h"
-#include "base/stl_util.h"
 #include "ipc/ipc_message.h"
 #include "ppapi/proxy/ppapi_param_traits.h"
 #include "ppapi/shared_impl/array_var.h"
diff --git a/printing/backend/test_print_backend_unittest.cc b/printing/backend/test_print_backend_unittest.cc
index f9e5ba82..bb365bf 100644
--- a/printing/backend/test_print_backend_unittest.cc
+++ b/printing/backend/test_print_backend_unittest.cc
@@ -11,7 +11,6 @@
 #include <vector>
 
 #include "base/memory/scoped_refptr.h"
-#include "base/stl_util.h"
 #include "base/test/gtest_util.h"
 #include "printing/backend/print_backend.h"
 #include "printing/mojom/print.mojom.h"
diff --git a/remoting/client/audio/audio_jitter_buffer.cc b/remoting/client/audio/audio_jitter_buffer.cc
index 43083df..67259cf 100644
--- a/remoting/client/audio/audio_jitter_buffer.cc
+++ b/remoting/client/audio/audio_jitter_buffer.cc
@@ -8,7 +8,6 @@
 #include <string>
 
 #include "base/check_op.h"
-#include "base/stl_util.h"
 
 namespace {
 
diff --git a/remoting/client/audio/audio_player.cc b/remoting/client/audio/audio_player.cc
index aa25ee4a..f14cd59 100644
--- a/remoting/client/audio/audio_player.cc
+++ b/remoting/client/audio/audio_player.cc
@@ -10,7 +10,6 @@
 
 #include "base/callback_helpers.h"
 #include "base/check_op.h"
-#include "base/stl_util.h"
 
 // If queue grows bigger than 150ms we start dropping packets.
 const int kMaxQueueLatencyMs = 150;
diff --git a/remoting/client/jni/jni_runtime_delegate.cc b/remoting/client/jni/jni_runtime_delegate.cc
index d7dd38df..cad38ce 100644
--- a/remoting/client/jni/jni_runtime_delegate.cc
+++ b/remoting/client/jni/jni_runtime_delegate.cc
@@ -13,7 +13,6 @@
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/singleton.h"
-#include "base/stl_util.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/task/thread_pool/thread_pool_instance.h"
 #include "remoting/android/jni_headers/JniInterface_jni.h"
diff --git a/remoting/host/file_transfer/file_transfer_message_handler.cc b/remoting/host/file_transfer/file_transfer_message_handler.cc
index 8c0ce2d1..96c3b89 100644
--- a/remoting/host/file_transfer/file_transfer_message_handler.cc
+++ b/remoting/host/file_transfer/file_transfer_message_handler.cc
@@ -11,7 +11,6 @@
 #include "base/callback_helpers.h"
 #include "base/logging.h"
 #include "base/path_service.h"
-#include "base/stl_util.h"
 #include "net/base/filename_util.h"
 #include "remoting/base/compound_buffer.h"
 #include "remoting/protocol/file_transfer_helpers.h"
diff --git a/remoting/host/input_injector_win.cc b/remoting/host/input_injector_win.cc
index 0e9276f..bb253c1 100644
--- a/remoting/host/input_injector_win.cc
+++ b/remoting/host/input_injector_win.cc
@@ -19,7 +19,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/numerics/ranges.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/win/windows_version.h"
 #include "remoting/base/util.h"
diff --git a/remoting/host/it2me/it2me_native_messaging_host_chromeos.cc b/remoting/host/it2me/it2me_native_messaging_host_chromeos.cc
index 2cc8867..6f261b0 100644
--- a/remoting/host/it2me/it2me_native_messaging_host_chromeos.cc
+++ b/remoting/host/it2me/it2me_native_messaging_host_chromeos.cc
@@ -7,7 +7,6 @@
 #include <memory>
 
 #include "base/lazy_instance.h"
-#include "base/stl_util.h"
 #include "base/task/post_task.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
diff --git a/remoting/host/linux/x11_keyboard_impl.cc b/remoting/host/linux/x11_keyboard_impl.cc
index b32cfa26..9b92cc55 100644
--- a/remoting/host/linux/x11_keyboard_impl.cc
+++ b/remoting/host/linux/x11_keyboard_impl.cc
@@ -4,7 +4,6 @@
 
 #include "remoting/host/linux/x11_keyboard_impl.h"
 
-#include "base/stl_util.h"
 #include "remoting/host/linux/unicode_to_keysym.h"
 #include "ui/gfx/x/future.h"
 #include "ui/gfx/x/xkb.h"
diff --git a/remoting/host/remote_open_url_client.cc b/remoting/host/remote_open_url_client.cc
index fd09779b..d3d788b 100644
--- a/remoting/host/remote_open_url_client.cc
+++ b/remoting/host/remote_open_url_client.cc
@@ -9,6 +9,7 @@
 #include "base/environment.h"
 #include "base/logging.h"
 #include "base/process/launch.h"
+#include "base/time/time.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/platform/named_platform_channel.h"
 #include "mojo/public/cpp/system/invitation.h"
@@ -24,6 +25,8 @@
 constexpr char kChromeRemoteDesktopSessionEnvVar[] =
     "CHROME_REMOTE_DESKTOP_SESSION";
 
+constexpr base::TimeDelta kRequestTimeout = base::TimeDelta::FromSeconds(5);
+
 void OpenOnFallbackBrowserInternal(const GURL& url = GURL()) {
   std::string previous_default_browser =
       HostSettings::GetInstance()->GetString(kLinuxPreviousDefaultWebBrowser);
@@ -68,6 +71,13 @@
 
   url_ = url;
 
+  if (!url_.SchemeIsHTTPOrHTTPS() && !url_.SchemeIs("mailto")) {
+    HOST_LOG << "Unrecognized scheme. Failing back to the previous default "
+             << "browser...";
+    OnOpenUrlResponse(mojom::OpenUrlResult::LOCAL_FALLBACK);
+    return;
+  }
+
   if (!environment_->HasVar(kChromeRemoteDesktopSessionEnvVar)) {
     LOG(WARNING) << "The program is not run on a remote session. "
                  << "Falling back to the previous default browser...";
@@ -94,11 +104,14 @@
   }
 
   remote_.Bind(std::move(pending_remote));
+  timeout_timer_.Start(FROM_HERE, kRequestTimeout, this,
+                       &RemoteOpenUrlClient::OnRequestTimeout);
   remote_->OpenUrl(url_, base::BindOnce(&RemoteOpenUrlClient::OnOpenUrlResponse,
                                         base::Unretained(this)));
 }
 
 void RemoteOpenUrlClient::OnOpenUrlResponse(mojom::OpenUrlResult result) {
+  timeout_timer_.AbandonAndStop();
   switch (result) {
     case mojom::OpenUrlResult::SUCCESS:
       HOST_LOG << "The URL is successfully opened on the client.";
@@ -115,4 +128,9 @@
   std::move(done_).Run();
 }
 
+void RemoteOpenUrlClient::OnRequestTimeout() {
+  LOG(ERROR) << "Timed out waiting for OpenUrl response.";
+  OnOpenUrlResponse(mojom::OpenUrlResult::LOCAL_FALLBACK);
+}
+
 }  // namespace remoting
diff --git a/remoting/host/remote_open_url_client.h b/remoting/host/remote_open_url_client.h
index e2414a23..7b7ba56 100644
--- a/remoting/host/remote_open_url_client.h
+++ b/remoting/host/remote_open_url_client.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "base/callback.h"
+#include "base/timer/timer.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "remoting/host/mojom/remote_url_opener.mojom.h"
 
@@ -35,6 +36,9 @@
 
  private:
   void OnOpenUrlResponse(mojom::OpenUrlResult result);
+  void OnRequestTimeout();
+
+  base::OneShotTimer timeout_timer_;
 
   std::unique_ptr<base::Environment> environment_;
   GURL url_;
diff --git a/remoting/host/setup/me2me_native_messaging_host.cc b/remoting/host/setup/me2me_native_messaging_host.cc
index 1d160263..bc776ea 100644
--- a/remoting/host/setup/me2me_native_messaging_host.cc
+++ b/remoting/host/setup/me2me_native_messaging_host.cc
@@ -16,7 +16,6 @@
 #include "base/json/json_writer.h"
 #include "base/logging.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/stringize_macros.h"
 #include "base/time/time.h"
 #include "base/values.h"
diff --git a/remoting/protocol/jingle_session.cc b/remoting/protocol/jingle_session.cc
index 4b1479f5..74b6d56 100644
--- a/remoting/protocol/jingle_session.cc
+++ b/remoting/protocol/jingle_session.cc
@@ -14,7 +14,6 @@
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/string_split.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
diff --git a/remoting/protocol/webrtc_audio_module.cc b/remoting/protocol/webrtc_audio_module.cc
index a5c111b4..58cc2956 100644
--- a/remoting/protocol/webrtc_audio_module.cc
+++ b/remoting/protocol/webrtc_audio_module.cc
@@ -8,7 +8,6 @@
 
 #include "base/bind.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/timer/timer.h"
 
diff --git a/remoting/signaling/fake_signal_strategy.cc b/remoting/signaling/fake_signal_strategy.cc
index b90b5ad..6227fe5 100644
--- a/remoting/signaling/fake_signal_strategy.cc
+++ b/remoting/signaling/fake_signal_strategy.cc
@@ -10,7 +10,6 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "remoting/signaling/signaling_id_util.h"
diff --git a/sandbox/win/src/sandbox_policy_base.cc b/sandbox/win/src/sandbox_policy_base.cc
index 0c8896a..de3d829 100644
--- a/sandbox/win/src/sandbox_policy_base.cc
+++ b/sandbox/win/src/sandbox_policy_base.cc
@@ -13,7 +13,6 @@
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/stl_util.h"
 #include "base/win/win_util.h"
 #include "base/win/windows_version.h"
 #include "sandbox/win/src/acl.h"
diff --git a/services/network/cors/preflight_controller_unittest.cc b/services/network/cors/preflight_controller_unittest.cc
index 6d7dc43b..d4d8f76 100644
--- a/services/network/cors/preflight_controller_unittest.cc
+++ b/services/network/cors/preflight_controller_unittest.cc
@@ -322,6 +322,25 @@
     if (wait_for_completed_)
       std::move(wait_for_completed_).Run();
   }
+
+  void OnSubresourceWebBundleMetadata(const std::string& devtools_request_id,
+                                      const std::vector<GURL>& urls) override {}
+
+  void OnSubresourceWebBundleMetadataError(
+      const std::string& devtools_request_id,
+      const std::string& error_message) override {}
+
+  void OnSubresourceWebBundleInnerResponse(
+      const std::string& inner_request_devtools_id,
+      const ::GURL& url,
+      const absl::optional<std::string>& bundle_request_devtools_id) override {}
+
+  void OnSubresourceWebBundleInnerResponseError(
+      const std::string& inner_request_devtools_id,
+      const ::GURL& url,
+      const std::string& error_message,
+      const absl::optional<std::string>& bundle_request_devtools_id) override {}
+
   void OnCorsError(const absl::optional<std::string>& devtool_request_id,
                    const absl::optional<::url::Origin>& initiator_origin,
                    const GURL& url,
diff --git a/services/network/public/mojom/url_request.mojom b/services/network/public/mojom/url_request.mojom
index 07d3a3d..31161f3 100644
--- a/services/network/public/mojom/url_request.mojom
+++ b/services/network/public/mojom/url_request.mojom
@@ -579,6 +579,32 @@
     url.mojom.Url url,
     CorsErrorStatus status);
 
+  // Called when parsing the .wbn file has succeeded. The event
+  // contains the information about the web bundle contents.
+  OnSubresourceWebBundleMetadata(
+    string devtool_request_id,
+    array<url.mojom.Url> urls);
+
+  // Called when parsing the .wbn file has failed.
+  OnSubresourceWebBundleMetadataError(
+    string devtool_request_id,
+    string error_message);
+
+  // Called when handling requests for resources within a .wbn file.
+  // Note: this will only be fired for resources that are requested by the
+  // webpage.
+  OnSubresourceWebBundleInnerResponse(
+    string inner_request_devtools_id,
+    url.mojom.Url url,
+    string? bundle_request_devtools_id);
+
+  // Called when an error occurs while handling a request within a .wbn file.
+  OnSubresourceWebBundleInnerResponseError(
+    string inner_request_devtools_id,
+    url.mojom.Url url,
+    string error_message,
+    string? bundle_request_devtools_id);
+
   // Used by the NetworkService to create a copy of this observer.
   // (e.g. when creating an observer for URLLoader from URLLoaderFactory's
   // observer).
diff --git a/services/network/test/mock_devtools_observer.h b/services/network/test/mock_devtools_observer.h
index deef3785..ca48f36 100644
--- a/services/network/test/mock_devtools_observer.h
+++ b/services/network/test/mock_devtools_observer.h
@@ -14,6 +14,7 @@
 #include "services/network/public/mojom/http_raw_headers.mojom-forward.h"
 #include "services/network/public/mojom/ip_address_space.mojom-forward.h"
 #include "services/network/public/mojom/url_request.mojom.h"
+#include "testing/gmock/include/gmock/gmock.h"
 
 namespace network {
 
@@ -66,6 +67,33 @@
       const std::string& devtool_request_id,
       network::mojom::TrustTokenOperationResultPtr result) override;
 
+  MOCK_METHOD(void,
+              OnSubresourceWebBundleMetadata,
+              (const std::string& devtools_request_id,
+               const std::vector<GURL>& urls),
+              (override));
+
+  MOCK_METHOD(void,
+              OnSubresourceWebBundleMetadataError,
+              (const std::string& devtools_request_id,
+               const std::string& error_message),
+              (override));
+
+  MOCK_METHOD(void,
+              OnSubresourceWebBundleInnerResponse,
+              (const std::string& inner_request_devtools_id,
+               const GURL& url,
+               const absl::optional<std::string>& bundle_request_devtools_id),
+              (override));
+
+  MOCK_METHOD(void,
+              OnSubresourceWebBundleInnerResponseError,
+              (const std::string& inner_request_devtools_id,
+               const GURL& url,
+               const std::string& error_message,
+               const absl::optional<std::string>& bundle_request_devtools_id),
+              (override));
+
   void OnCorsError(const absl::optional<std::string>& devtool_request_id,
                    const absl::optional<::url::Origin>& initiator_origin,
                    const GURL& url,
diff --git a/services/network/web_bundle_url_loader_factory.cc b/services/network/web_bundle_url_loader_factory.cc
index 242d89b3..c136ecf 100644
--- a/services/network/web_bundle_url_loader_factory.cc
+++ b/services/network/web_bundle_url_loader_factory.cc
@@ -163,6 +163,7 @@
         request_mode_(request.mode),
         request_initiator_(request.request_initiator),
         request_initiator_origin_lock_(request_initiator_origin_lock),
+        devtools_request_id_(request.devtools_request_id),
         receiver_(this, std::move(loader)),
         client_(std::move(client)),
         trusted_header_client_(std::move(trusted_header_client)) {
@@ -178,6 +179,9 @@
 
   const GURL& url() const { return url_; }
   const mojom::RequestMode& request_mode() const { return request_mode_; }
+  const absl::optional<std::string>& devtools_request_id() const {
+    return devtools_request_id_;
+  }
 
   const absl::optional<url::Origin>& request_initiator() const {
     return request_initiator_;
@@ -278,6 +282,7 @@
   // (via URLLoaderFactory -> WebBundleManager -> WebBundleURLLoaderFactory
   // -> WebBundleURLLoader).
   const absl::optional<url::Origin> request_initiator_origin_lock_;
+  absl::optional<std::string> devtools_request_id_;
   mojo::Receiver<mojom::URLLoader> receiver_;
   mojo::Remote<mojom::URLLoaderClient> client_;
   mojo::Remote<mojom::TrustedHeaderClient> trusted_header_client_;
@@ -616,10 +621,24 @@
     ReportErrorAndCancelPendingLoaders(
         SubresourceWebBundleLoadResult::kMetadataParseError,
         mojom::WebBundleErrorType::kMetadataParseError, error->message);
+    if (devtools_request_id_) {
+      devtools_observer_->OnSubresourceWebBundleMetadataError(
+          *devtools_request_id_, error->message);
+    }
     return;
   }
 
   metadata_ = std::move(metadata);
+  if (devtools_observer_ && devtools_request_id_) {
+    std::vector<GURL> urls;
+    urls.reserve(metadata_->requests.size());
+    for (const auto& item : metadata_->requests) {
+      urls.push_back(item.first);
+    }
+    devtools_observer_->OnSubresourceWebBundleMetadata(*devtools_request_id_,
+                                                       std::move(urls));
+  }
+
   if (data_completed_)
     MaybeReportLoadResult(SubresourceWebBundleLoadResult::kSuccess);
   for (auto loader : pending_loaders_)
@@ -635,11 +654,28 @@
   if (!loader)
     return;
   if (error) {
+    if (devtools_observer_ && loader->devtools_request_id()) {
+      devtools_observer_->OnSubresourceWebBundleInnerResponseError(
+          *loader->devtools_request_id(), loader->url(), error->message,
+          devtools_request_id_);
+    }
     web_bundle_handle_->OnWebBundleError(
         mojom::WebBundleErrorType::kResponseParseError, error->message);
     loader->OnFail(net::ERR_INVALID_WEB_BUNDLE);
     return;
   }
+  if (devtools_observer_) {
+    std::vector<network::mojom::HttpRawHeaderPairPtr> headers;
+    headers.reserve(response->response_headers.size());
+    for (const auto& it : response->response_headers) {
+      headers.push_back(
+          network::mojom::HttpRawHeaderPair::New(it.first, it.second));
+    }
+    if (loader->devtools_request_id()) {
+      devtools_observer_->OnSubresourceWebBundleInnerResponse(
+          *loader->devtools_request_id(), loader->url(), devtools_request_id_);
+    }
+  }
   // Add an artificial "X-Content-Type-Options: "nosniff" header, which is
   // explained at
   // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#name-responses.
diff --git a/services/network/web_bundle_url_loader_factory_unittest.cc b/services/network/web_bundle_url_loader_factory_unittest.cc
index 9aeea80..1d00443 100644
--- a/services/network/web_bundle_url_loader_factory_unittest.cc
+++ b/services/network/web_bundle_url_loader_factory_unittest.cc
@@ -13,6 +13,7 @@
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "services/network/public/mojom/url_loader.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/test/mock_devtools_observer.h"
 #include "services/network/test/test_url_loader_client.h"
 #include "services/network/web_bundle_memory_quota_consumer.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -24,14 +25,24 @@
 
 const char kInitiatorUrl[] = "https://example.com/";
 const char kBundleUrl[] = "https://example.com/bundle.wbn";
+const char kBundleRequestId[] = "bundle-devtools-request-id";
 const char kResourceUrl[] = "https://example.com/";
 const char kResourceUrl2[] = "https://example.com/another";
 const char kResourceUrl3[] = "https://example.com/yetanother";
+const char kResourceRequestId[] = "resource-1-devtools-request-id";
+const char kResourceRequestId2[] = "resource-2-devtools-request-id";
+const char kResourceRequestId3[] = "resource-3-devtools-request-id";
 
 // Cross origin resources
 const char kCrossOriginJsonUrl[] = "https://other.com/resource.json";
 const char kCrossOriginJsUrl[] = "https://other.com/resource.js";
 
+using ::testing::_;
+using ::testing::ElementsAre;
+using ::testing::Eq;
+using ::testing::Optional;
+using ::testing::Pointee;
+
 std::vector<uint8_t> CreateSmallBundle() {
   web_package::test::WebBundleBuilder builder(kResourceUrl,
                                               "" /* manifest_url */);
@@ -157,12 +168,12 @@
     mojo::Remote<mojom::WebBundleHandle> handle;
     handle_ = std::make_unique<TestWebBundleHandle>(
         handle.BindNewPipeAndPassReceiver());
+    devtools_observer_ = std::make_unique<MockDevToolsObserver>();
     factory_ = std::make_unique<WebBundleURLLoaderFactory>(
         GURL(kBundleUrl), std::move(handle),
         /*request_initiator_origin_lock=*/absl::nullopt,
-        std::make_unique<MockMemoryQuotaConsumer>(),
-        /*devtools_observer=*/mojo::PendingRemote<mojom::DevToolsObserver>(),
-        /*devtools_request_id=*/absl::nullopt);
+        std::make_unique<MockMemoryQuotaConsumer>(), devtools_observer_->Bind(),
+        kBundleRequestId);
     factory_->SetBundleStream(std::move(consumer));
   }
 
@@ -179,13 +190,16 @@
     std::unique_ptr<network::TestURLLoaderClient> client;
   };
 
-  network::ResourceRequest CreateRequest(const GURL& url) {
+  network::ResourceRequest CreateRequest(
+      const GURL& url,
+      const std::string& devtools_request_id) {
     network::ResourceRequest request;
     request.url = url;
     request.method = "GET";
     request.request_initiator = url::Origin::Create(GURL(kInitiatorUrl));
     request.web_bundle_token_params = ResourceRequest::WebBundleTokenParams();
     request.web_bundle_token_params->bundle_url = GURL(kBundleUrl);
+    request.devtools_request_id = devtools_request_id;
     return request;
   }
 
@@ -199,8 +213,9 @@
     return result;
   }
 
-  StartRequestResult StartRequest(const GURL& url) {
-    return StartRequest(CreateRequest(url));
+  StartRequestResult StartRequest(const GURL& url,
+                                  const std::string& devtools_request_id) {
+    return StartRequest(CreateRequest(url, devtools_request_id));
   }
 
   void RunUntilBundleError() { handle_->RunUntilBundleError(); }
@@ -211,6 +226,7 @@
   }
 
  protected:
+  std::unique_ptr<MockDevToolsObserver> devtools_observer_;
   std::unique_ptr<WebBundleURLLoaderFactory> factory_;
 
  private:
@@ -224,7 +240,15 @@
   WriteBundle(CreateSmallBundle());
   FinishWritingBundle();
 
-  auto request = StartRequest(GURL(kResourceUrl));
+  EXPECT_CALL(*devtools_observer_,
+              OnSubresourceWebBundleMetadata(kBundleRequestId,
+                                             ElementsAre(GURL(kResourceUrl))));
+  EXPECT_CALL(*devtools_observer_,
+              OnSubresourceWebBundleInnerResponse(
+                  kResourceRequestId, GURL(kResourceUrl),
+                  Optional(std::string(kBundleRequestId))));
+
+  auto request = StartRequest(GURL(kResourceUrl), kResourceRequestId);
   request.client->RunUntilComplete();
 
   EXPECT_EQ(net::OK, request.client->completion_status().error_code);
@@ -241,13 +265,18 @@
 
 TEST_F(WebBundleURLLoaderFactoryTest, MetadataParseError) {
   base::HistogramTester histogram_tester;
-  auto request = StartRequest(GURL(kResourceUrl));
+  auto request = StartRequest(GURL(kResourceUrl), kResourceRequestId);
 
   std::vector<uint8_t> bundle = CreateSmallBundle();
   bundle[4] ^= 1;  // Mutate magic bytes.
   WriteBundle(bundle);
   FinishWritingBundle();
 
+  EXPECT_CALL(*devtools_observer_,
+              OnSubresourceWebBundleMetadataError(kBundleRequestId,
+                                                  Eq("Wrong magic bytes.")));
+  EXPECT_CALL(*devtools_observer_, OnSubresourceWebBundleInnerResponse(_, _, _))
+      .Times(0);
   request.client->RunUntilComplete();
   RunUntilBundleError();
 
@@ -258,7 +287,7 @@
   EXPECT_EQ(last_bundle_error()->second, "Wrong magic bytes.");
 
   // Requests made after metadata parse error should also fail.
-  auto request2 = StartRequest(GURL(kResourceUrl));
+  auto request2 = StartRequest(GURL(kResourceUrl), kResourceRequestId);
   request2.client->RunUntilComplete();
 
   EXPECT_EQ(net::ERR_INVALID_WEB_BUNDLE,
@@ -278,7 +307,16 @@
   WriteBundle(builder.CreateBundle());
   FinishWritingBundle();
 
-  auto request = StartRequest(GURL(kResourceUrl));
+  EXPECT_CALL(*devtools_observer_,
+              OnSubresourceWebBundleMetadata(kBundleRequestId,
+                                             ElementsAre(GURL(kResourceUrl))));
+  EXPECT_CALL(*devtools_observer_,
+              OnSubresourceWebBundleInnerResponseError(
+                  kResourceRequestId, GURL(kResourceUrl),
+                  Eq(":status must be 3 ASCII decimal digits."),
+                  Optional(std::string(kBundleRequestId))));
+
+  auto request = StartRequest(GURL(kResourceUrl), kResourceRequestId);
   request.client->RunUntilComplete();
   RunUntilBundleError();
 
@@ -294,7 +332,14 @@
   WriteBundle(CreateSmallBundle());
   FinishWritingBundle();
 
-  auto request = StartRequest(GURL("https://example.com/no-such-resource"));
+  EXPECT_CALL(*devtools_observer_,
+              OnSubresourceWebBundleMetadata(kBundleRequestId,
+                                             ElementsAre(GURL(kResourceUrl))));
+  EXPECT_CALL(*devtools_observer_, OnSubresourceWebBundleInnerResponse(_, _, _))
+      .Times(0);
+
+  auto request = StartRequest(GURL("https://example.com/no-such-resource"),
+                              kResourceRequestId);
   request.client->RunUntilComplete();
   RunUntilBundleError();
 
@@ -318,7 +363,16 @@
   WriteBundle(builder.CreateBundle());
   FinishWritingBundle();
 
-  auto request = StartRequest(GURL(kResourceUrl));
+  EXPECT_CALL(*devtools_observer_,
+              OnSubresourceWebBundleMetadata(
+                  kBundleRequestId,
+                  ElementsAre(GURL(kResourceUrl), GURL(kResourceUrl2))));
+  EXPECT_CALL(*devtools_observer_,
+              OnSubresourceWebBundleInnerResponse(
+                  kResourceRequestId, GURL(kResourceUrl),
+                  Optional(std::string(kBundleRequestId))));
+
+  auto request = StartRequest(GURL(kResourceUrl), kResourceRequestId);
   request.client->RunUntilComplete();
   RunUntilBundleError();
 
@@ -330,7 +384,7 @@
 }
 
 TEST_F(WebBundleURLLoaderFactoryTest, StartRequestBeforeReadingBundle) {
-  auto request = StartRequest(GURL(kResourceUrl));
+  auto request = StartRequest(GURL(kResourceUrl), kResourceRequestId);
 
   WriteBundle(CreateSmallBundle());
   FinishWritingBundle();
@@ -340,8 +394,8 @@
 }
 
 TEST_F(WebBundleURLLoaderFactoryTest, MultipleRequests) {
-  auto request1 = StartRequest(GURL(kResourceUrl));
-  auto request2 = StartRequest(GURL(kResourceUrl2));
+  auto request1 = StartRequest(GURL(kResourceUrl), kResourceRequestId);
+  auto request2 = StartRequest(GURL(kResourceUrl2), kResourceRequestId2);
 
   std::vector<uint8_t> bundle = CreateLargeBundle();
   // Write the first 10kB of the bundle in which the bundle's metadata and the
@@ -362,11 +416,16 @@
 }
 
 TEST_F(WebBundleURLLoaderFactoryTest, CancelRequest) {
-  auto request_to_complete1 = StartRequest(GURL(kResourceUrl));
-  auto request_to_complete2 = StartRequest(GURL(kResourceUrl2));
-  auto request_to_cancel1 = StartRequest(GURL(kResourceUrl));
-  auto request_to_cancel2 = StartRequest(GURL(kResourceUrl2));
-  auto request_to_cancel3 = StartRequest(GURL(kResourceUrl3));
+  auto request_to_complete1 =
+      StartRequest(GURL(kResourceUrl), kResourceRequestId);
+  auto request_to_complete2 =
+      StartRequest(GURL(kResourceUrl2), kResourceRequestId2);
+  auto request_to_cancel1 =
+      StartRequest(GURL(kResourceUrl), kResourceRequestId);
+  auto request_to_cancel2 =
+      StartRequest(GURL(kResourceUrl2), kResourceRequestId2);
+  auto request_to_cancel3 =
+      StartRequest(GURL(kResourceUrl3), kResourceRequestId3);
 
   // Cancel request before getting metadata.
   request_to_cancel1.loader.reset();
@@ -396,7 +455,7 @@
 
 TEST_F(WebBundleURLLoaderFactoryTest,
        FactoryDestructionCancelsInflightRequests) {
-  auto request = StartRequest(GURL(kResourceUrl));
+  auto request = StartRequest(GURL(kResourceUrl), kResourceRequestId);
 
   factory_ = nullptr;
 
@@ -414,7 +473,7 @@
   WriteBundle(std::move(bundle));
   FinishWritingBundle();
 
-  auto request = StartRequest(GURL(kResourceUrl));
+  auto request = StartRequest(GURL(kResourceUrl), kResourceRequestId);
   request.client->RunUntilComplete();
   RunUntilBundleError();
 
@@ -429,7 +488,7 @@
   WriteBundle(CreateCrossOriginBundle());
   FinishWritingBundle();
 
-  auto request = StartRequest(GURL(kCrossOriginJsonUrl));
+  auto request = StartRequest(GURL(kCrossOriginJsonUrl), kResourceRequestId);
   request.client->RunUntilComplete();
 
   EXPECT_EQ(net::OK, request.client->completion_status().error_code);
@@ -445,7 +504,7 @@
   WriteBundle(CreateCrossOriginBundle());
   FinishWritingBundle();
 
-  auto request = StartRequest(GURL(kCrossOriginJsUrl));
+  auto request = StartRequest(GURL(kCrossOriginJsUrl), kResourceRequestId);
   request.client->RunUntilComplete();
 
   EXPECT_EQ(net::OK, request.client->completion_status().error_code);
@@ -463,7 +522,8 @@
   WriteBundle(CreateSmallBundle());
   FinishWritingBundle();
 
-  network::ResourceRequest url_request = CreateRequest(GURL(kResourceUrl));
+  network::ResourceRequest url_request =
+      CreateRequest(GURL(kResourceUrl), kResourceRequestId);
   url_request.web_bundle_token_params->bundle_url =
       GURL("https://modified-bundle-url.example.com/");
   auto request = StartRequest(url_request);
diff --git a/sql/sandboxed_vfs.cc b/sql/sandboxed_vfs.cc
index 145efad..63daf9b 100644
--- a/sql/sandboxed_vfs.cc
+++ b/sql/sandboxed_vfs.cc
@@ -14,7 +14,6 @@
 #include "base/files/file.h"
 #include "base/no_destructor.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "base/threading/platform_thread.h"
 #include "build/build_config.h"
 #include "sql/initialization.h"
diff --git a/storage/DIR_METADATA b/storage/DIR_METADATA
index f9e9509f..150afdb 100644
--- a/storage/DIR_METADATA
+++ b/storage/DIR_METADATA
@@ -1,10 +1,10 @@
 # Metadata information for this directory.
 #
 # For more information on DIR_METADATA files, see:
-#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
 #
 # For the schema of this file, see Metadata message:
-#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
 
 monorail {
   component: "Blink>Storage"
diff --git a/storage/browser/blob/DIR_METADATA b/storage/browser/blob/DIR_METADATA
index 19266882..30c02fb 100644
--- a/storage/browser/blob/DIR_METADATA
+++ b/storage/browser/blob/DIR_METADATA
@@ -1,10 +1,10 @@
 # Metadata information for this directory.
 #
 # For more information on DIR_METADATA files, see:
-#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
 #
 # For the schema of this file, see Metadata message:
-#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
 
 monorail {
   component: "Blink>Storage>FileAPI"
diff --git a/storage/browser/database/DIR_METADATA b/storage/browser/database/DIR_METADATA
index 67bdd01..5bb86736d 100644
--- a/storage/browser/database/DIR_METADATA
+++ b/storage/browser/database/DIR_METADATA
@@ -1,10 +1,10 @@
 # Metadata information for this directory.
 #
 # For more information on DIR_METADATA files, see:
-#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
 #
 # For the schema of this file, see Metadata message:
-#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
 
 monorail {
   component: "Blink>Storage>WebSQL"
diff --git a/storage/browser/database/database_tracker.cc b/storage/browser/database/database_tracker.cc
index 2bdd932..0203175 100644
--- a/storage/browser/database/database_tracker.cc
+++ b/storage/browser/database/database_tracker.cc
@@ -82,7 +82,11 @@
       db_dir_(is_incognito_
                   ? profile_path_.Append(kIncognitoDatabaseDirectoryName)
                   : profile_path_.Append(kDatabaseDirectoryName)),
-      db_(std::make_unique<sql::Database>()),
+      db_(std::make_unique<sql::Database>(sql::DatabaseOptions{
+          .exclusive_locking = true,
+          .page_size = 4096,
+          .cache_size = 500,
+      })),
       special_storage_policy_(special_storage_policy),
       quota_manager_proxy_(quota_manager_proxy),
       task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
diff --git a/storage/browser/file_system/DIR_METADATA b/storage/browser/file_system/DIR_METADATA
index a32478d..a6d562a 100644
--- a/storage/browser/file_system/DIR_METADATA
+++ b/storage/browser/file_system/DIR_METADATA
@@ -1,10 +1,10 @@
 # Metadata information for this directory.
 #
 # For more information on DIR_METADATA files, see:
-#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
 #
 # For the schema of this file, see Metadata message:
-#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
 
 monorail {
   component: "Blink>Storage>FileSystem"
diff --git a/storage/browser/quota/DIR_METADATA b/storage/browser/quota/DIR_METADATA
index 58c664b..f3365fa 100644
--- a/storage/browser/quota/DIR_METADATA
+++ b/storage/browser/quota/DIR_METADATA
@@ -1,10 +1,10 @@
 # Metadata information for this directory.
 #
 # For more information on DIR_METADATA files, see:
-#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
 #
 # For the schema of this file, see Metadata message:
-#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
 
 monorail {
   component: "Blink>Storage>Quota"
diff --git a/storage/browser/quota/quota_database.cc b/storage/browser/quota/quota_database.cc
index 075ca3a..a331757 100644
--- a/storage/browser/quota/quota_database.cc
+++ b/storage/browser/quota/quota_database.cc
@@ -811,7 +811,11 @@
     return false;
   }
 
-  db_ = std::make_unique<sql::Database>();
+  db_ = std::make_unique<sql::Database>(sql::DatabaseOptions{
+      .exclusive_locking = true,
+      .page_size = 4096,
+      .cache_size = 500,
+  });
   meta_table_ = std::make_unique<sql::MetaTable>();
 
   db_->set_histogram_tag("Quota");
diff --git a/storage/common/database/DIR_METADATA b/storage/common/database/DIR_METADATA
index 67bdd01..5bb86736d 100644
--- a/storage/common/database/DIR_METADATA
+++ b/storage/common/database/DIR_METADATA
@@ -1,10 +1,10 @@
 # Metadata information for this directory.
 #
 # For more information on DIR_METADATA files, see:
-#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
 #
 # For the schema of this file, see Metadata message:
-#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
 
 monorail {
   component: "Blink>Storage>WebSQL"
diff --git a/storage/common/file_system/DIR_METADATA b/storage/common/file_system/DIR_METADATA
index a32478d..a6d562a 100644
--- a/storage/common/file_system/DIR_METADATA
+++ b/storage/common/file_system/DIR_METADATA
@@ -1,10 +1,10 @@
 # Metadata information for this directory.
 #
 # For more information on DIR_METADATA files, see:
-#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
 #
 # For the schema of this file, see Metadata message:
-#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
 
 monorail {
   component: "Blink>Storage>FileSystem"
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index fe4bb08..aea38e9 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -4768,7 +4768,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.73"
+              "revision": "version:91.0.4472.74"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -5005,7 +5005,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.73"
+              "revision": "version:91.0.4472.74"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index c0315001..469ac52 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -53932,7 +53932,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.73"
+              "revision": "version:91.0.4472.74"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -54172,7 +54172,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.73"
+              "revision": "version:91.0.4472.74"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -54476,7 +54476,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.73"
+              "revision": "version:91.0.4472.74"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -54713,7 +54713,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.73"
+              "revision": "version:91.0.4472.74"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -55017,7 +55017,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.73"
+              "revision": "version:91.0.4472.74"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -55254,7 +55254,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.73"
+              "revision": "version:91.0.4472.74"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index f6d617a..e5d97c9c 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -424,7 +424,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M91',
-          'revision': 'version:91.0.4472.73',
+          'revision': 'version:91.0.4472.74',
         }
       ],
     },
@@ -496,7 +496,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M91',
-          'revision': 'version:91.0.4472.73',
+          'revision': 'version:91.0.4472.74',
         }
       ],
     },
@@ -568,7 +568,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M91',
-          'revision': 'version:91.0.4472.73',
+          'revision': 'version:91.0.4472.74',
         }
       ],
     },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index fb8a4910..5a595ce 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -3134,7 +3134,7 @@
                 {
                     "name": "EnabledLaunch",
                     "params": {
-                        "DisabledProviders": "Comcast",
+                        "DisabledProviders": "Quad9Secure",
                         "ShowUi": "true"
                     },
                     "enable_features": [
@@ -5133,102 +5133,42 @@
             ],
             "experiments": [
                 {
-                    "name": "Enabled",
-                    "params": {
-                        "colorful_mic": "false",
-                        "min_agsa_version": "12.15"
-                    },
-                    "enable_features": [
-                        "OmniboxAssistantVoiceSearch"
-                    ],
-                    "disable_features": [
-                        "LensCameraAssistedSearch"
-                    ]
-                },
-                {
-                    "name": "EnabledColorfulMic",
-                    "params": {
-                        "colorful_mic": "true",
-                        "min_agsa_version": "12.15"
-                    },
-                    "enable_features": [
-                        "OmniboxAssistantVoiceSearch"
-                    ],
-                    "disable_features": [
-                        "LensCameraAssistedSearch"
-                    ]
-                },
-                {
-                    "name": "AlwaysMicWithAssistant",
-                    "params": {
-                        "colorful_mic": "false",
-                        "min_agsa_version": "12.15"
-                    },
-                    "enable_features": [
-                        "OmniboxAssistantVoiceSearch",
-                        "VoiceButtonInTopToolbar",
-                        "VoiceSearchAudioCapturePolicy"
-                    ]
-                },
-                {
-                    "name": "AlwaysMicWithoutAssistant",
-                    "params": {
-                        "min_agsa_version": "12.15"
-                    },
-                    "enable_features": [
-                        "VoiceButtonInTopToolbar",
-                        "VoiceSearchAudioCapturePolicy"
-                    ],
-                    "disable_features": [
-                        "OmniboxAssistantVoiceSearch"
-                    ]
-                },
-                {
-                    "name": "EnabledLensThenDefaultMic",
+                    "name": "EnabledLensThenDefaultMicV12",
                     "params": {
                         "disableOnIncognito": "true",
                         "enableCameraAssistedSearchOnLowEndDevice": "false",
                         "enableCameraAssistedSearchOnTablet": "false",
-                        "minAgsaVersionForLensCameraAssistedSearch": "12.15",
+                        "minAgsaVersionForLensCameraAssistedSearch": "12.13.8",
                         "searchBoxStartVariantForLensCameraAssistedSearch": "true"
                     },
                     "enable_features": [
                         "LensCameraAssistedSearch"
-                    ],
-                    "disable_features": [
-                        "OmniboxAssistantVoiceSearch"
                     ]
                 },
                 {
-                    "name": "EnabledDefaultMicThenLens",
+                    "name": "EnabledDefaultMicThenLensV12",
                     "params": {
                         "disableOnIncognito": "true",
                         "enableCameraAssistedSearchOnLowEndDevice": "false",
                         "enableCameraAssistedSearchOnTablet": "false",
-                        "minAgsaVersionForLensCameraAssistedSearch": "12.15",
+                        "minAgsaVersionForLensCameraAssistedSearch": "12.13.8",
                         "searchBoxStartVariantForLensCameraAssistedSearch": "false"
                     },
                     "enable_features": [
                         "LensCameraAssistedSearch"
-                    ],
-                    "disable_features": [
-                        "OmniboxAssistantVoiceSearch"
                     ]
                 },
                 {
-                    "name": "EnabledDefaultMicThenLensOnLowEndDevices",
+                    "name": "EnabledDefaultMicThenLensOnLowEndDevicesV12",
                     "params": {
                         "disableOnIncognito": "true",
                         "enableCameraAssistedSearchOnLowEndDevice": "true",
                         "enableCameraAssistedSearchOnTablet": "false",
-                        "minAgsaVersionForLensCameraAssistedSearch": "12.15",
+                        "minAgsaVersionForLensCameraAssistedSearch": "12.13.8",
                         "searchBoxStartVariantForLensCameraAssistedSearch": "false"
                     },
                     "enable_features": [
                         "LensCameraAssistedSearch"
-                    ],
-                    "disable_features": [
-                        "OmniboxAssistantVoiceSearch"
                     ]
                 }
             ]
@@ -5580,10 +5520,10 @@
                     ]
                 },
                 {
-                    "name": "IPH_TrackingOnly_20210513",
+                    "name": "IPH_TrackingOnly_20210520",
                     "params": {
                         "availability": ">=10",
-                        "colorful_mic": "true",
+                        "colorful_mic": "false",
                         "event_trigger": "name:mic_toolbar_iph_would_have_triggered;comparator:==0;window:90;storage:90",
                         "event_used": "name:successful_voice_search;comparator:==0;window:10;storage:90",
                         "generic_message": "true",
@@ -5606,10 +5546,10 @@
                     ]
                 },
                 {
-                    "name": "IPH_GenericMessage_20210513",
+                    "name": "IPH_GenericMessage_20210520",
                     "params": {
                         "availability": ">=10",
-                        "colorful_mic": "true",
+                        "colorful_mic": "false",
                         "event_trigger": "name:mic_toolbar_iph_triggered;comparator:==0;window:90;storage:90",
                         "event_used": "name:successful_voice_search;comparator:==0;window:10;storage:90",
                         "generic_message": "true",
@@ -5632,10 +5572,10 @@
                     ]
                 },
                 {
-                    "name": "IPH_ExampleQuery_20210513",
+                    "name": "IPH_ExampleQuery_20210520",
                     "params": {
                         "availability": ">=10",
-                        "colorful_mic": "true",
+                        "colorful_mic": "false",
                         "event_trigger": "name:mic_toolbar_iph_triggered;comparator:==0;window:90;storage:90",
                         "event_used": "name:successful_voice_search;comparator:==0;window:10;storage:90",
                         "generic_message": "false",
@@ -5658,9 +5598,9 @@
                     ]
                 },
                 {
-                    "name": "VoiceButton_Actions_20210513",
+                    "name": "VoiceButton_Actions_20210520",
                     "params": {
-                        "colorful_mic": "true",
+                        "colorful_mic": "false",
                         "experiment_id": "47453835",
                         "min_agsa_version": "12.18"
                     },
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index 36576de..dbb7278 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -973,10 +973,5 @@
     "MinimizeAudioProcessingForUnusedOutput",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Makes autofill look across shadow boundaries when collecting form controls to
-// fill.
-const base::Feature kAutofillShadowDOM{"AutofillShadowDOM",
-                                       base::FEATURE_DISABLED_BY_DEFAULT};
-
 }  // namespace features
 }  // namespace blink
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 3f6c476..810be99 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -407,10 +407,6 @@
 BLINK_COMMON_EXPORT extern const base::Feature
     kMinimizeAudioProcessingForUnusedOutput;
 
-// Makes autofill look across shadow boundaries when collecting form controls to
-// fill.
-BLINK_COMMON_EXPORT extern const base::Feature kAutofillShadowDOM;
-
 }  // namespace features
 }  // namespace blink
 
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
index bd3f53d..ea5c928a 100644
--- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl
+++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -5898,6 +5898,50 @@
       # The number of obtained Trust Tokens on a successful "Issuance" operation.
       optional integer issuedTokenCount
 
+  # Fired once when parsing the .wbn file has succeeded.
+  # The event contains the information about the web bundle contents.
+  experimental event subresourceWebBundleMetadataReceived
+    parameters
+      # Request identifier. Used to match this information to another event.
+      RequestId requestId
+      # A list of URLs of resources in the subresource Web Bundle.
+      array of string urls
+
+  # Fired once when parsing the .wbn file has failed.
+  experimental event subresourceWebBundleMetadataError
+    parameters
+      # Request identifier. Used to match this information to another event.
+      RequestId requestId
+      # Error message
+      string errorMessage
+
+  # Fired when handling requests for resources within a .wbn file.
+  # Note: this will only be fired for resources that are requested by the webpage.
+  experimental event subresourceWebBundleInnerResponseParsed
+    parameters
+      # Request identifier of the subresource request
+      RequestId innerRequestId
+      # URL of the subresource resource.
+      string innerRequestURL
+      # Bundle request identifier. Used to match this information to another event.
+      # This made be absent in case when the instrumentation was enabled only
+      # after webbundle was parsed.
+      optional RequestId bundleRequestId
+
+  # Fired when request for resources within a .wbn file failed.
+  experimental event subresourceWebBundleInnerResponseError
+    parameters
+      # Request identifier of the subresource request
+      RequestId innerRequestId
+      # URL of the subresource resource.
+      string innerRequestURL
+      # Error message
+      string errorMessage
+      # Bundle request identifier. Used to match this information to another event.
+      # This made be absent in case when the instrumentation was enabled only
+      # after webbundle was parsed.
+      optional RequestId bundleRequestId
+
   experimental type CrossOriginOpenerPolicyValue extends string
     enum
       SameOrigin
diff --git a/third_party/blink/public/mojom/page/widget.mojom b/third_party/blink/public/mojom/page/widget.mojom
index a512423..ec4bd81 100644
--- a/third_party/blink/public/mojom/page/widget.mojom
+++ b/third_party/blink/public/mojom/page/widget.mojom
@@ -245,6 +245,13 @@
   UpdateTooltipUnderCursor(mojo_base.mojom.String16 tooltip_text,
                            mojo_base.mojom.TextDirection text_direction_hint);
 
+  // Sent by a widget to the browser to set the tooltip text and trigger a
+  // tooltip to show up, aligned with the bounds (in widget-relative DIPS)
+  // passed by parameter. An empty |tooltip_text| will hide the tooltip view.
+  UpdateTooltipFromKeyboard(mojo_base.mojom.String16 tooltip_text,
+                            mojo_base.mojom.TextDirection text_direction_hint,
+                            gfx.mojom.Rect bounds);
+
   // Sent when the text input state is changed. This usually happens when
   // a text input entry is focused.
   TextInputStateChanged(ui.mojom.TextInputState state);
diff --git a/third_party/blink/public/platform/web_theme_engine.h b/third_party/blink/public/platform/web_theme_engine.h
index 928a94f..cf28ea04 100644
--- a/third_party/blink/public/platform/web_theme_engine.h
+++ b/third_party/blink/public/platform/web_theme_engine.h
@@ -194,6 +194,7 @@
     bool is_overlay;
     mojom::ColorScheme scrollbar_theme;
     ScrollbarOrientation orientation;
+    float scale_from_dip;
   };
 #endif
 
diff --git a/third_party/blink/public/web/web_element.h b/third_party/blink/public/web/web_element.h
index 940937d6..1835164 100644
--- a/third_party/blink/public/web/web_element.h
+++ b/third_party/blink/public/web/web_element.h
@@ -85,9 +85,6 @@
   // Returns true if this is an autonomous custom element.
   bool IsAutonomousCustomElement() const;
 
-  // Returns the owning shadow host for this element, if there is one.
-  WebElement OwnerShadowHost() const;
-
   // Returns an author ShadowRoot attached to this element, regardless
   // of open or closed.  This returns null WebNode if this
   // element has no ShadowRoot or has a UA ShadowRoot.
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h
index fd6ce9a..95a7591 100644
--- a/third_party/blink/public/web/web_local_frame.h
+++ b/third_party/blink/public/web/web_local_frame.h
@@ -369,6 +369,9 @@
   // Returns the world ID associated with |script_context|.
   virtual int32_t GetScriptContextWorldId(
       v8::Local<v8::Context> script_context) const = 0;
+  virtual v8::Local<v8::Context> GetScriptContextFromWorldId(
+      v8::Isolate* isolate,
+      int world_id) const = 0;
 
   // Executes script in the context of the current page and returns the value
   // that the script evaluated to with callback. Script execution can be
diff --git a/third_party/blink/renderer/core/css/build.gni b/third_party/blink/renderer/core/css/build.gni
index 0870677..eaab1e8 100644
--- a/third_party/blink/renderer/core/css/build.gni
+++ b/third_party/blink/renderer/core/css/build.gni
@@ -149,6 +149,8 @@
   "css_path_value.h",
   "css_pending_substitution_value.cc",
   "css_pending_substitution_value.h",
+  "css_pending_system_font_value.cc",
+  "css_pending_system_font_value.h",
   "css_primitive_value.cc",
   "css_primitive_value.h",
   "css_primitive_value_mappings.h",
diff --git a/third_party/blink/renderer/core/css/css_pending_system_font_value.cc b/third_party/blink/renderer/core/css/css_pending_system_font_value.cc
new file mode 100644
index 0000000..8425a4bf
--- /dev/null
+++ b/third_party/blink/renderer/core/css/css_pending_system_font_value.cc
@@ -0,0 +1,58 @@
+// Copyright 2021 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/css/css_pending_system_font_value.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h"
+#include "third_party/blink/renderer/core/layout/layout_theme_font_provider.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+namespace cssvalue {
+
+CSSPendingSystemFontValue::CSSPendingSystemFontValue(CSSValueID system_font_id)
+    : CSSValue(kPendingSystemFontValueClass), system_font_id_(system_font_id) {
+  DCHECK(CSSParserFastPaths::IsValidSystemFont(system_font_id));
+}
+
+// static
+CSSPendingSystemFontValue* CSSPendingSystemFontValue::Create(
+    CSSValueID system_font_id) {
+  return MakeGarbageCollected<CSSPendingSystemFontValue>(system_font_id);
+}
+
+const FontSelectionValue& CSSPendingSystemFontValue::ResolveFontStyle() const {
+  return LayoutThemeFontProvider::SystemFontStyle(system_font_id_);
+}
+
+const FontSelectionValue& CSSPendingSystemFontValue::ResolveFontWeight() const {
+  return LayoutThemeFontProvider::SystemFontWeight(system_font_id_);
+}
+
+FontDescription::FamilyDescription
+CSSPendingSystemFontValue::ResolveFontFamily() const {
+  FontDescription::FamilyDescription desc(FontDescription::kNoFamily);
+  desc.family.SetFamily(
+      LayoutThemeFontProvider::SystemFontFamily(system_font_id_));
+  return desc;
+}
+
+FontDescription::Size CSSPendingSystemFontValue::ResolveFontSize(
+    const Document* document) const {
+  return FontDescription::Size(
+      0, LayoutThemeFontProvider::SystemFontSize(system_font_id_, document),
+      true);
+}
+
+String CSSPendingSystemFontValue::CustomCSSText() const {
+  return "";
+}
+
+void CSSPendingSystemFontValue::TraceAfterDispatch(
+    blink::Visitor* visitor) const {
+  CSSValue::TraceAfterDispatch(visitor);
+}
+
+}  // namespace cssvalue
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_pending_system_font_value.h b/third_party/blink/renderer/core/css/css_pending_system_font_value.h
new file mode 100644
index 0000000..33cbefc4
--- /dev/null
+++ b/third_party/blink/renderer/core/css/css_pending_system_font_value.h
@@ -0,0 +1,65 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PENDING_SYSTEM_FONT_VALUE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PENDING_SYSTEM_FONT_VALUE_H_
+
+#include "third_party/blink/renderer/core/css/css_value.h"
+#include "third_party/blink/renderer/core/css_value_keywords.h"
+#include "third_party/blink/renderer/platform/fonts/font_description.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
+
+namespace blink {
+namespace cssvalue {
+
+// The 'font' shorthand accepts some special system font values, like 'caption'
+// (https://drafts.csswg.org/css-fonts/#valdef-font-caption).
+//
+// The resolution of these values into longhands is platform-dependent, and can
+// also depend on user's settings, like the default font size.
+//
+// The CSS parser wouldn't be able to resolve these, since we need a |Document|
+// in order to retrieve the settings, and |CSSParserContext::GetDocument()|
+// would be null when system fonts are set in UA styles.
+//
+// So the parser sets all the font longhands to a |CSSPendingSystemFontValue|,
+// and the resolution is deferred until computed-value time, when we can use
+// |StyleResolverState::GetDocument()|.
+class CSSPendingSystemFontValue : public CSSValue {
+ public:
+  static CSSPendingSystemFontValue* Create(CSSValueID);
+
+  explicit CSSPendingSystemFontValue(CSSValueID);
+
+  CSSValueID SystemFontId() const { return system_font_id_; }
+
+  const FontSelectionValue& ResolveFontStyle() const;
+  const FontSelectionValue& ResolveFontWeight() const;
+  FontDescription::FamilyDescription ResolveFontFamily() const;
+  FontDescription::Size ResolveFontSize(const Document*) const;
+
+  bool Equals(const CSSPendingSystemFontValue& other) const {
+    return system_font_id_ == other.system_font_id_;
+  }
+
+  String CustomCSSText() const;
+
+  void TraceAfterDispatch(blink::Visitor*) const;
+
+ private:
+  const CSSValueID system_font_id_;
+};
+
+}  // namespace cssvalue
+
+template <>
+struct DowncastTraits<cssvalue::CSSPendingSystemFontValue> {
+  static bool AllowFrom(const CSSValue& value) {
+    return value.IsPendingSystemFontValue();
+  }
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PENDING_SYSTEM_FONT_VALUE_H_
diff --git a/third_party/blink/renderer/core/css/css_value.cc b/third_party/blink/renderer/core/css/css_value.cc
index bb2cb20d..217f2d5 100644
--- a/third_party/blink/renderer/core/css/css_value.cc
+++ b/third_party/blink/renderer/core/css/css_value.cc
@@ -65,6 +65,7 @@
 #include "third_party/blink/renderer/core/css/css_paint_value.h"
 #include "third_party/blink/renderer/core/css/css_path_value.h"
 #include "third_party/blink/renderer/core/css/css_pending_substitution_value.h"
+#include "third_party/blink/renderer/core/css/css_pending_system_font_value.h"
 #include "third_party/blink/renderer/core/css/css_primitive_value.h"
 #include "third_party/blink/renderer/core/css/css_quad_value.h"
 #include "third_party/blink/renderer/core/css/css_ray_value.h"
@@ -278,6 +279,9 @@
       case kPendingSubstitutionValueClass:
         return CompareCSSValues<cssvalue::CSSPendingSubstitutionValue>(*this,
                                                                        other);
+      case kPendingSystemFontValueClass:
+        return CompareCSSValues<cssvalue::CSSPendingSystemFontValue>(*this,
+                                                                     other);
       case kInvalidVariableValueClass:
         return CompareCSSValues<CSSInvalidVariableValue>(*this, other);
       case kCyclicVariableValueClass:
@@ -404,6 +408,8 @@
       return To<CSSCustomPropertyDeclaration>(this)->CustomCSSText();
     case kPendingSubstitutionValueClass:
       return To<cssvalue::CSSPendingSubstitutionValue>(this)->CustomCSSText();
+    case kPendingSystemFontValueClass:
+      return To<cssvalue::CSSPendingSystemFontValue>(this)->CustomCSSText();
     case kInvalidVariableValueClass:
       return To<CSSInvalidVariableValue>(this)->CustomCSSText();
     case kCyclicVariableValueClass:
@@ -588,6 +594,10 @@
       To<cssvalue::CSSPendingSubstitutionValue>(this)
           ->~CSSPendingSubstitutionValue();
       return;
+    case kPendingSystemFontValueClass:
+      To<cssvalue::CSSPendingSystemFontValue>(this)
+          ->~CSSPendingSystemFontValue();
+      return;
     case kInvalidVariableValueClass:
       To<CSSInvalidVariableValue>(this)->~CSSInvalidVariableValue();
       return;
@@ -776,6 +786,10 @@
       To<cssvalue::CSSPendingSubstitutionValue>(this)->TraceAfterDispatch(
           visitor);
       return;
+    case kPendingSystemFontValueClass:
+      To<cssvalue::CSSPendingSystemFontValue>(this)->TraceAfterDispatch(
+          visitor);
+      return;
     case kInvalidVariableValueClass:
       To<CSSInvalidVariableValue>(this)->TraceAfterDispatch(visitor);
       return;
diff --git a/third_party/blink/renderer/core/css/css_value.h b/third_party/blink/renderer/core/css/css_value.h
index a26ea33..abcd472 100644
--- a/third_party/blink/renderer/core/css/css_value.h
+++ b/third_party/blink/renderer/core/css/css_value.h
@@ -166,6 +166,9 @@
   bool IsPendingSubstitutionValue() const {
     return class_type_ == kPendingSubstitutionValueClass;
   }
+  bool IsPendingSystemFontValue() const {
+    return class_type_ == kPendingSystemFontValueClass;
+  }
   bool IsInvalidVariableValue() const {
     return class_type_ == kInvalidVariableValueClass ||
            class_type_ == kCyclicVariableValueClass;
@@ -265,6 +268,7 @@
     kVariableReferenceClass,
     kCustomPropertyDeclarationClass,
     kPendingSubstitutionValueClass,
+    kPendingSystemFontValueClass,
     kInvalidVariableValueClass,
     kCyclicVariableValueClass,
     kLayoutFunctionClass,
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
index e2718da..94ad881 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
+++ b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
@@ -1118,6 +1118,10 @@
   }
 }
 
+bool CSSParserFastPaths::IsValidSystemFont(CSSValueID value_id) {
+  return value_id >= CSSValueID::kCaption && value_id <= CSSValueID::kStatusBar;
+}
+
 static CSSValue* ParseKeywordValue(CSSPropertyID property_id,
                                    const String& string,
                                    CSSParserMode parser_mode) {
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h
index 85a29d9..faf577c 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h
+++ b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h
@@ -32,6 +32,8 @@
                                              CSSValueID,
                                              CSSParserMode);
 
+  static bool IsValidSystemFont(CSSValueID);
+
   static CSSValue* ParseColor(const String&, CSSParserMode);
 };
 
diff --git a/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc b/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
index 485b157..30c53b8c 100644
--- a/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
@@ -4,10 +4,10 @@
 
 #include "base/stl_util.h"
 #include "third_party/blink/renderer/core/css/css_content_distribution_value.h"
-#include "third_party/blink/renderer/core/css/css_font_family_value.h"
 #include "third_party/blink/renderer/core/css/css_identifier_value.h"
 #include "third_party/blink/renderer/core/css/css_initial_value.h"
 #include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
+#include "third_party/blink/renderer/core/css/css_pending_system_font_value.h"
 #include "third_party/blink/renderer/core/css/css_primitive_value_mappings.h"
 #include "third_party/blink/renderer/core/css/css_property_value.h"
 #include "third_party/blink/renderer/core/css/css_value_pair.h"
@@ -23,7 +23,6 @@
 #include "third_party/blink/renderer/core/css/properties/shorthands.h"
 #include "third_party/blink/renderer/core/css/zoom_adjusted_pixel_value.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/core/layout/layout_theme_font_provider.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/core/style_property_shorthand.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -979,69 +978,14 @@
                        CSSParserTokenRange& range,
                        HeapVector<CSSPropertyValue, 256>& properties) {
   CSSValueID system_font_id = range.ConsumeIncludingWhitespace().Id();
-  DCHECK_GE(system_font_id, CSSValueID::kCaption);
-  DCHECK_LE(system_font_id, CSSValueID::kStatusBar);
+  DCHECK(CSSParserFastPaths::IsValidSystemFont(system_font_id));
   if (!range.AtEnd())
     return false;
 
-  FontSelectionValue font_slope = NormalSlopeValue();
-  FontSelectionValue font_weight = NormalWeightValue();
-  float font_size = 0;
-  AtomicString font_family;
-  LayoutThemeFontProvider::SystemFont(system_font_id, font_slope, font_weight,
-                                      font_size, font_family);
-
-  css_parsing_utils::AddProperty(
-      CSSPropertyID::kFontStyle, CSSPropertyID::kFont,
-      *CSSIdentifierValue::Create(font_slope == ItalicSlopeValue()
-                                      ? CSSValueID::kItalic
-                                      : CSSValueID::kNormal),
-      important, css_parsing_utils::IsImplicitProperty::kNotImplicit,
+  css_parsing_utils::AddExpandedPropertyForValue(
+      CSSPropertyID::kFont,
+      *cssvalue::CSSPendingSystemFontValue::Create(system_font_id), important,
       properties);
-  css_parsing_utils::AddProperty(
-      CSSPropertyID::kFontWeight, CSSPropertyID::kFont,
-      *CSSNumericLiteralValue::Create(font_weight,
-                                      CSSPrimitiveValue::UnitType::kNumber),
-      important, css_parsing_utils::IsImplicitProperty::kNotImplicit,
-      properties);
-  css_parsing_utils::AddProperty(
-      CSSPropertyID::kFontSize, CSSPropertyID::kFont,
-      *CSSNumericLiteralValue::Create(font_size,
-                                      CSSPrimitiveValue::UnitType::kPixels),
-      important, css_parsing_utils::IsImplicitProperty::kNotImplicit,
-      properties);
-
-  CSSValueList* font_family_list = CSSValueList::CreateCommaSeparated();
-  font_family_list->Append(*CSSFontFamilyValue::Create(font_family));
-  css_parsing_utils::AddProperty(
-      CSSPropertyID::kFontFamily, CSSPropertyID::kFont, *font_family_list,
-      important, css_parsing_utils::IsImplicitProperty::kNotImplicit,
-      properties);
-
-  css_parsing_utils::AddProperty(
-      CSSPropertyID::kFontStretch, CSSPropertyID::kFont,
-      *CSSIdentifierValue::Create(CSSValueID::kNormal), important,
-      css_parsing_utils::IsImplicitProperty::kNotImplicit, properties);
-  css_parsing_utils::AddProperty(
-      CSSPropertyID::kFontVariantCaps, CSSPropertyID::kFont,
-      *CSSIdentifierValue::Create(CSSValueID::kNormal), important,
-      css_parsing_utils::IsImplicitProperty::kNotImplicit, properties);
-  css_parsing_utils::AddProperty(
-      CSSPropertyID::kFontVariantLigatures, CSSPropertyID::kFont,
-      *CSSIdentifierValue::Create(CSSValueID::kNormal), important,
-      css_parsing_utils::IsImplicitProperty::kNotImplicit, properties);
-  css_parsing_utils::AddProperty(
-      CSSPropertyID::kFontVariantNumeric, CSSPropertyID::kFont,
-      *CSSIdentifierValue::Create(CSSValueID::kNormal), important,
-      css_parsing_utils::IsImplicitProperty::kNotImplicit, properties);
-  css_parsing_utils::AddProperty(
-      CSSPropertyID::kFontVariantEastAsian, CSSPropertyID::kFont,
-      *CSSIdentifierValue::Create(CSSValueID::kNormal), important,
-      css_parsing_utils::IsImplicitProperty::kNotImplicit, properties);
-  css_parsing_utils::AddProperty(
-      CSSPropertyID::kLineHeight, CSSPropertyID::kFont,
-      *CSSIdentifierValue::Create(CSSValueID::kNormal), important,
-      css_parsing_utils::IsImplicitProperty::kNotImplicit, properties);
   return true;
 }
 
@@ -1186,8 +1130,7 @@
                           const CSSParserLocalContext&,
                           HeapVector<CSSPropertyValue, 256>& properties) const {
   const CSSParserToken& token = range.Peek();
-  if (token.Id() >= CSSValueID::kCaption &&
-      token.Id() <= CSSValueID::kStatusBar)
+  if (CSSParserFastPaths::IsValidSystemFont(token.Id()))
     return ConsumeSystemFont(important, range, properties);
   return ConsumeFont(important, range, context, properties);
 }
diff --git a/third_party/blink/renderer/core/css/resolver/font_style_resolver.cc b/third_party/blink/renderer/core/css/resolver/font_style_resolver.cc
index cbac112b..25424675 100644
--- a/third_party/blink/renderer/core/css/resolver/font_style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/font_style_resolver.cc
@@ -27,7 +27,7 @@
   if (property_set.HasProperty(CSSPropertyID::kFontSize)) {
     builder.SetSize(StyleBuilderConverterBase::ConvertFontSize(
         *property_set.GetPropertyCSSValue(CSSPropertyID::kFontSize),
-        conversionData, FontDescription::Size(0, 0.0f, false)));
+        conversionData, FontDescription::Size(0, 0.0f, false), nullptr));
   }
 
   // CSSPropertyID::kFontFamily
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
index 985326a..6afcd74e 100644
--- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
@@ -45,6 +45,7 @@
 #include "third_party/blink/renderer/core/css/css_math_function_value.h"
 #include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
 #include "third_party/blink/renderer/core/css/css_path_value.h"
+#include "third_party/blink/renderer/core/css/css_pending_system_font_value.h"
 #include "third_party/blink/renderer/core/css/css_primitive_value_mappings.h"
 #include "third_party/blink/renderer/core/css/css_quad_value.h"
 #include "third_party/blink/renderer/core/css/css_reflect_value.h"
@@ -221,6 +222,10 @@
     const CSSValue& value,
     FontBuilder* font_builder,
     const Document* document_for_count) {
+  if (const auto* system_font =
+          DynamicTo<cssvalue::CSSPendingSystemFontValue>(value))
+    return system_font->ResolveFontFamily();
+
   FontDescription::FamilyDescription desc(FontDescription::kNoFamily);
   FontFamily* curr_family = nullptr;
 
@@ -388,7 +393,8 @@
 FontDescription::Size StyleBuilderConverterBase::ConvertFontSize(
     const CSSValue& value,
     const CSSToLengthConversionData& conversion_data,
-    FontDescription::Size parent_size) {
+    FontDescription::Size parent_size,
+    const Document* document) {
   if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
     CSSValueID value_id = identifier_value->GetValueID();
     if (FontSizeFunctions::IsValidValueID(value_id)) {
@@ -403,6 +409,10 @@
     return FontBuilder::InitialSize();
   }
 
+  if (const auto* system_font =
+          DynamicTo<cssvalue::CSSPendingSystemFontValue>(value))
+    return system_font->ResolveFontSize(document);
+
   const auto& primitive_value = To<CSSPrimitiveValue>(value);
   if (primitive_value.IsPercentage()) {
     return FontDescription::Size(
@@ -439,7 +449,7 @@
   }
 
   return StyleBuilderConverterBase::ConvertFontSize(
-      value, state.FontSizeConversionData(), parent_size);
+      value, state.FontSizeConversionData(), parent_size, &state.GetDocument());
 }
 
 float StyleBuilderConverter::ConvertFontSizeAdjust(StyleResolverState& state,
@@ -486,6 +496,10 @@
         break;
     }
   }
+
+  if (value.IsPendingSystemFontValue())
+    return NormalWidthValue();
+
   NOTREACHED();
   return NormalWidthValue();
 }
@@ -511,6 +525,11 @@
         NOTREACHED();
         return NormalSlopeValue();
     }
+  } else if (const auto* system_font =
+                 DynamicTo<cssvalue::CSSPendingSystemFontValue>(value)) {
+    if (system_font->ResolveFontStyle() == ItalicSlopeValue())
+      return ItalicSlopeValue();
+    return NormalSlopeValue();
   } else if (const auto* style_range_value =
                  DynamicTo<cssvalue::CSSFontStyleRangeValue>(value)) {
     const CSSValueList* values = style_range_value->GetObliqueValues();
@@ -546,6 +565,10 @@
       return clampTo<FontSelectionValue>(primitive_value->GetFloatValue());
   }
 
+  if (const auto* system_font =
+          DynamicTo<cssvalue::CSSPendingSystemFontValue>(value))
+    return system_font->ResolveFontWeight();
+
   if (const auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
     switch (identifier_value->GetValueID()) {
       case CSSValueID::kNormal:
@@ -574,6 +597,9 @@
 
 FontDescription::FontVariantCaps
 StyleBuilderConverterBase::ConvertFontVariantCaps(const CSSValue& value) {
+  if (value.IsPendingSystemFontValue())
+    return FontDescription::kCapsNormal;
+
   CSSValueID value_id = To<CSSIdentifierValue>(value).GetValueID();
   switch (value_id) {
     case CSSValueID::kNormal:
@@ -641,6 +667,9 @@
     return ligatures;
   }
 
+  if (value.IsPendingSystemFontValue())
+    return FontDescription::VariantLigatures();
+
   if (To<CSSIdentifierValue>(value).GetValueID() == CSSValueID::kNone) {
     return FontDescription::VariantLigatures(
         FontDescription::kDisabledLigaturesState);
@@ -658,6 +687,9 @@
     return FontVariantNumeric();
   }
 
+  if (value.IsPendingSystemFontValue())
+    return FontVariantNumeric();
+
   FontVariantNumeric variant_numeric;
   for (const CSSValue* feature : To<CSSValueList>(value)) {
     switch (To<CSSIdentifierValue>(feature)->GetValueID()) {
@@ -704,6 +736,9 @@
     return FontVariantEastAsian();
   }
 
+  if (value.IsPendingSystemFontValue())
+    return FontVariantEastAsian();
+
   FontVariantEastAsian variant_east_asian;
   for (const CSSValue* feature : To<CSSValueList>(value)) {
     switch (To<CSSIdentifierValue>(feature)->GetValueID()) {
@@ -1228,6 +1263,9 @@
     }
   }
 
+  if (value.IsPendingSystemFontValue())
+    return ComputedStyleInitialValues::InitialLineHeight();
+
   DCHECK_EQ(To<CSSIdentifierValue>(value).GetValueID(), CSSValueID::kNormal);
   return ComputedStyleInitialValues::InitialLineHeight();
 }
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.h b/third_party/blink/renderer/core/css/resolver/style_builder_converter.h
index b864aef..8059584 100644
--- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.h
+++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.h
@@ -89,7 +89,8 @@
   static FontDescription::Size ConvertFontSize(
       const CSSValue&,
       const CSSToLengthConversionData&,
-      FontDescription::Size parent_size);
+      FontDescription::Size parent_size,
+      const Document*);
 };
 
 // Note that we assume the parser only allows valid CSSValue types.
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc
index f2d13ea..882782e 100644
--- a/third_party/blink/renderer/core/css/style_engine_test.cc
+++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -3832,4 +3832,50 @@
   EXPECT_EQ("1. ", GetListMarkerText(shadow_bar));
 }
 
+TEST_F(StyleEngineTest, SystemFontsObeyDefaultFontSize) {
+  // <input> get assigned "font: -webkit-small-control" in the UA sheet.
+  Element* body = GetDocument().body();
+  body->setInnerHTML("<input>");
+  Element* input = GetDocument().QuerySelector("input");
+
+  // Test the standard font sizes that can be chosen in chrome://settings/
+  for (int fontSize : {9, 12, 16, 20, 24}) {
+    GetDocument().GetSettings()->SetDefaultFontSize(fontSize);
+    UpdateAllLifecyclePhases();
+    EXPECT_EQ(fontSize, body->GetComputedStyle()->FontSize());
+    EXPECT_EQ(fontSize - 3, input->GetComputedStyle()->FontSize());
+  }
+
+  // Now test degenerate cases
+  GetDocument().GetSettings()->SetDefaultFontSize(-1);
+  UpdateAllLifecyclePhases();
+  EXPECT_EQ(1, body->GetComputedStyle()->FontSize());
+  EXPECT_EQ(1, input->GetComputedStyle()->FontSize());
+
+  GetDocument().GetSettings()->SetDefaultFontSize(0);
+  UpdateAllLifecyclePhases();
+  EXPECT_EQ(1, body->GetComputedStyle()->FontSize());
+  EXPECT_EQ(13, input->GetComputedStyle()->FontSize());
+
+  GetDocument().GetSettings()->SetDefaultFontSize(1);
+  UpdateAllLifecyclePhases();
+  EXPECT_EQ(1, body->GetComputedStyle()->FontSize());
+  EXPECT_EQ(1, input->GetComputedStyle()->FontSize());
+
+  GetDocument().GetSettings()->SetDefaultFontSize(2);
+  UpdateAllLifecyclePhases();
+  EXPECT_EQ(2, body->GetComputedStyle()->FontSize());
+  EXPECT_EQ(2, input->GetComputedStyle()->FontSize());
+
+  GetDocument().GetSettings()->SetDefaultFontSize(3);
+  UpdateAllLifecyclePhases();
+  EXPECT_EQ(3, body->GetComputedStyle()->FontSize());
+  EXPECT_EQ(0, input->GetComputedStyle()->FontSize());
+
+  GetDocument().GetSettings()->SetDefaultFontSize(12345);
+  UpdateAllLifecyclePhases();
+  EXPECT_EQ(10000, body->GetComputedStyle()->FontSize());
+  EXPECT_EQ(10000, input->GetComputedStyle()->FontSize());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/style_property_serializer.cc b/third_party/blink/renderer/core/css/style_property_serializer.cc
index d536af0..099bc27 100644
--- a/third_party/blink/renderer/core/css/style_property_serializer.cc
+++ b/third_party/blink/renderer/core/css/style_property_serializer.cc
@@ -31,6 +31,7 @@
 #include "third_party/blink/renderer/core/css/css_identifier_value.h"
 #include "third_party/blink/renderer/core/css/css_markup.h"
 #include "third_party/blink/renderer/core/css/css_pending_substitution_value.h"
+#include "third_party/blink/renderer/core/css/css_pending_system_font_value.h"
 #include "third_party/blink/renderer/core/css/css_value_pair.h"
 #include "third_party/blink/renderer/core/css/css_value_pool.h"
 #include "third_party/blink/renderer/core/css/properties/css_property.h"
@@ -730,6 +731,26 @@
       east_asian_value->IsValueList())
     return g_empty_string;
 
+  const StylePropertyShorthand& shorthand = fontShorthand();
+  const CSSProperty** longhands = shorthand.properties();
+  unsigned length = shorthand.length();
+  const CSSValue* first = property_set_.GetPropertyCSSValue(*longhands[0]);
+  if (const auto* system_font =
+          DynamicTo<cssvalue::CSSPendingSystemFontValue>(first)) {
+    for (unsigned i = 1; i < length; i++) {
+      const CSSValue* value = property_set_.GetPropertyCSSValue(*longhands[i]);
+      if (!DataEquivalent(first, value))
+        return g_empty_string;
+    }
+    return getValueName(system_font->SystemFontId());
+  } else {
+    for (unsigned i = 1; i < length; i++) {
+      const CSSValue* value = property_set_.GetPropertyCSSValue(*longhands[i]);
+      if (value->IsPendingSystemFontValue())
+        return g_empty_string;
+    }
+  }
+
   StringBuilder result;
   AppendFontLonghandValueIfNotNormal(GetCSSPropertyFontStyle(), result);
 
diff --git a/third_party/blink/renderer/core/dom/node_traversal.cc b/third_party/blink/renderer/core/dom/node_traversal.cc
index 3c1b16a..90ca86e0 100644
--- a/third_party/blink/renderer/core/dom/node_traversal.cc
+++ b/third_party/blink/renderer/core/dom/node_traversal.cc
@@ -47,14 +47,10 @@
                                          const Node* stay_within) {
   if (Node* next = current.PseudoAwareFirstChild())
     return next;
-  if (current == stay_within)
-    return nullptr;
-  if (Node* next = current.PseudoAwareNextSibling())
-    return next;
-  for (Node& parent : AncestorsOf(current)) {
-    if (parent == stay_within)
+  for (Node& node : InclusiveAncestorsOf(current)) {
+    if (node == stay_within)
       return nullptr;
-    if (Node* next = parent.PseudoAwareNextSibling())
+    if (Node* next = node.PseudoAwareNextSibling())
       return next;
   }
   return nullptr;
@@ -63,14 +59,10 @@
 Node* NodeTraversal::NextIncludingPseudoSkippingChildren(
     const Node& current,
     const Node* stay_within) {
-  if (current == stay_within)
-    return nullptr;
-  if (Node* next = current.PseudoAwareNextSibling())
-    return next;
-  for (Node& parent : AncestorsOf(current)) {
-    if (parent == stay_within)
+  for (Node& node : InclusiveAncestorsOf(current)) {
+    if (node == stay_within)
       return nullptr;
-    if (Node* next = parent.PseudoAwareNextSibling())
+    if (Node* next = node.PseudoAwareNextSibling())
       return next;
   }
   return nullptr;
@@ -124,17 +116,25 @@
   return current.parentNode();
 }
 
+Node* NodeTraversal::PreviousAbsoluteSiblingIncludingPseudo(
+    const Node& current,
+    const Node* stay_within) {
+  for (Node& iter : InclusiveAncestorsOf(current)) {
+    if (iter == stay_within)
+      return nullptr;
+    if (Node* result = iter.PseudoAwarePreviousSibling())
+      return result;
+  }
+  return nullptr;
+}
+
 Node* NodeTraversal::PreviousAbsoluteSibling(const Node& current,
                                              const Node* stay_within) {
-  if (current == stay_within)
-    return nullptr;
-  if (current.previousSibling())
-    return current.previousSibling();
-  for (Node& parent : AncestorsOf(current)) {
-    if (parent == stay_within)
+  for (Node& node : InclusiveAncestorsOf(current)) {
+    if (node == stay_within)
       return nullptr;
-    if (parent.previousSibling())
-      return parent.previousSibling();
+    if (Node* prev = node.previousSibling())
+      return prev;
   }
   return nullptr;
 }
diff --git a/third_party/blink/renderer/core/dom/node_traversal.h b/third_party/blink/renderer/core/dom/node_traversal.h
index 25ce73e..862f37c 100644
--- a/third_party/blink/renderer/core/dom/node_traversal.h
+++ b/third_party/blink/renderer/core/dom/node_traversal.h
@@ -95,7 +95,11 @@
   CORE_EXPORT static Node* NextIncludingPseudo(
       const Node&,
       const Node* stay_within = nullptr);
-  static Node* NextIncludingPseudoSkippingChildren(
+  // See comment for |FlatTreeTraversal::PreviousAbsoluteSibling| for details.
+  CORE_EXPORT static Node* PreviousAbsoluteSiblingIncludingPseudo(
+      const Node&,
+      const Node* stay_within = nullptr);
+  CORE_EXPORT static Node* NextIncludingPseudoSkippingChildren(
       const Node&,
       const Node* stay_within = nullptr);
 
diff --git a/third_party/blink/renderer/core/exported/web_element.cc b/third_party/blink/renderer/core/exported/web_element.cc
index 7d6faf2..1829c4f8 100644
--- a/third_party/blink/renderer/core/exported/web_element.cc
+++ b/third_party/blink/renderer/core/exported/web_element.cc
@@ -148,13 +148,6 @@
   return WebNode(root);
 }
 
-WebElement WebElement::OwnerShadowHost() const {
-  if (auto* host = ConstUnwrap<Element>()->OwnerShadowHost()) {
-    return WebElement(host);
-  }
-  return WebElement();
-}
-
 WebNode WebElement::OpenOrClosedShadowRoot() {
   if (IsNull())
     return WebNode();
diff --git a/third_party/blink/renderer/core/exported/web_form_element.cc b/third_party/blink/renderer/core/exported/web_form_element.cc
index a0bd1676..3940883 100644
--- a/third_party/blink/renderer/core/exported/web_form_element.cc
+++ b/third_party/blink/renderer/core/exported/web_form_element.cc
@@ -66,8 +66,7 @@
     const {
   const HTMLFormElement* form = ConstUnwrap<HTMLFormElement>();
   Vector<WebFormControlElement> form_control_elements;
-  for (const auto& element :
-       form->ListedElements(/*include_shadow_trees=*/true)) {
+  for (const auto& element : form->ListedElements()) {
     if (auto* form_control =
             blink::DynamicTo<HTMLFormControlElement>(element.Get())) {
       form_control_elements.push_back(form_control);
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
index 68c463e2..c1c0872 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -854,6 +854,11 @@
     const String& tooltip_text,
     base::i18n::TextDirection text_direction_hint) {}
 
+void TestWebFrameWidgetHost::UpdateTooltipFromKeyboard(
+    const String& tooltip_text,
+    base::i18n::TextDirection text_direction_hint,
+    const gfx::Rect& bounds) {}
+
 void TestWebFrameWidgetHost::TextInputStateChanged(
     ui::mojom::blink::TextInputStatePtr state) {
   if (state->show_ime_if_needed)
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.h b/third_party/blink/renderer/core/frame/frame_test_helpers.h
index 94d0ba5..109342c 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.h
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.h
@@ -188,6 +188,9 @@
   void UpdateTooltipUnderCursor(
       const String& tooltip_text,
       base::i18n::TextDirection text_direction_hint) override;
+  void UpdateTooltipFromKeyboard(const String& tooltip_text,
+                                 base::i18n::TextDirection text_direction_hint,
+                                 const gfx::Rect& bounds) override;
   void TextInputStateChanged(
       ui::mojom::blink::TextInputStatePtr state) override;
   void SelectionBoundsChanged(const gfx::Rect& anchor_rect,
diff --git a/third_party/blink/renderer/core/frame/web_frame_test.cc b/third_party/blink/renderer/core/frame/web_frame_test.cc
index eb22710..67db15b 100644
--- a/third_party/blink/renderer/core/frame/web_frame_test.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_test.cc
@@ -6422,6 +6422,7 @@
                            {"composited_selection_bounds_basic.html"});
 }
 TEST_P(CompositedSelectionBoundsTest, Editable) {
+  web_view_helper_.GetWebView()->GetSettings()->SetDefaultFontSize(16);
   RunTest("composited_selection_bounds_editable.html");
 }
 TEST_P(CompositedSelectionBoundsTest, EditableDiv) {
@@ -6436,9 +6437,11 @@
 #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS)
 #if !defined(OS_ANDROID)
 TEST_P(CompositedSelectionBoundsTest, Input) {
+  web_view_helper_.GetWebView()->GetSettings()->SetDefaultFontSize(16);
   RunTest("composited_selection_bounds_input.html");
 }
 TEST_P(CompositedSelectionBoundsTest, InputScrolled) {
+  web_view_helper_.GetWebView()->GetSettings()->SetDefaultFontSize(16);
   RunTest("composited_selection_bounds_input_scrolled.html");
 }
 #endif
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
index 3dd4e255..fab478e9 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -3086,6 +3086,12 @@
   widget_base_->UpdateTooltipUnderCursor(tooltip_text, dir);
 }
 
+void WebFrameWidgetImpl::UpdateTooltipFromKeyboard(const String& tooltip_text,
+                                                   TextDirection dir,
+                                                   const gfx::Rect& bounds) {
+  widget_base_->UpdateTooltipFromKeyboard(tooltip_text, dir, bounds);
+}
+
 void WebFrameWidgetImpl::DidOverscroll(
     const gfx::Vector2dF& overscroll_delta,
     const gfx::Vector2dF& accumulated_overscroll,
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
index 3475cad..8062134 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
@@ -496,6 +496,9 @@
   void SetWindowRectSynchronouslyForTesting(const gfx::Rect& new_window_rect);
 
   void UpdateTooltipUnderCursor(const String& tooltip_text, TextDirection dir);
+  void UpdateTooltipFromKeyboard(const String& tooltip_text,
+                                 TextDirection dir,
+                                 const gfx::Rect& bounds);
 
   void ShowVirtualKeyboardOnElementFocus();
   void ProcessTouchAction(WebTouchAction touch_action);
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 6ccbeca2..51503e5 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -1084,6 +1084,14 @@
   return DOMWrapperWorld::World(script_context).GetWorldId();
 }
 
+v8::Local<v8::Context> WebLocalFrameImpl::GetScriptContextFromWorldId(
+    v8::Isolate* isolate,
+    int world_id) const {
+  scoped_refptr<DOMWrapperWorld> world =
+      DOMWrapperWorld::EnsureIsolatedWorld(isolate, world_id);
+  return ToScriptState(GetFrame(), *world)->GetContext();
+}
+
 v8::Local<v8::Object> WebLocalFrameImpl::GlobalProxy() const {
   return MainWorldScriptContext()->Global();
 }
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
index 07f6946..e762e86 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -170,6 +170,9 @@
   v8::Local<v8::Context> MainWorldScriptContext() const override;
   int32_t GetScriptContextWorldId(
       v8::Local<v8::Context> script_context) const override;
+  v8::Local<v8::Context> GetScriptContextFromWorldId(
+      v8::Isolate* isolate,
+      int world_id) const override;
   void RequestExecuteScriptAndReturnValue(const WebScriptSource&,
                                           bool user_gesture,
                                           WebScriptExecutionCallback*) override;
diff --git a/third_party/blink/renderer/core/html/forms/html_form_element.cc b/third_party/blink/renderer/core/html/forms/html_form_element.cc
index c185ec3c..747c4e7 100644
--- a/third_party/blink/renderer/core/html/forms/html_form_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_form_element.cc
@@ -73,26 +73,9 @@
 
 namespace blink {
 
-namespace {
-
-bool HasFormInBetween(const Node* root, const Node* descendant) {
-  DCHECK(descendant->IsDescendantOf(root));
-  DCHECK(!IsA<HTMLFormElement>(descendant));
-  for (ContainerNode* parent = descendant->parentNode(); parent != root;
-       parent = parent->parentNode()) {
-    if (DynamicTo<HTMLFormElement>(parent)) {
-      return true;
-    }
-  }
-  return false;
-}
-
-}  // namespace
-
 HTMLFormElement::HTMLFormElement(Document& document)
     : HTMLElement(html_names::kFormTag, document),
       listed_elements_are_dirty_(false),
-      listed_elements_including_shadow_trees_are_dirty_(false),
       image_elements_are_dirty_(false),
       has_elements_associated_by_parser_(false),
       has_elements_associated_by_form_attribute_(false),
@@ -110,7 +93,6 @@
   visitor->Trace(past_names_map_);
   visitor->Trace(radio_button_group_scope_);
   visitor->Trace(listed_elements_);
-  visitor->Trace(listed_elements_including_shadow_trees_);
   visitor->Trace(image_elements_);
   HTMLElement::Trace(visitor);
 }
@@ -654,8 +636,6 @@
 void HTMLFormElement::Associate(ListedElement& e) {
   listed_elements_are_dirty_ = true;
   listed_elements_.clear();
-  listed_elements_including_shadow_trees_are_dirty_ = true;
-  listed_elements_including_shadow_trees_.clear();
   if (e.ToHTMLElement().FastHasAttribute(html_names::kFormAttr))
     has_elements_associated_by_form_attribute_ = true;
 }
@@ -663,8 +643,6 @@
 void HTMLFormElement::Disassociate(ListedElement& e) {
   listed_elements_are_dirty_ = true;
   listed_elements_.clear();
-  listed_elements_including_shadow_trees_are_dirty_ = true;
-  listed_elements_including_shadow_trees_.clear();
   RemoveFromPastNamesMap(e.ToHTMLElement());
 }
 
@@ -701,66 +679,31 @@
 }
 
 void HTMLFormElement::CollectListedElements(
-    const Node& root,
-    ListedElement::List& elements,
-    ListedElement::List* elements_including_shadow_trees,
-    bool in_shadow_tree) const {
-  DCHECK(!in_shadow_tree || elements_including_shadow_trees);
+    Node& root,
+    ListedElement::List& elements) const {
   elements.clear();
   for (HTMLElement& element : Traversal<HTMLElement>::StartsAfter(root)) {
-    if (ListedElement* listed_element = ListedElement::From(element)) {
-      // If there is a <form> in between |root| and |listed_element|, then we
-      // shouldn't include it in |elements_including_shadow_trees| in order to
-      // prevent multiple forms from "owning" the same |listed_element| as shown
-      // by their |elements_including_shadow_trees|. |elements| doesn't have
-      // this problem because it can check |listed_element->Form()|.
-      if (in_shadow_tree && !HasFormInBetween(&root, &element)) {
-        elements_including_shadow_trees->push_back(listed_element);
-      } else if (listed_element->Form() == this) {
-        elements.push_back(listed_element);
-        if (elements_including_shadow_trees)
-          elements_including_shadow_trees->push_back(listed_element);
-      }
-    }
-    if (elements_including_shadow_trees && element.AuthorShadowRoot() &&
-        !HasFormInBetween(&root, &element)) {
-      const Node& shadow = *element.AuthorShadowRoot();
-      CollectListedElements(shadow, elements, elements_including_shadow_trees,
-                            /*in_shadow_tree=*/true);
-    }
+    ListedElement* listed_element = ListedElement::From(element);
+    if (listed_element && listed_element->Form() == this)
+      elements.push_back(listed_element);
   }
 }
 
 // This function should be const conceptually. However we update some fields
 // because of lazy evaluation.
-const ListedElement::List& HTMLFormElement::ListedElements(
-    bool include_shadow_trees) const {
-  if (!RuntimeEnabledFeatures::AutofillShadowDOMEnabled())
-    include_shadow_trees = false;
-  bool collect_shadow_inputs =
-      include_shadow_trees && listed_elements_including_shadow_trees_are_dirty_;
-
-  if (listed_elements_are_dirty_ || collect_shadow_inputs) {
-    HTMLFormElement* mutable_this = const_cast<HTMLFormElement*>(this);
-    Node* scope = mutable_this;
-    if (has_elements_associated_by_parser_)
-      scope = &NodeTraversal::HighestAncestorOrSelf(*mutable_this);
-    if (isConnected() && has_elements_associated_by_form_attribute_)
-      scope = &GetTreeScope().RootNode();
-    DCHECK(scope);
-    mutable_this->listed_elements_.clear();
-    mutable_this->listed_elements_including_shadow_trees_.clear();
-    CollectListedElements(
-        *scope, mutable_this->listed_elements_,
-        collect_shadow_inputs
-            ? &mutable_this->listed_elements_including_shadow_trees_
-            : nullptr);
-    mutable_this->listed_elements_are_dirty_ = false;
-    mutable_this->listed_elements_including_shadow_trees_are_dirty_ =
-        !collect_shadow_inputs;
-  }
-  return include_shadow_trees ? listed_elements_including_shadow_trees_
-                              : listed_elements_;
+const ListedElement::List& HTMLFormElement::ListedElements() const {
+  if (!listed_elements_are_dirty_)
+    return listed_elements_;
+  HTMLFormElement* mutable_this = const_cast<HTMLFormElement*>(this);
+  Node* scope = mutable_this;
+  if (has_elements_associated_by_parser_)
+    scope = &NodeTraversal::HighestAncestorOrSelf(*mutable_this);
+  if (isConnected() && has_elements_associated_by_form_attribute_)
+    scope = &GetTreeScope().RootNode();
+  DCHECK(scope);
+  CollectListedElements(*scope, mutable_this->listed_elements_);
+  mutable_this->listed_elements_are_dirty_ = false;
+  return listed_elements_;
 }
 
 void HTMLFormElement::CollectImageElements(
@@ -986,8 +929,4 @@
   }
 }
 
-void HTMLFormElement::InvalidateListedElementsIncludingShadowTrees() {
-  listed_elements_including_shadow_trees_are_dirty_ = true;
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/forms/html_form_element.h b/third_party/blink/renderer/core/html/forms/html_form_element.h
index c2b4298b..e68a299 100644
--- a/third_party/blink/renderer/core/html/forms/html_form_element.h
+++ b/third_party/blink/renderer/core/html/forms/html_form_element.h
@@ -102,8 +102,7 @@
     return radio_button_group_scope_;
   }
 
-  const ListedElement::List& ListedElements(
-      bool include_shadow_trees = false) const;
+  const ListedElement::List& ListedElements() const;
   const HeapVector<Member<HTMLImageElement>>& ImageElements();
 
   V8UnionElementOrRadioNodeList* AnonymousNamedGetter(const AtomicString& name);
@@ -117,8 +116,6 @@
 
   unsigned UniqueRendererFormId() const { return unique_renderer_form_id_; }
 
-  void InvalidateListedElementsIncludingShadowTrees();
-
  private:
   InsertionNotificationRequest InsertedInto(ContainerNode&) override;
   void RemovedFrom(ContainerNode&) override;
@@ -138,11 +135,7 @@
   void ScheduleFormSubmission(const Event*,
                               HTMLFormControlElement* submit_button);
 
-  void CollectListedElements(
-      const Node& root,
-      ListedElement::List& elements,
-      ListedElement::List* elements_including_shadow_trees = nullptr,
-      bool in_shadow_tree = false) const;
+  void CollectListedElements(Node& root, ListedElement::List&) const;
   void CollectImageElements(Node& root, HeapVector<Member<HTMLImageElement>>&);
 
   // Returns true if the submission should proceed.
@@ -166,9 +159,6 @@
 
   // Do not access listed_elements_ directly. Use ListedElements() instead.
   ListedElement::List listed_elements_;
-  // Do not access listed_elements_including_shadow_trees_ directly. Use
-  // ListedElements(true) instead.
-  ListedElement::List listed_elements_including_shadow_trees_;
   // Do not access image_elements_ directly. Use ImageElements() instead.
   HeapVector<Member<HTMLImageElement>> image_elements_;
 
@@ -179,7 +169,6 @@
   bool is_constructing_entry_list_ = false;
 
   bool listed_elements_are_dirty_ : 1;
-  bool listed_elements_including_shadow_trees_are_dirty_ : 1;
   bool image_elements_are_dirty_ : 1;
   bool has_elements_associated_by_parser_ : 1;
   bool has_elements_associated_by_form_attribute_ : 1;
diff --git a/third_party/blink/renderer/core/html/forms/html_form_element_test.cc b/third_party/blink/renderer/core/html/forms/html_form_element_test.cc
index e9863afd6..1f79394e 100644
--- a/third_party/blink/renderer/core/html/forms/html_form_element_test.cc
+++ b/third_party/blink/renderer/core/html/forms/html_form_element_test.cc
@@ -5,9 +5,6 @@
 #include "third_party/blink/renderer/core/html/forms/html_form_element.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/core/dom/shadow_root.h"
-#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
-#include "third_party/blink/renderer/core/html/html_body_element.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 
 namespace blink {
@@ -34,224 +31,4 @@
   EXPECT_EQ(first_id + 2, form3->UniqueRendererFormId());
 }
 
-// This tree is created manually because the HTML parser removes nested forms.
-// The created tree looks like this:
-// <body>
-//   <form id=form1>
-//     <form id=form2>
-//       <input>
-TEST_F(HTMLFormElementTest, ListedElementsNestedForms) {
-  HTMLBodyElement* body = GetDocument().FirstBodyElement();
-
-  HTMLFormElement* form1 = MakeGarbageCollected<HTMLFormElement>(GetDocument());
-  body->AppendChild(form1);
-
-  HTMLFormElement* form2 = MakeGarbageCollected<HTMLFormElement>(GetDocument());
-  form1->AppendChild(form2);
-
-  HTMLInputElement* input = MakeGarbageCollected<HTMLInputElement>(
-      GetDocument(), CreateElementFlags::ByCreateElement());
-  form2->AppendChild(input);
-
-  ListedElement::List form1elements = form1->ListedElements();
-  ListedElement::List form2elements = form2->ListedElements();
-  EXPECT_EQ(form1elements.size(), 0u);
-  ASSERT_EQ(form2elements.size(), 1u);
-  EXPECT_EQ(form2elements.at(0)->ToHTMLElement(), input);
-}
-
-TEST_F(HTMLFormElementTest, ListedElementsDetachedForm) {
-  HTMLBodyElement* body = GetDocument().FirstBodyElement();
-
-  HTMLFormElement* form = MakeGarbageCollected<HTMLFormElement>(GetDocument());
-  body->AppendChild(form);
-
-  HTMLInputElement* input = MakeGarbageCollected<HTMLInputElement>(
-      GetDocument(), CreateElementFlags::ByCreateElement());
-  form->AppendChild(input);
-
-  ListedElement::List listed_elements = form->ListedElements();
-  ASSERT_EQ(listed_elements.size(), 1u);
-  EXPECT_EQ(listed_elements.at(0)->ToHTMLElement(), input);
-
-  form->remove();
-  listed_elements = form->ListedElements();
-  ASSERT_EQ(listed_elements.size(), 1u);
-  EXPECT_EQ(listed_elements.at(0)->ToHTMLElement(), input);
-}
-
-// This tree is created manually because the HTML parser removes nested forms.
-// The created tree looks like this:
-// <body>
-//   <form id=form1>
-//     <div id=form1div>
-//       <template shadowroot=open>
-//         <form id=form2>
-//           <form id=form3>
-//             <div id=form3div>
-//               <template shadowroot=open>
-//
-// An <input> element is appended at the bottom and moved up one node at a time
-// in this tree, and each step of the way, ListedElements is checked on all
-// forms.
-TEST_F(HTMLFormElementTest, ListedElementsIncludeShadowTrees) {
-  HTMLBodyElement* body = GetDocument().FirstBodyElement();
-
-  HTMLFormElement* form1 = MakeGarbageCollected<HTMLFormElement>(GetDocument());
-  body->AppendChild(form1);
-
-  HTMLDivElement* form1div =
-      MakeGarbageCollected<HTMLDivElement>(GetDocument());
-  form1->AppendChild(form1div);
-  ShadowRoot& form1root =
-      form1div->AttachShadowRootInternal(ShadowRootType::kOpen);
-
-  HTMLFormElement* form2 = MakeGarbageCollected<HTMLFormElement>(GetDocument());
-  form1root.AppendChild(form2);
-
-  HTMLFormElement* form3 = MakeGarbageCollected<HTMLFormElement>(GetDocument());
-  form2->AppendChild(form3);
-
-  HTMLDivElement* form3div =
-      MakeGarbageCollected<HTMLDivElement>(GetDocument());
-  form3->AppendChild(form3div);
-  ShadowRoot& form3root =
-      form3div->AttachShadowRootInternal(ShadowRootType::kOpen);
-
-  HTMLInputElement* input = MakeGarbageCollected<HTMLInputElement>(
-      GetDocument(), CreateElementFlags::ByCreateElement());
-
-  form3root.AppendChild(input);
-  EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{input});
-
-  input->remove();
-  EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-
-  form3div->AppendChild(input);
-  EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(), ListedElement::List{input});
-  EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{input});
-
-  form3->AppendChild(input);
-  EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(), ListedElement::List{input});
-  EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{input});
-
-  input->remove();
-  EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-
-  form2->AppendChild(input);
-  EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(), ListedElement::List{input});
-  EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{input});
-  EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-
-  input->remove();
-  EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-
-  form1root.AppendChild(input);
-  EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{input});
-  EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-
-  input->remove();
-  EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-
-  form1div->AppendChild(input);
-  EXPECT_EQ(form1->ListedElements(), ListedElement::List{input});
-  EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{input});
-  EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-
-  form1->AppendChild(input);
-  EXPECT_EQ(form1->ListedElements(), ListedElement::List{input});
-  EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{input});
-  EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-
-  input->remove();
-  EXPECT_EQ(form1->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form1->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form2->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(), ListedElement::List{});
-  EXPECT_EQ(form3->ListedElements(/*include_shadow_trees=*/true),
-            ListedElement::List{});
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/forms/listed_element.cc b/third_party/blink/renderer/core/html/forms/listed_element.cc
index f416080..a55a83f6 100644
--- a/third_party/blink/renderer/core/html/forms/listed_element.cc
+++ b/third_party/blink/renderer/core/html/forms/listed_element.cc
@@ -51,27 +51,6 @@
 
 namespace blink {
 
-namespace {
-
-void InvalidateShadowIncludingAncestorForms(ContainerNode& insertion_point) {
-  if (!RuntimeEnabledFeatures::AutofillShadowDOMEnabled())
-    return;
-
-  // Let any forms in the shadow including ancestors know that this
-  // ListedElement has changed. Don't include any forms inside the same
-  // TreeScope know because that relationship isn't tracked by listed elements
-  // including shadow trees.
-  for (ContainerNode* parent = insertion_point.OwnerShadowHost(); parent;
-       parent = parent->ParentOrShadowHostNode()) {
-    if (HTMLFormElement* form = DynamicTo<HTMLFormElement>(parent)) {
-      form->InvalidateListedElementsIncludingShadowTrees();
-      return;
-    }
-  }
-}
-
-}  // namespace
-
 class FormAttributeTargetObserver : public IdTargetObserver {
  public:
   FormAttributeTargetObserver(const AtomicString& id, ListedElement*);
@@ -144,8 +123,6 @@
   // Trigger for elements outside of forms.
   if (!form_ && insertion_point.isConnected())
     element.GetDocument().DidAssociateFormControl(&element);
-
-  InvalidateShadowIncludingAncestorForms(insertion_point);
 }
 
 void ListedElement::RemovedFrom(ContainerNode& insertion_point) {
@@ -179,8 +156,6 @@
         .GetFormController()
         .InvalidateStatefulFormControlList();
   }
-
-  InvalidateShadowIncludingAncestorForms(insertion_point);
 }
 
 HTMLFormElement* ListedElement::FindAssociatedForm(
diff --git a/third_party/blink/renderer/core/input/gesture_manager.cc b/third_party/blink/renderer/core/input/gesture_manager.cc
index 672e08d..62856d58 100644
--- a/third_party/blink/renderer/core/input/gesture_manager.cc
+++ b/third_party/blink/renderer/core/input/gesture_manager.cc
@@ -326,6 +326,15 @@
       event_handling_util::MergeEventResult(mouse_down_event_result,
                                             mouse_up_event_result),
       click_event_result);
+
+  if (RuntimeEnabledFeatures::TextFragmentTapOpensContextMenuEnabled() &&
+      TextFragmentHandler::IsOverTextFragment(current_hit_test)) {
+    if (event_result == WebInputEventResult::kNotHandled) {
+      return SendContextMenuEventForGesture(targeted_event);
+    }
+  }
+
+  // Default case when tap that is not handled.
   if (event_result == WebInputEventResult::kNotHandled && tapped_node &&
       frame_->GetPage()) {
     bool dom_tree_changed = pre_dispatch_dom_tree_version !=
@@ -339,12 +348,6 @@
     ShowUnhandledTapUIIfNeeded(dom_tree_changed, style_changed, tapped_node,
                                tapped_element, tapped_position_in_viewport);
   }
-  if (RuntimeEnabledFeatures::TextFragmentTapOpensContextMenuEnabled() &&
-      TextFragmentHandler::IsOverTextFragment(current_hit_test)) {
-    if (event_result == WebInputEventResult::kNotHandled) {
-      return SendContextMenuEventForGesture(targeted_event);
-    }
-  }
 
   return event_result;
 }
diff --git a/third_party/blink/renderer/core/layout/layout_shift_tracker.cc b/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
index db4ebbd..1a03337 100644
--- a/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
+++ b/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
@@ -646,6 +646,17 @@
       type == WebInputEvent::Type::kPointerDown &&
       static_cast<const WebPointerEvent&>(event).hovering;
 
+  const bool mousemove_with_button_down =
+      type == WebInputEvent::Type::kMouseMove &&
+      (event.GetModifiers() & WebInputEvent::kLeftButtonDown ||
+       event.GetModifiers() & WebInputEvent::kMiddleButtonDown ||
+       event.GetModifiers() & WebInputEvent::kRightButtonDown ||
+       event.GetModifiers() & WebInputEvent::kBackButtonDown ||
+       event.GetModifiers() & WebInputEvent::kForwardButtonDown);
+
+  const bool mouseup_after_dragging =
+      type == WebInputEvent::Type::kMouseUp && saw_dragged_mousemove_;
+
   const bool should_trigger_shift_exclusion =
       type == WebInputEvent::Type::kMouseDown ||
       type == WebInputEvent::Type::kKeyDown ||
@@ -653,7 +664,8 @@
       // We need to explicitly include tap, as if there are no listeners, we
       // won't receive the pointer events.
       type == WebInputEvent::Type::kGestureTap || is_hovering_pointerdown ||
-      pointerdown_became_tap;
+      pointerdown_became_tap || mousemove_with_button_down ||
+      mouseup_after_dragging;
 
   if (should_trigger_shift_exclusion) {
     observed_input_or_scroll_ = true;
@@ -671,6 +683,13 @@
   }
   if (type == WebInputEvent::Type::kPointerDown && !is_hovering_pointerdown)
     pointerdown_pending_data_.saw_pointerdown = true;
+
+  if (mousemove_with_button_down)
+    saw_dragged_mousemove_ = mousemove_with_button_down;
+  if (type == WebInputEvent::Type::kMouseUp ||
+      type == WebInputEvent::Type::kMouseDown) {
+    saw_dragged_mousemove_ = false;
+  }
 }
 
 void LayoutShiftTracker::UpdateInputTimestamp(base::TimeTicks timestamp) {
@@ -795,6 +814,10 @@
   }
 }
 
+void LayoutShiftTracker::ResetTimerForTesting() {
+  timer_.Stop();
+}
+
 void LayoutShiftTracker::Trace(Visitor* visitor) const {
   visitor->Trace(frame_view_);
   visitor->Trace(timer_);
diff --git a/third_party/blink/renderer/core/layout/layout_shift_tracker.h b/third_party/blink/renderer/core/layout/layout_shift_tracker.h
index 8a7d2be..245fe9a 100644
--- a/third_party/blink/renderer/core/layout/layout_shift_tracker.h
+++ b/third_party/blink/renderer/core/layout/layout_shift_tracker.h
@@ -87,6 +87,7 @@
   base::TimeTicks MostRecentInputTimestamp() {
     return most_recent_input_timestamp_;
   }
+  void ResetTimerForTesting();
   void Trace(Visitor* visitor) const;
 
   // Saves and restores geometry on layout boxes when a layout tree is rebuilt
@@ -263,6 +264,11 @@
 
   // Nodes that have contributed to the impact region for the current frame.
   std::array<Attribution, LayoutShift::kMaxAttributions> attributions_;
+
+  // Set to true when we see MouseMove events with any button pressed, and
+  // reset to false when we see a MouseUp or MouseDown event. This helps to set
+  // the MouseUp event after mouse dragging to be hasRecentInput.
+  bool saw_dragged_mousemove_ = false;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc b/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc
index 7c7ac49..d062cf71 100644
--- a/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc
@@ -333,6 +333,75 @@
           false /* expect_exclusion */);
 }
 
+TEST_F(LayoutShiftTrackerSimTest, MouseMoveDraggingAction) {
+  SimRequest main_resource("https://example.com/", "text/html");
+  LoadURL("https://example.com/");
+  main_resource.Complete(R"HTML(
+    <style>
+      body { margin: 0; height: 1500px; }
+      #box {
+        left: 0px;
+        top: 0px;
+        width: 400px;
+        height: 600px;
+        background: yellow;
+        position: absolute;
+      }
+    </style>
+    <div id="box"></div>
+    <script>
+      box.addEventListener("mousemove", (e) => {
+        box.style.top = "100px";
+        e.preventDefault();
+      });
+    </script>
+  )HTML");
+
+  Compositor().BeginFrame();
+  test::RunPendingTasks();
+
+  WebMouseEvent event1(WebInputEvent::Type::kMouseDown, gfx::PointF(),
+                       gfx::PointF(), WebPointerProperties::Button::kLeft, 0,
+                       WebInputEvent::Modifiers::kLeftButtonDown,
+                       base::TimeTicks::Now());
+  WebMouseEvent event2(WebInputEvent::Type::kMouseMove, gfx::PointF(),
+                       gfx::PointF(), WebPointerProperties::Button::kLeft, 1,
+                       WebInputEvent::Modifiers::kLeftButtonDown,
+                       base::TimeTicks::Now());
+
+  // Coordinates inside #box.
+  event1.SetPositionInWidget(50, 150);
+  event2.SetPositionInWidget(50, 160);
+
+  WebView().MainFrameWidget()->HandleInputEvent(
+      WebCoalescedInputEvent(event1, ui::LatencyInfo()));
+
+  WindowPerformance& perf = *DOMWindowPerformance::performance(Window());
+  auto& tracker = MainFrame().GetFrameView()->GetLayoutShiftTracker();
+  Compositor().BeginFrame();
+  test::RunPendingTasks();
+
+  EXPECT_EQ(0u, perf.getBufferedEntriesByType("layout-shift").size());
+  EXPECT_FLOAT_EQ(0.0, tracker.Score());
+
+  tracker.ResetTimerForTesting();
+  WebView().MainFrameWidget()->HandleInputEvent(
+      WebCoalescedInputEvent(event2, ui::LatencyInfo()));
+
+  Compositor().BeginFrame();
+  test::RunPendingTasks();
+
+  auto entries = perf.getBufferedEntriesByType("layout-shift");
+  EXPECT_EQ(1u, entries.size());
+  LayoutShift* shift = static_cast<LayoutShift*>(entries.front().Get());
+
+  // region fraction 50%, distance fraction 1/8
+  const double expected_shift = 0.5 * 0.125;
+  EXPECT_TRUE(shift->hadRecentInput());
+  EXPECT_FLOAT_EQ(expected_shift, shift->value());
+  EXPECT_FLOAT_EQ(0, tracker.Score());
+}
+
 TEST_F(LayoutShiftTrackerTest, StableCompositingChanges) {
   SetBodyInnerHTML(R"HTML(
     <style>
diff --git a/third_party/blink/renderer/core/layout/layout_theme.cc b/third_party/blink/renderer/core/layout/layout_theme.cc
index 5a64291..ceaae9b 100644
--- a/third_party/blink/renderer/core/layout/layout_theme.cc
+++ b/third_party/blink/renderer/core/layout/layout_theme.cc
@@ -572,22 +572,21 @@
 }
 
 void LayoutTheme::SystemFont(CSSValueID system_font_id,
-                             FontDescription& font_description) {
+                             FontDescription& font_description,
+                             const Document* document) {
   font_description = GetCachedFontDescription(system_font_id);
   if (font_description.IsAbsoluteSize())
     return;
 
-  FontSelectionValue font_slope = NormalSlopeValue();
-  FontSelectionValue font_weight = NormalWeightValue();
-  float font_size = 0;
-  AtomicString font_family;
-  LayoutThemeFontProvider::SystemFont(system_font_id, font_slope, font_weight,
-                                      font_size, font_family);
-  font_description.SetStyle(font_slope);
-  font_description.SetWeight(font_weight);
-  font_description.SetSpecifiedSize(font_size);
+  font_description.SetStyle(
+      LayoutThemeFontProvider::SystemFontStyle(system_font_id));
+  font_description.SetWeight(
+      LayoutThemeFontProvider::SystemFontWeight(system_font_id));
+  font_description.SetSpecifiedSize(
+      LayoutThemeFontProvider::SystemFontSize(system_font_id, document));
   font_description.SetIsAbsoluteSize(true);
-  font_description.FirstFamily().SetFamily(font_family);
+  font_description.FirstFamily().SetFamily(
+      LayoutThemeFontProvider::SystemFontFamily(system_font_id));
   font_description.SetGenericFamily(FontDescription::kNoFamily);
 }
 
diff --git a/third_party/blink/renderer/core/layout/layout_theme.h b/third_party/blink/renderer/core/layout/layout_theme.h
index 0185d72..44fa68ea 100644
--- a/third_party/blink/renderer/core/layout/layout_theme.h
+++ b/third_party/blink/renderer/core/layout/layout_theme.h
@@ -42,6 +42,7 @@
 namespace blink {
 
 class ComputedStyle;
+class Document;
 class Element;
 class File;
 class FontDescription;
@@ -146,7 +147,7 @@
   virtual base::TimeDelta CaretBlinkInterval() const;
 
   // System fonts and colors for CSS.
-  void SystemFont(CSSValueID system_font_id, FontDescription&);
+  void SystemFont(CSSValueID system_font_id, FontDescription&, const Document*);
   virtual Color SystemColor(CSSValueID,
                             mojom::blink::ColorScheme color_scheme) const;
 
diff --git a/third_party/blink/renderer/core/layout/layout_theme_font_provider.cc b/third_party/blink/renderer/core/layout/layout_theme_font_provider.cc
index fe3c34e..87ececf8 100644
--- a/third_party/blink/renderer/core/layout/layout_theme_font_provider.cc
+++ b/third_party/blink/renderer/core/layout/layout_theme_font_provider.cc
@@ -25,11 +25,16 @@
 
 #include "third_party/blink/renderer/core/layout/layout_theme_font_provider.h"
 
+#include "third_party/blink/renderer/core/css/font_size_functions.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
 namespace blink {
 
+constexpr float kDefaultFontSizeFallback = 16.0;
+
 // We aim to match IE here.
 // -IE uses a font based on the encoding as the default font for form controls.
 // -Gecko uses MS Shell Dlg (actually calls GetStockObject(DEFAULT_GUI_FONT),
@@ -44,4 +49,17 @@
   return font_face;
 }
 
+float LayoutThemeFontProvider::DefaultFontSize(const Document* document) {
+  const Settings* settings = document ? document->GetSettings() : nullptr;
+
+  // The default font size setting may be uninitialized in some cases, like
+  // in the calendar picker of an <input type=date> widget.
+  if (!settings || !settings->GetDefaultFontSize())
+    return kDefaultFontSizeFallback;
+
+  static const unsigned keyword = FontSizeFunctions::InitialKeywordSize();
+  static const bool is_monospace = false;
+  return FontSizeFunctions::FontSizeForKeyword(document, keyword, is_monospace);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_theme_font_provider.h b/third_party/blink/renderer/core/layout/layout_theme_font_provider.h
index d76f890..32e472a 100644
--- a/third_party/blink/renderer/core/layout/layout_theme_font_provider.h
+++ b/third_party/blink/renderer/core/layout/layout_theme_font_provider.h
@@ -34,18 +34,21 @@
 
 namespace blink {
 
+class Document;
+
 class CORE_EXPORT LayoutThemeFontProvider {
   STATIC_ONLY(LayoutThemeFontProvider);
 
  public:
-  static void SystemFont(CSSValueID system_font_id,
-                         FontSelectionValue& slope,
-                         FontSelectionValue& weight,
-                         float& font_size,
-                         AtomicString& font_family);
+  static const FontSelectionValue& SystemFontStyle(CSSValueID system_font_id);
+  static const FontSelectionValue& SystemFontWeight(CSSValueID system_font_id);
+  static const AtomicString& SystemFontFamily(CSSValueID system_font_id);
+  static float SystemFontSize(CSSValueID system_font_id,
+                              const Document* document);
 
  protected:
   static const WTF::AtomicString& DefaultGUIFont();
+  static float DefaultFontSize(const Document*);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_theme_font_provider_default.cc b/third_party/blink/renderer/core/layout/layout_theme_font_provider_default.cc
index 744790a..2ec46b7 100644
--- a/third_party/blink/renderer/core/layout/layout_theme_font_provider_default.cc
+++ b/third_party/blink/renderer/core/layout/layout_theme_font_provider_default.cc
@@ -33,19 +33,27 @@
 
 namespace blink {
 
-constexpr float kDefaultFontSize = 16.0;
+// static
+const FontSelectionValue& LayoutThemeFontProvider::SystemFontStyle(
+    CSSValueID system_font_id) {
+  return NormalSlopeValue();
+}
 
 // static
-void LayoutThemeFontProvider::SystemFont(CSSValueID system_font_id,
-                                         FontSelectionValue& font_slope,
-                                         FontSelectionValue& font_weight,
-                                         float& font_size,
-                                         AtomicString& font_family) {
-  font_weight = NormalWeightValue();
-  font_slope = NormalSlopeValue();
-  font_size = kDefaultFontSize;
-  font_family = DefaultGUIFont();
+const FontSelectionValue& LayoutThemeFontProvider::SystemFontWeight(
+    CSSValueID system_font_id) {
+  return NormalWeightValue();
+}
 
+// static
+const AtomicString& LayoutThemeFontProvider::SystemFontFamily(
+    CSSValueID system_font_id) {
+  return DefaultGUIFont();
+}
+
+// static
+float LayoutThemeFontProvider::SystemFontSize(CSSValueID system_font_id,
+                                              const Document* document) {
   switch (system_font_id) {
     case CSSValueID::kWebkitMiniControl:
     case CSSValueID::kWebkitSmallControl:
@@ -55,10 +63,11 @@
       // Windows.
       static const float kPointsPerInch = 72.0f;
       static const float kPixelsPerInch = 96.0f;
-      font_size -= (2.0f / kPointsPerInch) * kPixelsPerInch;
+      return DefaultFontSize(document) -
+             (2.0f / kPointsPerInch) * kPixelsPerInch;
       break;
     default:
-      break;
+      return DefaultFontSize(document);
   }
 }
 
diff --git a/third_party/blink/renderer/core/layout/layout_theme_font_provider_win.cc b/third_party/blink/renderer/core/layout/layout_theme_font_provider_win.cc
index 0d690783e..b806f1a 100644
--- a/third_party/blink/renderer/core/layout/layout_theme_font_provider_win.cc
+++ b/third_party/blink/renderer/core/layout/layout_theme_font_provider_win.cc
@@ -32,8 +32,6 @@
 
 namespace blink {
 
-constexpr float kDefaultFontSize = 16.0;
-
 // Converts |points| to pixels. One point is 1/72 of an inch.
 static float PointsToPixels(float points) {
   const float kPixelsPerInch = 96.0f;
@@ -42,38 +40,49 @@
 }
 
 // static
-void LayoutThemeFontProvider::SystemFont(CSSValueID system_font_id,
-                                         FontSelectionValue& font_style,
-                                         FontSelectionValue& font_weight,
-                                         float& font_size,
-                                         AtomicString& font_family) {
-  font_style = NormalSlopeValue();
-  font_weight = NormalWeightValue();
+const FontSelectionValue& LayoutThemeFontProvider::SystemFontStyle(
+    CSSValueID system_font_id) {
+  return NormalSlopeValue();
+}
 
+// static
+const FontSelectionValue& LayoutThemeFontProvider::SystemFontWeight(
+    CSSValueID system_font_id) {
+  return NormalWeightValue();
+}
+
+// static
+const AtomicString& LayoutThemeFontProvider::SystemFontFamily(
+    CSSValueID system_font_id) {
   switch (system_font_id) {
     case CSSValueID::kSmallCaption:
-      font_size = FontCache::SmallCaptionFontHeight();
-      font_family = FontCache::SmallCaptionFontFamily();
-      break;
+      return FontCache::SmallCaptionFontFamily();
     case CSSValueID::kMenu:
-      font_size = FontCache::MenuFontHeight();
-      font_family = FontCache::MenuFontFamily();
-      break;
+      return FontCache::MenuFontFamily();
     case CSSValueID::kStatusBar:
-      font_size = FontCache::StatusFontHeight();
-      font_family = FontCache::StatusFontFamily();
-      break;
+      return FontCache::StatusFontFamily();
+    default:
+      return DefaultGUIFont();
+  }
+}
+
+// static
+float LayoutThemeFontProvider::SystemFontSize(CSSValueID system_font_id,
+                                              const Document* document) {
+  switch (system_font_id) {
+    case CSSValueID::kSmallCaption:
+      return FontCache::SmallCaptionFontHeight();
+    case CSSValueID::kMenu:
+      return FontCache::MenuFontHeight();
+    case CSSValueID::kStatusBar:
+      return FontCache::StatusFontHeight();
     case CSSValueID::kWebkitMiniControl:
     case CSSValueID::kWebkitSmallControl:
     case CSSValueID::kWebkitControl:
       // Why 2 points smaller? Because that's what Gecko does.
-      font_size = kDefaultFontSize - PointsToPixels(2);
-      font_family = DefaultGUIFont();
-      break;
+      return DefaultFontSize(document) - PointsToPixels(2);
     default:
-      font_size = kDefaultFontSize;
-      font_family = DefaultGUIFont();
-      break;
+      return DefaultFontSize(document);
   }
 }
 
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.cc b/third_party/blink/renderer/core/page/chrome_client_impl.cc
index 69a5ddb..716d5e9 100644
--- a/third_party/blink/renderer/core/page/chrome_client_impl.cc
+++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -567,7 +567,9 @@
   if (!RuntimeEnabledFeatures::KeyboardAccessibleTooltipEnabled())
     return;
 
-  // TODO(bebeaudr): Add WidgetHost function and call it here.
+  WebLocalFrameImpl::FromFrame(frame)
+      ->LocalRootFrameWidget()
+      ->UpdateTooltipFromKeyboard(tooltip_text, dir, bounds);
 }
 
 void ChromeClientImpl::DispatchViewportPropertiesDidChange(
diff --git a/third_party/blink/renderer/core/page/drag_controller.cc b/third_party/blink/renderer/core/page/drag_controller.cc
index 2ca9637..5630339 100644
--- a/third_party/blink/renderer/core/page/drag_controller.cc
+++ b/third_party/blink/renderer/core/page/drag_controller.cc
@@ -1118,10 +1118,11 @@
 
 static std::unique_ptr<DragImage> DragImageForLink(const KURL& link_url,
                                                    const String& link_text,
-                                                   float device_scale_factor) {
+                                                   float device_scale_factor,
+                                                   const Document* document) {
   FontDescription font_description;
-  LayoutTheme::GetTheme().SystemFont(blink::CSSValueID::kNone,
-                                     font_description);
+  LayoutTheme::GetTheme().SystemFont(blink::CSSValueID::kNone, font_description,
+                                     document);
   return DragImage::Create(link_url, link_text, font_description,
                            device_scale_factor);
 }
@@ -1282,8 +1283,9 @@
       DCHECK(src->GetPage());
       float screen_device_scale_factor =
           src->GetChromeClient().GetScreenInfo(*src).device_scale_factor;
-      drag_image = DragImageForLink(link_url, hit_test_result.TextContent(),
-                                    screen_device_scale_factor);
+      drag_image =
+          DragImageForLink(link_url, hit_test_result.TextContent(),
+                           screen_device_scale_factor, src->GetDocument());
       drag_location = DragLocationForLink(drag_image.get(), mouse_dragged_point,
                                           screen_device_scale_factor,
                                           src->GetPage()->PageScaleFactor());
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_test.cc b/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_test.cc
index 5a264e43b..c859095 100644
--- a/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_test.cc
@@ -9,6 +9,8 @@
 #include "third_party/blink/public/common/input/web_menu_source_type.h"
 #include "third_party/blink/public/mojom/scroll/scroll_enums.mojom-blink.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/public_buildflags.h"
+#include "third_party/blink/renderer/bindings/core/v8/string_or_array_buffer_or_array_buffer_view.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_font_face_descriptors.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_mouse_event_init.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_string.h"
@@ -29,6 +31,7 @@
 #include "third_party/blink/renderer/core/input/event_handler.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/loader/document_loader.h"
+#include "third_party/blink/renderer/core/loader/empty_clients.h"
 #include "third_party/blink/renderer/core/page/context_menu_controller.h"
 #include "third_party/blink/renderer/core/page/scrolling/fragment_anchor.h"
 #include "third_party/blink/renderer/core/page/scrolling/text_fragment_finder.h"
@@ -38,6 +41,11 @@
 #include "third_party/blink/renderer/core/testing/sim/sim_test.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 
+#if BUILDFLAG(ENABLE_UNHANDLED_TAP)
+#include "third_party/blink/public/mojom/unhandled_tap_notifier/unhandled_tap_notifier.mojom-blink.h"
+#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
+#endif  // BUILDFLAG(ENABLE_UNHANDLED_TAP)
+
 namespace blink {
 
 namespace {
@@ -2512,6 +2520,104 @@
                    .ContextMenuNodeForFrame(GetDocument().GetFrame()));
 }
 
+#if BUILDFLAG(ENABLE_UNHANDLED_TAP)
+// Mock implementation of the UnhandledTapNotifier Mojo receiver, for testing
+// the ShowUnhandledTapUIIfNeeded notification.
+class MockUnhandledTapNotifierImpl : public mojom::blink::UnhandledTapNotifier {
+ public:
+  MockUnhandledTapNotifierImpl() = default;
+
+  void Bind(mojo::ScopedMessagePipeHandle handle) {
+    receiver_.Bind(mojo::PendingReceiver<mojom::blink::UnhandledTapNotifier>(
+        std::move(handle)));
+  }
+
+  void ShowUnhandledTapUIIfNeeded(
+      mojom::blink::UnhandledTapInfoPtr unhandled_tap_info) override {
+    was_unhandled_tap_ = true;
+  }
+  bool WasUnhandledTap() const { return was_unhandled_tap_; }
+  bool ReceiverIsBound() const { return receiver_.is_bound(); }
+  void Reset() {
+    was_unhandled_tap_ = false;
+    receiver_.reset();
+  }
+
+ private:
+  bool was_unhandled_tap_ = false;
+
+  mojo::Receiver<mojom::blink::UnhandledTapNotifier> receiver_{this};
+};
+#endif  // BUILDFLAG(ENABLE_UNHANDLED_TAP)
+
+#if BUILDFLAG(ENABLE_UNHANDLED_TAP)
+// Test that on Android, when a user taps on a text, ShouldNotRequestUnhandled
+// does not get triggered. When a user taps on a highlight, no text should be
+// selected. RuntimeEnabledFeature is enabled.
+TEST_F(TextFragmentAnchorTest,
+       ShouldNotRequestUnhandledTapNotifierWhenTapOnTextFragment) {
+  base::test::ScopedFeatureList feature_list_;
+  feature_list_.InitAndEnableFeature(
+      shared_highlighting::kSharedHighlightingV2);
+  LoadAhem();
+  SimRequest request(
+      "https://example.com/"
+      "test.html#:~:text=this%20is%20a%20test%20page",
+      "text/html");
+  LoadURL(
+      "https://example.com/"
+      "test.html#:~:text=this%20is%20a%20test%20page");
+  request.Complete(R"HTML(
+    <!DOCTYPE html>
+    <style>p { font: 10px/1 Ahem; }</style>
+    <p id="first">This is a test page</p>
+    <p id="two">Second test page two</p>
+  )HTML");
+  RunAsyncMatchingTasks();
+  MockUnhandledTapNotifierImpl mock_notifier;
+  GetDocument().GetFrame()->GetBrowserInterfaceBroker().SetBinderForTesting(
+      mojom::blink::UnhandledTapNotifier::Name_,
+      WTF::BindRepeating(&MockUnhandledTapNotifierImpl::Bind,
+                         WTF::Unretained(&mock_notifier)));
+
+  Compositor().BeginFrame();
+
+  Range* range = Range::Create(GetDocument());
+  range->setStart(GetDocument().getElementById("first"), 0,
+                  IGNORE_EXCEPTION_FOR_TESTING);
+  range->setEnd(GetDocument().getElementById("first"), 1,
+                IGNORE_EXCEPTION_FOR_TESTING);
+  ASSERT_EQ("This is a test page", range->GetText());
+
+  mock_notifier.Reset();
+  IntPoint tap_point = range->BoundingBox().Center();
+  SimulateTap(tap_point.X(), tap_point.Y());
+
+  base::RunLoop().RunUntilIdle();
+  if (RuntimeEnabledFeatures::TextFragmentTapOpensContextMenuEnabled()) {
+    EXPECT_FALSE(mock_notifier.WasUnhandledTap());
+    EXPECT_FALSE(mock_notifier.ReceiverIsBound());
+  } else {
+    EXPECT_TRUE(mock_notifier.WasUnhandledTap());
+    EXPECT_TRUE(mock_notifier.ReceiverIsBound());
+  }
+
+  range->setStart(GetDocument().getElementById("two"), 0,
+                  IGNORE_EXCEPTION_FOR_TESTING);
+  range->setEndAfter(GetDocument().getElementById("two"),
+                     IGNORE_EXCEPTION_FOR_TESTING);
+  ASSERT_EQ("Second test page two", range->GetText());
+
+  mock_notifier.Reset();
+  tap_point = range->BoundingBox().Center();
+  SimulateTap(tap_point.X(), tap_point.Y());
+
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(mock_notifier.WasUnhandledTap());
+  EXPECT_TRUE(mock_notifier.ReceiverIsBound());
+}
+#endif  // BUILDFLAG(ENABLE_UNHANDLED_TAP)
+
 }  // namespace
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/embedded_object_painter.cc b/third_party/blink/renderer/core/paint/embedded_object_painter.cc
index bebbbd98..c88a78dd 100644
--- a/third_party/blink/renderer/core/paint/embedded_object_painter.cc
+++ b/third_party/blink/renderer/core/paint/embedded_object_painter.cc
@@ -25,10 +25,10 @@
 static const float kReplacementTextRoundedRectRadius = 5;
 static const float kReplacementTextTextOpacity = 0.55f;
 
-static Font ReplacementTextFont() {
+static Font ReplacementTextFont(const Document* document) {
   FontDescription font_description;
   LayoutTheme::GetTheme().SystemFont(CSSValueID::kWebkitSmallControl,
-                                     font_description);
+                                     font_description, document);
   font_description.SetWeight(BoldWeightValue());
   font_description.SetComputedSize(font_description.SpecifiedSize());
   Font font(font_description);
@@ -56,7 +56,7 @@
   BoxDrawingRecorder recorder(context, layout_embedded_object_,
                               paint_info.phase, paint_offset);
 
-  Font font = ReplacementTextFont();
+  Font font = ReplacementTextFont(&layout_embedded_object_.GetDocument());
   const SimpleFontData* font_data = font.PrimaryFont();
   DCHECK(font_data);
   if (!font_data)
diff --git a/third_party/blink/renderer/core/scroll/scrollbar.h b/third_party/blink/renderer/core/scroll/scrollbar.h
index a0eb0e9b..b5b2906 100644
--- a/third_party/blink/renderer/core/scroll/scrollbar.h
+++ b/third_party/blink/renderer/core/scroll/scrollbar.h
@@ -199,8 +199,8 @@
   EScrollbarWidth CSSScrollbarWidth() const;
 
   // The Element that supplies our style information. If the scrollbar is
-  // for a document, this is either the <body> or <html> element. Otherwise, it
-  // is the element that owns our PaintLayerScrollableArea.
+  // for a document, this returns nullptr. Otherwise, it is the element that
+  // owns our PaintLayerScrollableArea.
   Element* StyleSource() const { return style_source_.Get(); }
 
   mojom::blink::ColorScheme UsedColorScheme() const;
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm b/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm
index 05b828f..42caecb 100644
--- a/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm
+++ b/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm
@@ -258,6 +258,7 @@
 
   params.scrollbar_extra.is_hovering =
       scrollbar.HoveredPart() != ScrollbarPart::kNoPart;
+  params.scrollbar_extra.scale_from_dip = scrollbar.ScaleFromDIP();
   return params;
 }
 
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc
index e6b51df34..b7a4bfb 100644
--- a/third_party/blink/renderer/core/style/computed_style.cc
+++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -37,6 +37,7 @@
 #include "third_party/blink/renderer/core/css/css_paint_value.h"
 #include "third_party/blink/renderer/core/css/css_primitive_value.h"
 #include "third_party/blink/renderer/core/css/css_property_equality.h"
+#include "third_party/blink/renderer/core/css/css_property_names.h"
 #include "third_party/blink/renderer/core/css/properties/css_property.h"
 #include "third_party/blink/renderer/core/css/properties/longhand.h"
 #include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
@@ -1008,14 +1009,11 @@
 static bool HasPropertyThatCreatesStackingContext(
     const Vector<CSSPropertyID>& properties) {
   for (CSSPropertyID property : properties) {
-    switch (property) {
+    switch (ResolveCSSPropertyID(property)) {
       case CSSPropertyID::kOpacity:
       case CSSPropertyID::kTransform:
-      case CSSPropertyID::kAliasWebkitTransform:
       case CSSPropertyID::kTransformStyle:
-      case CSSPropertyID::kAliasWebkitTransformStyle:
       case CSSPropertyID::kPerspective:
-      case CSSPropertyID::kAliasWebkitPerspective:
       case CSSPropertyID::kTranslate:
       case CSSPropertyID::kRotate:
       case CSSPropertyID::kScale:
@@ -1024,10 +1022,8 @@
       case CSSPropertyID::kWebkitMask:
       case CSSPropertyID::kWebkitMaskBoxImage:
       case CSSPropertyID::kClipPath:
-      case CSSPropertyID::kAliasWebkitClipPath:
       case CSSPropertyID::kWebkitBoxReflect:
       case CSSPropertyID::kFilter:
-      case CSSPropertyID::kAliasWebkitFilter:
       case CSSPropertyID::kBackdropFilter:
       case CSSPropertyID::kZIndex:
       case CSSPropertyID::kPosition:
@@ -1082,9 +1078,8 @@
 }
 
 static bool IsWillChangeTransformHintProperty(CSSPropertyID property) {
-  switch (property) {
+  switch (ResolveCSSPropertyID(property)) {
     case CSSPropertyID::kTransform:
-    case CSSPropertyID::kAliasWebkitTransform:
     case CSSPropertyID::kPerspective:
     case CSSPropertyID::kTranslate:
     case CSSPropertyID::kScale:
@@ -1092,7 +1087,6 @@
     case CSSPropertyID::kOffsetPath:
     case CSSPropertyID::kOffsetPosition:
     case CSSPropertyID::kTransformStyle:
-    case CSSPropertyID::kAliasWebkitTransformStyle:
       return true;
     default:
       break;
@@ -1103,10 +1097,9 @@
 static bool IsWillChangeCompositingHintProperty(CSSPropertyID property) {
   if (IsWillChangeTransformHintProperty(property))
     return true;
-  switch (property) {
+  switch (ResolveCSSPropertyID(property)) {
     case CSSPropertyID::kOpacity:
     case CSSPropertyID::kFilter:
-    case CSSPropertyID::kAliasWebkitFilter:
     case CSSPropertyID::kBackdropFilter:
     case CSSPropertyID::kTop:
     case CSSPropertyID::kLeft:
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h
index a3d07a72..f3d168a9 100644
--- a/third_party/blink/renderer/core/style/computed_style.h
+++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -1416,7 +1416,8 @@
   // Will-change utility functions.
   bool HasWillChangeCompositingHint() const;
   bool HasWillChangeOpacityHint() const {
-    return WillChangeProperties().Contains(CSSPropertyID::kOpacity);
+    return WillChangeProperties().Contains(CSSPropertyID::kOpacity) ||
+           WillChangeProperties().Contains(CSSPropertyID::kAliasWebkitOpacity);
   }
   bool HasWillChangeTransformHint() const;
   bool HasWillChangeFilterHint() const {
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
index bde147e..cb8e6fc 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -4263,8 +4263,7 @@
   if (!GetNode())
     return;
 
-  if (GetDocument()->IsFlatTreeTraversalForbidden() ||
-      GetDocument()->IsSlotAssignmentRecalcForbidden()) {
+  if (GetDocument()->IsFlatTreeTraversalForbidden()) {
     // Cannot use layout tree builder traversal now, will have to rely on
     // RepairParent() at a later point.
     return;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
index 04a4cc46..02882088 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -234,8 +234,8 @@
   if (!child && elem) {
     // No children of inline element. Check adjacent sibling in same direction.
     Node* adjacent_node =
-        is_after ? FlatTreeTraversal::NextSkippingChildren(*elem)
-                 : FlatTreeTraversal::PreviousAbsoluteSibling(*elem);
+        is_after ? NodeTraversal::NextIncludingPseudoSkippingChildren(*elem)
+                 : NodeTraversal::PreviousAbsoluteSiblingIncludingPseudo(*elem);
     return adjacent_node &&
            CanIgnoreSpaceNextTo(adjacent_node->GetLayoutObject(), is_after,
                                 ++counter);
@@ -247,7 +247,7 @@
   if (!layout_text.Parent())
     return false;
 
-  Node* node = layout_text.GetNode();
+  const Node* node = layout_text.GetNode();
   DCHECK(node);  // Anonymous text is processed earlier, doesn't reach here.
 
   // Ignore empty text.
@@ -261,12 +261,15 @@
   // Will now look at sibling nodes. We need the closest element to the
   // whitespace markup-wise, e.g. tag1 in these examples:
   // [whitespace] <tag1><tag2>x</tag2></tag1>
-  // <span>[whitespace]</span> <tag1><tag2>x</tag2></tag1>
-  Node* prev_node = FlatTreeTraversal::PreviousAbsoluteSibling(*node);
+  // <span>[whitespace]</span> <tag1><tag2>x</tag2></tag1>.
+  // Do not use LayoutTreeBuilderTraversal or FlatTreeTraversal as this may need
+  // to be called during slot assignment, when flat tree traversal is forbidden.
+  Node* prev_node =
+      NodeTraversal::PreviousAbsoluteSiblingIncludingPseudo(*node);
   if (!prev_node)
     return false;
 
-  Node* next_node = FlatTreeTraversal::NextSkippingChildren(*node);
+  Node* next_node = NodeTraversal::NextIncludingPseudoSkippingChildren(*node);
   if (!next_node)
     return false;
 
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
index 3514f09..d067b902 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
@@ -213,6 +213,9 @@
 
   // Get an AXObject* backed by the passed-in DOM node or the node's layout
   // object, whichever is available.
+  // If it no longer the correct type of AXObject (AXNodeObject/AXLayoutObject),
+  // will Invalidate() the AXObject so that it is refreshed with a new object
+  // when safe to do so.
   AXObject* Get(const Node*);
   AXObject* Get(const LayoutObject*);
 
diff --git a/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc b/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc
index 3d5d7585f..179832a 100644
--- a/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc
+++ b/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc
@@ -197,7 +197,8 @@
 
 AudioData* MakeAudioData(ScriptState* script_state,
                          const wc_fuzzer::AudioDataInit& proto) {
-  if (proto.channels().size() > media::limits::kMaxChannels)
+  if (!proto.channels().size() ||
+      proto.channels().size() > media::limits::kMaxChannels)
     return nullptr;
 
   if (proto.length() > media::limits::kMaxSamplesPerPacket)
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
index 85f167c7..31493f3 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
@@ -95,28 +95,59 @@
   neutered_ = true;
 }
 
+std::unique_ptr<WebGPUSwapBufferProvider::SwapBuffer>
+WebGPUSwapBufferProvider::NewOrRecycledSwapBuffer(const gfx::Size& size) {
+  // Recycled SwapBuffers must be the same size.
+  if (!unused_swap_buffers_.IsEmpty() &&
+      unused_swap_buffers_.back()->size != size) {
+    unused_swap_buffers_.clear();
+  }
+
+  if (unused_swap_buffers_.IsEmpty()) {
+    gpu::SharedImageInterface* sii =
+        dawn_control_client_->GetContextProvider()->SharedImageInterface();
+
+    gpu::Mailbox mailbox = sii->CreateSharedImage(
+        format_, static_cast<gfx::Size>(size), gfx::ColorSpace::CreateSRGB(),
+        kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
+        gpu::SHARED_IMAGE_USAGE_WEBGPU |
+            gpu::SHARED_IMAGE_USAGE_WEBGPU_SWAP_CHAIN_TEXTURE |
+            gpu::SHARED_IMAGE_USAGE_DISPLAY,
+        gpu::kNullSurfaceHandle);
+    gpu::SyncToken creation_token = sii->GenUnverifiedSyncToken();
+
+    unused_swap_buffers_.push_back(
+        std::make_unique<SwapBuffer>(this, mailbox, creation_token, size));
+    DCHECK_EQ(unused_swap_buffers_.back()->size, size);
+  }
+
+  std::unique_ptr<SwapBuffer> swap_buffer =
+      std::move(unused_swap_buffers_.back());
+  unused_swap_buffers_.pop_back();
+
+  return swap_buffer;
+}
+
+void WebGPUSwapBufferProvider::RecycleSwapBuffer(
+    std::unique_ptr<SwapBuffer> swap_buffer) {
+  // We don't want to keep an arbitrary large number of swap buffers.
+  if (unused_swap_buffers_.size() >
+      static_cast<unsigned int>(kMaxRecycledSwapBuffers))
+    return;
+
+  unused_swap_buffers_.push_back(std::move(swap_buffer));
+}
+
 WGPUTexture WebGPUSwapBufferProvider::GetNewTexture(const IntSize& size) {
   DCHECK(!current_swap_buffer_);
 
   gpu::webgpu::WebGPUInterface* webgpu = dawn_control_client_->GetInterface();
-  gpu::SharedImageInterface* sii =
-      dawn_control_client_->GetContextProvider()->SharedImageInterface();
 
   // Create a new swap buffer.
-  // TODO(cwallez@chromium.org): have some recycling mechanism.
-  gpu::Mailbox mailbox = sii->CreateSharedImage(
-      format_, static_cast<gfx::Size>(size), gfx::ColorSpace::CreateSRGB(),
-      kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
-      gpu::SHARED_IMAGE_USAGE_WEBGPU |
-          gpu::SHARED_IMAGE_USAGE_WEBGPU_SWAP_CHAIN_TEXTURE |
-          gpu::SHARED_IMAGE_USAGE_DISPLAY,
-      gpu::kNullSurfaceHandle);
-  gpu::SyncToken creation_token = sii->GenUnverifiedSyncToken();
+  current_swap_buffer_ = NewOrRecycledSwapBuffer(gfx::Size(size));
 
-  current_swap_buffer_ = base::AdoptRef(new SwapBuffer(
-      this, mailbox, creation_token, static_cast<gfx::Size>(size)));
-
-  // Ensure the shared image is allocated service-side before working with it
+  // Ensure the shared image is allocated and not in use service-side before
+  // working with it
   webgpu->WaitSyncTokenCHROMIUM(
       current_swap_buffer_->access_finished_token.GetConstData());
 
@@ -188,11 +219,11 @@
 
   // This holds a ref on the SwapBuffers that will keep it alive until the
   // mailbox is released (and while the release callback is running).
-  *out_release_callback = WTF::Bind(
-      &WebGPUSwapBufferProvider::MailboxReleased,
-      scoped_refptr<WebGPUSwapBufferProvider>(this), current_swap_buffer_);
+  *out_release_callback =
+      WTF::Bind(&WebGPUSwapBufferProvider::MailboxReleased,
+                scoped_refptr<WebGPUSwapBufferProvider>(this),
+                std::move(current_swap_buffer_));
 
-  current_swap_buffer_ = nullptr;
   wire_texture_id_ = 0;
   wire_texture_generation_ = 0;
 
@@ -200,12 +231,15 @@
 }
 
 void WebGPUSwapBufferProvider::MailboxReleased(
-    scoped_refptr<SwapBuffer> swap_buffer,
+    std::unique_ptr<SwapBuffer> swap_buffer,
     const gpu::SyncToken& sync_token,
     bool lost_resource) {
   // Update the SyncToken to ensure that we will wait for it even if we
   // immediately destroy this buffer.
   swap_buffer->access_finished_token = sync_token;
+
+  if (!lost_resource)
+    RecycleSwapBuffer(std::move(swap_buffer));
 }
 
 WebGPUSwapBufferProvider::SwapBuffer::SwapBuffer(
@@ -225,4 +259,8 @@
   sii->DestroySharedImage(access_finished_token, mailbox);
 }
 
+gpu::Mailbox WebGPUSwapBufferProvider::GetCurrentMailboxForTesting() const {
+  DCHECK(current_swap_buffer_);
+  return current_swap_buffer_->mailbox;
+}
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h
index 936f55b..3ddf462 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h
@@ -54,9 +54,11 @@
       viz::TransferableResource* out_resource,
       viz::ReleaseCallback* out_release_callback) override;
 
+  gpu::Mailbox GetCurrentMailboxForTesting() const;
+
  private:
   // Holds resources and synchronization for one of the swapchain images.
-  struct SwapBuffer : public RefCounted<SwapBuffer> {
+  struct SwapBuffer {
     SwapBuffer(WebGPUSwapBufferProvider*,
                gpu::Mailbox mailbox,
                gpu::SyncToken creation_token,
@@ -66,10 +68,12 @@
     gfx::Size size;
     gpu::Mailbox mailbox;
 
-    // A reference back to the swap buffers to keep it alive while this image
-    // is in flight so that the destructor can access data in the swap
-    // buffers.
-    scoped_refptr<WebGPUSwapBufferProvider> swap_buffers;
+    // A reference back to the swap buffers so that the destructor can access
+    // data in the swap buffers. This is a weak reference since the swap buffer
+    // is held alive by both the provider and the TransferableResource. If the
+    // swap chain gets destroyed, the TransferableResource release CB
+    // keeps the in-flight swap buffer alive.
+    WebGPUSwapBufferProvider* swap_buffers = nullptr;
 
     // A token signaled when the previous user of the image is finished using
     // it. It could be WebGPU, the compositor or the shared image creation.
@@ -79,7 +83,12 @@
     DISALLOW_COPY_AND_ASSIGN(SwapBuffer);
   };
 
-  void MailboxReleased(scoped_refptr<SwapBuffer> swap_buffer,
+  std::unique_ptr<WebGPUSwapBufferProvider::SwapBuffer> NewOrRecycledSwapBuffer(
+      const gfx::Size& size);
+
+  void RecycleSwapBuffer(std::unique_ptr<SwapBuffer> swap_buffer);
+
+  void MailboxReleased(std::unique_ptr<SwapBuffer> swap_buffer,
                        const gpu::SyncToken& sync_token,
                        bool lost_resource);
 
@@ -91,9 +100,15 @@
 
   WGPUTextureUsage usage_;
 
+  // The maximum number of in-flight swap-buffers waiting to be used for
+  // recycling.
+  static constexpr int kMaxRecycledSwapBuffers = 3;
+
+  WTF::Vector<std::unique_ptr<SwapBuffer>> unused_swap_buffers_;
+
   uint32_t wire_texture_id_ = 0;
   uint32_t wire_texture_generation_ = 0;
-  scoped_refptr<SwapBuffer> current_swap_buffer_;
+  std::unique_ptr<SwapBuffer> current_swap_buffer_;
   viz::ResourceFormat format_;
 };
 
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc
index 3441283d..35039d1 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc
@@ -237,7 +237,136 @@
   gpu::SyncToken release_token;
   webgpu_->GenSyncTokenCHROMIUM(release_token.GetData());
   std::move(release_callback).Run(release_token, false /* lostResource */);
+
+  // Release the unused swap buffers held by the provider.
+  provider_ = nullptr;
+
   EXPECT_EQ(sii_->MostRecentDestroyToken(), release_token);
 }
 
+// Ensures swap buffers will be recycled.
+// Creates two swap buffers, destroys them, then creates them again.
+TEST_F(WebGPUSwapBufferProviderTest, ReuseSwapBuffers) {
+  const IntSize kSize(10, 10);
+
+  base::flat_set<gpu::Mailbox> shared_images = {};
+
+  viz::TransferableResource resource;
+  gpu::webgpu::ReservedTexture reservation = {
+      reinterpret_cast<WGPUTexture>(&resource), 1, 1};
+
+  // Produce swap buffers
+  viz::ReleaseCallback release_callback_1;
+  EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+      .WillOnce(Return(reservation));
+  provider_->GetNewTexture(static_cast<IntSize>(kSize));
+
+  EXPECT_TRUE(
+      shared_images.insert(provider_->GetCurrentMailboxForTesting()).second);
+
+  EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
+                                                     &release_callback_1));
+
+  viz::ReleaseCallback release_callback_2;
+  EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+      .WillOnce(Return(reservation));
+  provider_->GetNewTexture(static_cast<IntSize>(kSize));
+
+  EXPECT_TRUE(
+      shared_images.insert(provider_->GetCurrentMailboxForTesting()).second);
+
+  EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
+                                                     &release_callback_2));
+
+  // Destroy the swap buffers.
+  std::move(release_callback_1).Run(gpu::SyncToken(), false /* lostResource */);
+  std::move(release_callback_2).Run(gpu::SyncToken(), false /* lostResource */);
+
+  // Produce swap buffers again
+  EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+      .WillOnce(Return(reservation));
+  provider_->GetNewTexture(static_cast<IntSize>(kSize));
+
+  EXPECT_FALSE(
+      shared_images.insert(provider_->GetCurrentMailboxForTesting()).second);
+
+  EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
+                                                     &release_callback_1));
+
+  EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+      .WillOnce(Return(reservation));
+  provider_->GetNewTexture(static_cast<IntSize>(kSize));
+
+  EXPECT_FALSE(
+      shared_images.insert(provider_->GetCurrentMailboxForTesting()).second);
+
+  EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
+                                                     &release_callback_2));
+}
+
+// Ensures swap buffers will NOT be recycled if resized.
+// Creates two swap buffers of a size, destroys them, then creates them again
+// with a different size.
+TEST_F(WebGPUSwapBufferProviderTest, ReuseSwapBufferResize) {
+  base::flat_set<gpu::Mailbox> shared_images = {};
+
+  viz::TransferableResource resource;
+  gpu::webgpu::ReservedTexture reservation = {
+      reinterpret_cast<WGPUTexture>(&resource), 1, 1};
+
+  // Create swap buffers
+  const IntSize kSize(10, 10);
+
+  viz::ReleaseCallback release_callback_1;
+  EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+      .WillOnce(Return(reservation));
+  provider_->GetNewTexture(static_cast<IntSize>(kSize));
+
+  EXPECT_TRUE(
+      shared_images.insert(provider_->GetCurrentMailboxForTesting()).second);
+
+  EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
+                                                     &release_callback_1));
+
+  viz::ReleaseCallback release_callback_2;
+  EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+      .WillOnce(Return(reservation));
+  provider_->GetNewTexture(static_cast<IntSize>(kSize));
+
+  EXPECT_TRUE(
+      shared_images.insert(provider_->GetCurrentMailboxForTesting()).second);
+
+  EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
+                                                     &release_callback_2));
+
+  // Destroy swap buffers
+  std::move(release_callback_1).Run(gpu::SyncToken(), false /* lostResource */);
+  std::move(release_callback_2).Run(gpu::SyncToken(), false /* lostResource */);
+
+  // Create swap buffers again with different size.
+  const IntSize kOtherSize(20, 20);
+
+  viz::ReleaseCallback release_callback_3;
+  EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+      .WillOnce(Return(reservation));
+  provider_->GetNewTexture(static_cast<IntSize>(kOtherSize));
+
+  EXPECT_TRUE(
+      shared_images.insert(provider_->GetCurrentMailboxForTesting()).second);
+
+  EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
+                                                     &release_callback_3));
+
+  viz::ReleaseCallback release_callback_4;
+  EXPECT_CALL(*webgpu_, ReserveTexture(fake_device_))
+      .WillOnce(Return(reservation));
+  provider_->GetNewTexture(static_cast<IntSize>(kOtherSize));
+
+  EXPECT_TRUE(
+      shared_images.insert(provider_->GetCurrentMailboxForTesting()).second);
+
+  EXPECT_TRUE(provider_->PrepareTransferableResource(nullptr, &resource,
+                                                     &release_callback_4));
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 0d75913..9c931aea 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -209,10 +209,6 @@
       status: "experimental",
     },
     {
-      name: "AutofillShadowDOM",
-      status: "experimental",
-    },
-    {
       name: "AutoLazyLoadOnReloads",
       depends_on: ["LazyFrameLoading"],
     },
diff --git a/third_party/blink/renderer/platform/theme/web_theme_engine_mac.cc b/third_party/blink/renderer/platform/theme/web_theme_engine_mac.cc
index c2dbbde..38623fc 100644
--- a/third_party/blink/renderer/platform/theme/web_theme_engine_mac.cc
+++ b/third_party/blink/renderer/platform/theme/web_theme_engine_mac.cc
@@ -51,6 +51,8 @@
       extra_params->scrollbar_extra.is_hovering;
   native_theme_extra_params.scrollbar_extra.is_overlay =
       extra_params->scrollbar_extra.is_overlay;
+  native_theme_extra_params.scrollbar_extra.scale_from_dip =
+      extra_params->scrollbar_extra.scale_from_dip;
   switch (extra_params->scrollbar_extra.orientation) {
     case WebThemeEngine::kVerticalOnRight:
       native_theme_extra_params.scrollbar_extra.orientation =
diff --git a/third_party/blink/renderer/platform/widget/widget_base.cc b/third_party/blink/renderer/platform/widget/widget_base.cc
index bcf1146..bf5ab4d 100644
--- a/third_party/blink/renderer/platform/widget/widget_base.cc
+++ b/third_party/blink/renderer/platform/widget/widget_base.cc
@@ -822,6 +822,14 @@
       tooltip_text.IsEmpty() ? "" : tooltip_text, ToBaseTextDirection(dir));
 }
 
+void WidgetBase::UpdateTooltipFromKeyboard(const String& tooltip_text,
+                                           TextDirection dir,
+                                           const gfx::Rect& bounds) {
+  widget_host_->UpdateTooltipFromKeyboard(
+      tooltip_text.IsEmpty() ? "" : tooltip_text, ToBaseTextDirection(dir),
+      BlinkSpaceToEnclosedDIPs(bounds));
+}
+
 void WidgetBase::ShowVirtualKeyboard() {
   UpdateTextInputStateInternal(true, false);
 }
diff --git a/third_party/blink/renderer/platform/widget/widget_base.h b/third_party/blink/renderer/platform/widget/widget_base.h
index 5eb9c42a..4c020d97 100644
--- a/third_party/blink/renderer/platform/widget/widget_base.h
+++ b/third_party/blink/renderer/platform/widget/widget_base.h
@@ -187,6 +187,12 @@
   WidgetBaseClient* client() { return client_; }
 
   void UpdateTooltipUnderCursor(const String& tooltip_text, TextDirection dir);
+  // This function allows us to trigger a tooltip to show from a keypress. The
+  // tooltip will be positioned relative to the gfx::Rect. That rect corresponds
+  // to the focused element's bounds in widget-relative DIPS.
+  void UpdateTooltipFromKeyboard(const String& tooltip_text,
+                                 TextDirection dir,
+                                 const gfx::Rect& bounds);
 
   // Posts a task with the given delay, then calls ScheduleAnimation() on the
   // WidgetBaseClient.
diff --git a/third_party/blink/web_tests/WebDriverExpectations b/third_party/blink/web_tests/WebDriverExpectations
index c70ae6a..b98ce99c 100644
--- a/third_party/blink/web_tests/WebDriverExpectations
+++ b/third_party/blink/web_tests/WebDriverExpectations
@@ -1,4 +1,4 @@
-# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ]
+# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Mac10.14 Mac10.15 Mac11.0 Win Win7 Win10 ]
 # tags: [ Release Debug ]
 # results: [ Timeout Crash Pass Failure Slow Skip ]
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/system-fonts-serialization.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/system-fonts-serialization.tentative.html
new file mode 100644
index 0000000..6abd6f0
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/system-fonts-serialization.tentative.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Fonts Test: Serialization of system fonts</title>
+<link rel="help" href="https://drafts.csswg.org/css-fonts/#valdef-font-caption">
+<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com">
+<div id="target"></div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+const target = document.getElementById("target");
+target.style.font = "initial";
+const fontLonghands = [...target.style];
+
+const cs = getComputedStyle(target);
+function copyComputedStyle() {
+  const data = {};
+  data.font = cs.font;
+  for (const longhand of fontLonghands) {
+    data[longhand] = cs[longhand];
+  }
+  return data;
+}
+
+function check(systemFont) {
+  target.style.cssText = "";
+  target.style.font = systemFont;
+
+  assert_equals(target.style.font, systemFont, "System font serializes as-is");
+  assert_array_equals([...target.style], fontLonghands, "System font sets all longhands");
+  for (const longhand of fontLonghands) {
+    assert_equals(target.style[longhand], "", `Longhand '${longhand}' serializes as empty string`);
+  }
+
+  const copy = copyComputedStyle();
+  for (const longhand of fontLonghands) {
+    const resolvedStyle = cs[longhand];
+    assert_not_equals(resolvedStyle, "");
+
+    target.style[longhand] = resolvedStyle;
+    assert_equals(target.style[longhand], resolvedStyle, `Can set longhand '${longhand}'`);
+
+    assert_equals(target.style.font, "", `Shorthand serializes as empty string after setting '${longhand}'`);
+    assert_object_equals(copyComputedStyle(), copy, `Other longhands still work  after setting '${longhand}'`);
+
+    target.style.font = systemFont;
+  }
+}
+
+// Standard system fonts
+const systemFonts = ["caption", "icon", "menu", "message-box", "small-caption", "status-bar"];
+
+// Some browsers also support these non-standard system fonts
+const extras = ["-webkit-mini-control", "-webkit-small-control", "-webkit-control"];
+
+for (const extra of extras) {
+  if (CSS.supports("font", extra)) {
+    systemFonts.push(extra);
+  }
+}
+
+for (let systemFont of systemFonts) {
+  test(() => check(systemFont), systemFont);
+}
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-tables/absolute-tables-003-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-tables/absolute-tables-003-expected.txt
deleted file mode 100644
index f1b3b49..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-tables/absolute-tables-003-expected.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-This is a testharness.js-based test.
-PASS .table 1
-PASS .table 2
-FAIL .table 3 assert_equals: 
-<table class="table vertical" data-expected-width="50" data-offset-x="150">
-    <tbody><tr>
-      <td class="cell" data-expected-width="46">
-        <div></div>
-      </td>
-    </tr>
-  </tbody></table>
-width expected 50 but got 108
-FAIL .table 4 assert_equals: 
-<table class="table vertical" data-expected-width="50" data-offset-x="150">
-    <tbody><tr>
-      <td class="cell" data-expected-width="46">
-        <div></div>
-      </td>
-    </tr>
-  </tbody></table>
-width expected 50 but got 108
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-tables/absolute-tables-003.html b/third_party/blink/web_tests/external/wpt/css/css-tables/absolute-tables-003.html
index 352d8cd62..a4f945e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-tables/absolute-tables-003.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-tables/absolute-tables-003.html
@@ -56,18 +56,18 @@
   </table>
 </div>
 <div class="cb">
-  <table class="table vertical" data-expected-width=50 data-offset-x="150">
+  <table class="table vertical" data-expected-width=108 data-offset-x="92">
     <tr>
-      <td class="cell" data-expected-width=46>
+      <td class="cell" data-expected-width=104>
         <div></div>
       </td>
     </tr>
   </table>
 </div>
 <div class="cb vertical">
-  <table class="table vertical" data-expected-width=50 data-offset-x="150">
+  <table class="table vertical" data-expected-width=108 data-offset-x="92">
     <tr>
-      <td class="cell" data-expected-width=46>
+      <td class="cell" data-expected-width=104>
         <div></div>
       </td>
     </tr>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-tables/absolute-tables-005-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-tables/absolute-tables-005-expected.txt
deleted file mode 100644
index 9ceaa9a0..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-tables/absolute-tables-005-expected.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-This is a testharness.js-based test.
-PASS .table 1
-PASS .table 2
-FAIL .table 3 assert_equals: 
-<table class="table vertical" data-expected-width="8" data-expected-height="108" data-offset-x="192">
-    <tbody><tr>
-      <td class="cell">
-        <div></div>
-      </td>
-    </tr>
-  </tbody></table>
-height expected 108 but got 50
-FAIL .table 4 assert_equals: 
-<table class="table vertical" data-expected-width="8" data-expected-height="108" data-offset-x="192">
-    <tbody><tr>
-      <td class="cell">
-        <div></div>
-      </td>
-    </tr>
-  </tbody></table>
-height expected 108 but got 50
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-tables/absolute-tables-005.html b/third_party/blink/web_tests/external/wpt/css/css-tables/absolute-tables-005.html
index 57c3f0de..24444d3b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-tables/absolute-tables-005.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-tables/absolute-tables-005.html
@@ -56,7 +56,7 @@
   </table>
 </div>
 <div class="cb">
-  <table class="table vertical" data-expected-width=8 data-expected-height=108 data-offset-x="192">
+  <table class="table vertical" data-expected-width=8 data-expected-height=50 data-offset-x="192">
     <tr>
       <td class="cell">
         <div></div>
@@ -65,7 +65,7 @@
   </table>
 </div>
 <div class="cb vertical">
-  <table class="table vertical" data-expected-width=8 data-expected-height=108 data-offset-x="192">
+  <table class="table vertical" data-expected-width=8 data-expected-height=50 data-offset-x="192">
     <tr>
       <td class="cell">
         <div></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-will-change/will-change-fixpos-cb-webkit-perspective-1.html b/third_party/blink/web_tests/external/wpt/css/css-will-change/will-change-fixpos-cb-webkit-perspective-1.html
new file mode 100644
index 0000000..2438dcd
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-will-change/will-change-fixpos-cb-webkit-perspective-1.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS will-change: 'will-change: -webkit-perspective' creates a containing block for fixed positioned elements</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/">
+<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
+<link rel="author" title="Google" href="https://www.google.com/">
+<link rel="help" href="https://drafts.csswg.org/css-will-change-1/#will-change">
+<link rel="help" href="http://www.w3.org/TR/css3-transforms/#perspective-property">
+<link rel="help" href="https://compat.spec.whatwg.org/#css-simple-aliases">
+<link rel="match" href="green-square-100-by-100-offset-ref.html">
+<meta name="assert" content="If any non-initial value of a property would cause the element to generate a containing block for fixed-position elements, specifying that property in will-change must cause the element to generate a containing block for fixed-position elements.">
+<style>
+html, body { margin: 0; padding: 0; }
+div { width: 100px; height: 100px }
+#wc { will-change: -webkit-perspective; margin: 100px 0 0 100px; background: red }
+.child { top: 0; left: 0; width: 50px; background: green }
+#fixpos { position: fixed }
+#abspos { position: absolute; left: 50px }
+</style>
+<body>
+  <div id="wc">
+    <div class="child" id="fixpos">
+    </div>
+    <div class="child" id="abspos">
+    </div>
+  </div>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/layout-instability/mousemove-becomes-drag.html b/third_party/blink/web_tests/external/wpt/layout-instability/mousemove-becomes-drag.html
new file mode 100644
index 0000000..df4a416c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/layout-instability/mousemove-becomes-drag.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<title>Layout Instability: no shift in mouse moves with a button pressed</title>
+<link rel="help" href="https://wicg.github.io/layout-instability/" />
+<style>
+
+body { margin: 0; height: 2000px; }
+#draggable {
+  top:50px;
+  left:50px;
+  width:50px;
+  height:50px;
+  background-color:blue;
+  position:absolute
+}
+
+</style>
+<div id="draggable" ></div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="resources/util.js"></script>
+<script>
+
+const draggable = document.getElementById("draggable");
+draggable.addEventListener('mousemove', function(event) {
+  // Move the element when the mouse moves.
+  draggable.style.top = event.pageY - 25 + 'px';
+  event.preventDefault();
+}, false);
+
+generateMouseMoveSequence = () => new test_driver.Actions()
+    .pointerMove(0, 0, {origin: draggable})
+    .pointerDown()
+    .pointerMove(0, 15, {origin: draggable})
+    .pause(100)
+    .pointerMove(0, 30, {origin: draggable})
+    .pause(100)
+    .pointerMove(0, 45, {origin: draggable})
+    .pause(100)
+    .pointerUp()
+    .pause(100);
+
+promise_test(async () => {
+
+  const watcher = new ScoreWatcher;
+
+  // Wait for the initial render to complete.
+  await waitForAnimationFrames(2);
+
+  // Send pointer events for a sequence of mouse actions, mouse down, mouse moves and mouse up.
+  await generateMouseMoveSequence().send();
+
+  // Mouse moves which drag the objects should be counted as the excluding inputs
+  // for the layout shift.
+  assert_greater_than(watcher.score, 0);
+  assert_equals(watcher.scoreWithInputExclusion, 0);
+
+}, "No layout shift when mouse moves with a button pressed.");
+
+</script>
diff --git a/third_party/blink/web_tests/fast/css/font-shorthand-expected.txt b/third_party/blink/web_tests/fast/css/font-shorthand-expected.txt
index 845e28c..a8a5c62 100644
--- a/third_party/blink/web_tests/fast/css/font-shorthand-expected.txt
+++ b/third_party/blink/web_tests/fast/css/font-shorthand-expected.txt
@@ -107,112 +107,112 @@
 font-family: Arial, sans-serif
 
 Longhands for font: caption
-font-style
-font-weight
-font-size
-font-family
-font-stretch
-font-variant-caps
-font-variant-ligatures
-font-variant-numeric
-font-variant-east-asian
-line-height
+font-style: 
+font-variant-ligatures: 
+font-variant-caps: 
+font-variant-numeric: 
+font-variant-east-asian: 
+font-weight: 
+font-stretch: 
+font-size: 
+line-height: 
+font-family: 
 
 Longhands for font: icon
-font-style
-font-weight
-font-size
-font-family
-font-stretch
-font-variant-caps
-font-variant-ligatures
-font-variant-numeric
-font-variant-east-asian
-line-height
+font-style: 
+font-variant-ligatures: 
+font-variant-caps: 
+font-variant-numeric: 
+font-variant-east-asian: 
+font-weight: 
+font-stretch: 
+font-size: 
+line-height: 
+font-family: 
 
 Longhands for font: menu
-font-style
-font-weight
-font-size
-font-family
-font-stretch
-font-variant-caps
-font-variant-ligatures
-font-variant-numeric
-font-variant-east-asian
-line-height
+font-style: 
+font-variant-ligatures: 
+font-variant-caps: 
+font-variant-numeric: 
+font-variant-east-asian: 
+font-weight: 
+font-stretch: 
+font-size: 
+line-height: 
+font-family: 
 
 Longhands for font: message-box
-font-style
-font-weight
-font-size
-font-family
-font-stretch
-font-variant-caps
-font-variant-ligatures
-font-variant-numeric
-font-variant-east-asian
-line-height
+font-style: 
+font-variant-ligatures: 
+font-variant-caps: 
+font-variant-numeric: 
+font-variant-east-asian: 
+font-weight: 
+font-stretch: 
+font-size: 
+line-height: 
+font-family: 
 
 Longhands for font: small-caption
-font-style
-font-weight
-font-size
-font-family
-font-stretch
-font-variant-caps
-font-variant-ligatures
-font-variant-numeric
-font-variant-east-asian
-line-height
+font-style: 
+font-variant-ligatures: 
+font-variant-caps: 
+font-variant-numeric: 
+font-variant-east-asian: 
+font-weight: 
+font-stretch: 
+font-size: 
+line-height: 
+font-family: 
 
 Longhands for font: status-bar
-font-style
-font-weight
-font-size
-font-family
-font-stretch
-font-variant-caps
-font-variant-ligatures
-font-variant-numeric
-font-variant-east-asian
-line-height
+font-style: 
+font-variant-ligatures: 
+font-variant-caps: 
+font-variant-numeric: 
+font-variant-east-asian: 
+font-weight: 
+font-stretch: 
+font-size: 
+line-height: 
+font-family: 
 
 Longhands for font: -webkit-mini-control
-font-style
-font-weight
-font-size
-font-family
-font-stretch
-font-variant-caps
-font-variant-ligatures
-font-variant-numeric
-font-variant-east-asian
-line-height
+font-style: 
+font-variant-ligatures: 
+font-variant-caps: 
+font-variant-numeric: 
+font-variant-east-asian: 
+font-weight: 
+font-stretch: 
+font-size: 
+line-height: 
+font-family: 
 
 Longhands for font: -webkit-small-control
-font-style
-font-weight
-font-size
-font-family
-font-stretch
-font-variant-caps
-font-variant-ligatures
-font-variant-numeric
-font-variant-east-asian
-line-height
+font-style: 
+font-variant-ligatures: 
+font-variant-caps: 
+font-variant-numeric: 
+font-variant-east-asian: 
+font-weight: 
+font-stretch: 
+font-size: 
+line-height: 
+font-family: 
 
 Longhands for font: -webkit-control
-font-style
-font-weight
-font-size
-font-family
-font-stretch
-font-variant-caps
-font-variant-ligatures
-font-variant-numeric
-font-variant-east-asian
-line-height
+font-style: 
+font-variant-ligatures: 
+font-variant-caps: 
+font-variant-numeric: 
+font-variant-east-asian: 
+font-weight: 
+font-stretch: 
+font-size: 
+line-height: 
+font-family: 
 
 Longhands for font: italic small-caps bold 12px/24px
 
diff --git a/third_party/blink/web_tests/fast/css/font-shorthand.html b/third_party/blink/web_tests/fast/css/font-shorthand.html
index 5090dcd..d575f96a 100644
--- a/third_party/blink/web_tests/fast/css/font-shorthand.html
+++ b/third_party/blink/web_tests/fast/css/font-shorthand.html
@@ -7,16 +7,14 @@
 }
 
 var style = target.style;
-function showFontLonghands(fontValue, suppressLonghandValue)
+function showFontLonghands(fontValue)
 {
     output.textContent += 'Longhands for font: ' + fontValue + '\n';
     style.font = '';
     style.font = fontValue;
     for (var i = 0; i < style.length; i++) {
         output.textContent += style[i];
-        if (!suppressLonghandValue) {
-            output.textContent += ': ' + style.getPropertyValue(style[i]);
-        }
+        output.textContent += ': ' + style.getPropertyValue(style[i]);
         output.textContent += '\n';
     }
     output.textContent += '\n';
@@ -32,17 +30,17 @@
 showFontLonghands('small-caps bold 14px/28px Arial, sans-serif');
 showFontLonghands('italic small-caps bold 14px/28px Arial, sans-serif');
 
-// Suppress showing the longhand values for system fonts because they are platform specific.
-// Platform specific system font styles are covered in fast/css/css2-system-fonts.html.
-showFontLonghands('caption', true);
-showFontLonghands('icon', true);
-showFontLonghands('menu', true);
-showFontLonghands('message-box', true);
-showFontLonghands('small-caption', true);
-showFontLonghands('status-bar', true);
-showFontLonghands('-webkit-mini-control', true);
-showFontLonghands('-webkit-small-control', true);
-showFontLonghands('-webkit-control', true);
+// System fonts aren't resolved at parse time, so the longhands serialize as empty strings.
+// Platform specific system font computed styles are covered in fast/css/css2-system-fonts.html.
+showFontLonghands('caption');
+showFontLonghands('icon');
+showFontLonghands('menu');
+showFontLonghands('message-box');
+showFontLonghands('small-caption');
+showFontLonghands('status-bar');
+showFontLonghands('-webkit-mini-control');
+showFontLonghands('-webkit-small-control');
+showFontLonghands('-webkit-control');
 
 // Invalid values should yield no longhands.
 showFontLonghands('italic small-caps bold 12px/24px');
diff --git a/third_party/blink/web_tests/flag-specific/enable-use-zoom-for-dsf/platform/mac/fast/hidpi/scrollbar-appearance-increase-device-scale-factor-expected.png b/third_party/blink/web_tests/flag-specific/enable-use-zoom-for-dsf/platform/mac/fast/hidpi/scrollbar-appearance-increase-device-scale-factor-expected.png
new file mode 100644
index 0000000..aade766
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/enable-use-zoom-for-dsf/platform/mac/fast/hidpi/scrollbar-appearance-increase-device-scale-factor-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-use-zoom-for-dsf/platform/mac/virtual/scalefactor200/css3/filters/backdrop-filter-plus-mask-large-expected.png b/third_party/blink/web_tests/flag-specific/enable-use-zoom-for-dsf/platform/mac/virtual/scalefactor200/css3/filters/backdrop-filter-plus-mask-large-expected.png
new file mode 100644
index 0000000..40397c4
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/enable-use-zoom-for-dsf/platform/mac/virtual/scalefactor200/css3/filters/backdrop-filter-plus-mask-large-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/generate-test-wbns.sh b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/generate-test-wbns.sh
new file mode 100755
index 0000000..9622fdd
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/generate-test-wbns.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+set -e
+
+if ! command -v gen-bundle > /dev/null 2>&1; then
+
+    echo "gen-bundle is not installed. Please run:"
+    echo "  go get -u github.com/WICG/webpackage/go/bundle/cmd/..."
+    echo '  export PATH=$PATH:$(go env GOPATH)/bin'
+    exit 1
+fi
+
+gen-bundle \
+  -version b1 \
+  -har webbundle.har \
+  -primaryURL urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720 \
+  -o webbundle.wbn
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/page-with-webbundle.html b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/page-with-webbundle.html
new file mode 100644
index 0000000..83a247b5
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/page-with-webbundle.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>WebBundle subresource loading for static elements with a base element</title>
+<link
+  rel="help"
+  href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
+/>
+<body>
+  <link rel="webbundle"
+        href="webbundle.php"
+        resources="urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720
+                   urn:uuid:429fcc4e-0696-4bad-b099-ee9175f023ae" />
+
+  <script src="urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720"></script>
+
+</body>
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/webbundle.har b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/webbundle.har
new file mode 100644
index 0000000..1708a891
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/webbundle.har
@@ -0,0 +1,44 @@
+{
+  "log": {
+    "entries": [
+      {
+        "request": {
+          "method": "GET",
+          "url": "urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720",
+          "headers": []
+        },
+        "response": {
+          "status": 200,
+          "headers": [
+            {
+              "name": "Content-type",
+              "value": "application/javascript"
+            }
+          ],
+          "content": {
+            "text": "window.report_result('OK');"
+          }
+        }
+      },
+      {
+        "request": {
+          "method": "GET",
+          "url": "urn:uuid:429fcc4e-0696-4bad-b099-ee9175f023ae",
+          "headers": []
+        },
+        "response": {
+          "status": 200,
+          "headers": [
+            {
+              "name": "Content-type",
+              "value": "text/html"
+            }
+          ],
+          "content": {
+            "text": "<script>\nwindow.addEventListener('message', (e) =>{e.source.postMessage(eval(e.data), e.origin);});\n</script>"
+          }
+        }
+      }
+    ]
+  }
+}
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/webbundle.php b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/webbundle.php
new file mode 100644
index 0000000..d839e07b
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/webbundle.php
@@ -0,0 +1,6 @@
+<?php
+header('Content-Type: application/webbundle');
+header('X-Content-Type-Options: nosniff');
+echo file_get_contents('webbundle.wbn');
+?>
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/webbundle.wbn b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/webbundle.wbn
new file mode 100644
index 0000000..3255787
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/webbundle.wbn
Binary files differ
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/webbundle-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/network/webbundle-expected.txt
new file mode 100644
index 0000000..fa964d1
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/webbundle-expected.txt
@@ -0,0 +1,107 @@
+Verifies that webbundle events are triggered
+requestWillBeSent[
+    [0] : {
+        documentURL : http://127.0.0.1:8000/inspector-protocol/network/resources/page-with-webbundle.html
+        frameId : <string>
+        hasUserGesture : false
+        initiator : {
+            type : other
+        }
+        loaderId : <string>
+        request : {
+            headers : {
+                Upgrade-Insecure-Requests : 1
+                User-Agent : <string>
+                sec-ch-ua : "content_shell";v="999"
+                sec-ch-ua-mobile : ?0
+            }
+            initialPriority : VeryHigh
+            method : GET
+            mixedContentType : none
+            referrerPolicy : strict-origin-when-cross-origin
+            url : http://127.0.0.1:8000/inspector-protocol/network/resources/page-with-webbundle.html
+        }
+        requestId : <string>
+        timestamp : <number>
+        type : Document
+        wallTime : <number>
+    }
+    [1] : {
+        documentURL : http://127.0.0.1:8000/inspector-protocol/network/resources/page-with-webbundle.html
+        frameId : <string>
+        hasUserGesture : false
+        initiator : {
+            columnNumber : 68
+            lineNumber : 10
+            type : parser
+            url : http://127.0.0.1:8000/inspector-protocol/network/resources/page-with-webbundle.html
+        }
+        loaderId : <string>
+        request : {
+            headers : {
+                Referer : http://127.0.0.1:8000/inspector-protocol/network/resources/page-with-webbundle.html
+                User-Agent : <string>
+                sec-ch-ua : "content_shell";v="999"
+                sec-ch-ua-mobile : ?0
+            }
+            initialPriority : High
+            method : GET
+            mixedContentType : none
+            referrerPolicy : strict-origin-when-cross-origin
+            url : http://127.0.0.1:8000/inspector-protocol/network/resources/webbundle.php
+        }
+        requestId : <string>
+        timestamp : <number>
+        type : Other
+        wallTime : <number>
+    }
+    [2] : {
+        documentURL : http://127.0.0.1:8000/inspector-protocol/network/resources/page-with-webbundle.html
+        frameId : <string>
+        hasUserGesture : false
+        initiator : {
+            columnNumber : 71
+            lineNumber : 12
+            type : parser
+            url : http://127.0.0.1:8000/inspector-protocol/network/resources/page-with-webbundle.html
+        }
+        loaderId : <string>
+        request : {
+            headers : {
+                Referer : http://127.0.0.1:8000/
+                User-Agent : <string>
+            }
+            initialPriority : High
+            method : GET
+            mixedContentType : none
+            referrerPolicy : strict-origin-when-cross-origin
+            url : urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720
+        }
+        requestId : <string>
+        timestamp : <number>
+        type : Script
+        wallTime : <number>
+    }
+]
+webBundleMetadataReceived[
+    [0] : {
+        requestId : <string>
+        urls : [
+            [0] : urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720
+            [1] : urn:uuid:429fcc4e-0696-4bad-b099-ee9175f023ae
+        ]
+    }
+]
+webBundleInnerResponse[
+    [0] : {
+        bundleRequestId : <string>
+        innerRequestId : <string>
+        innerRequestURL : urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720
+    }
+]
+webBundleMetadataReceived[0].urls: urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720,urn:uuid:429fcc4e-0696-4bad-b099-ee9175f023ae
+webBundleInnerResponse[0].innerRequestURL: urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720
+bundle request ID from webBundleMetadataReceived matches ID from requestWillBeSent
+inner request ID from webBundleInnerResponse matches ID from requestWillBeSent
+inner request ID from webBundleInnerResponse matches ID from webBundleMetadataReceived
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/webbundle.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network/webbundle.js
new file mode 100644
index 0000000..2f428a9
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/webbundle.js
@@ -0,0 +1,58 @@
+(async function(testRunner) {
+  const {page, session, dp} = await testRunner.startBlank(
+      `Verifies that webbundle events are triggered`);
+
+  await dp.Network.enable();
+
+  let requestWillBeSent = [];
+  let webBundleMetadataReceived = [];
+  let webBundleInnerResponse = [];
+
+  const recordEvent = (dest, event) => dest.push(event.params);
+
+  dp.Network.onRequestWillBeSent(recordEvent.bind(null, requestWillBeSent));
+  dp.Network.onSubresourceWebBundleMetadataReceived(
+      recordEvent.bind(null, webBundleMetadataReceived));
+  dp.Network.onSubresourceWebBundleInnerResponseParsed(
+      recordEvent.bind(null, webBundleInnerResponse));
+
+  const reportError = event => testRunner.log(event, 'Error: ');
+
+  dp.Network.onSubresourceWebBundleMetadataError(reportError);
+  dp.Network.onSubresourceWebBundleInnerResponseError(reportError);
+  session.navigate(testRunner.url('./resources/page-with-webbundle.html'));
+  await dp.Network.onceSubresourceWebBundleInnerResponseParsed();
+
+  testRunner.log(requestWillBeSent, 'requestWillBeSent', [
+    'timestamp', 'wallTime', 'loaderId', 'frameId', 'requestId', 'User-Agent'
+  ]);
+  testRunner.log(webBundleMetadataReceived, 'webBundleMetadataReceived');
+  testRunner.log(
+      webBundleInnerResponse, 'webBundleInnerResponse',
+      ['bundleRequestId', 'innerRequestId']);
+
+  testRunner.log(`webBundleMetadataReceived[0].urls: ${
+      webBundleMetadataReceived[0].urls}`);
+  testRunner.log(`webBundleInnerResponse[0].innerRequestURL: ${
+      webBundleInnerResponse[0].innerRequestURL}`);
+  if (requestWillBeSent[1].requestId ===
+      webBundleMetadataReceived[0].requestId) {
+    testRunner.log(
+        'bundle request ID from webBundleMetadataReceived ' +
+        'matches ID from requestWillBeSent');
+  }
+  if (requestWillBeSent[2].requestId ===
+      webBundleInnerResponse[0].innerRequestId) {
+    testRunner.log(
+        'inner request ID from webBundleInnerResponse ' +
+        'matches ID from requestWillBeSent');
+  }
+  if (webBundleInnerResponse[0].bundleRequestId ===
+      webBundleMetadataReceived[0].requestId) {
+    testRunner.log(
+        'inner request ID from webBundleInnerResponse ' +
+        'matches ID from webBundleMetadataReceived');
+  }
+
+  testRunner.completeTest();
+})
diff --git a/third_party/mig/3pp/3pp.pb b/third_party/mig/3pp/3pp.pb
index cfae07c..0301c0a 100644
--- a/third_party/mig/3pp/3pp.pb
+++ b/third_party/mig/3pp/3pp.pb
@@ -2,8 +2,8 @@
   platform_re: "linux-.*|mac-.*"
   source {
     url {
-      download_url: "https://github.com/markmentovai/bootstrap_cmds/archive/1146f2bf0e78b3a4855fb556cc08d83568d28a4a.tar.gz"
-      version: "121"
+      download_url: "https://github.com/markmentovai/bootstrap_cmds/archive/ca2b82d5dee993aa8ed52a04cfa33a9d167618f9.tar.gz"
+      version: "121.100.1"
     }
     unpack_archive: true
   }
diff --git a/third_party/sqlite/README.md b/third_party/sqlite/README.md
index 4e89dbb..f3ee16d5 100644
--- a/third_party/sqlite/README.md
+++ b/third_party/sqlite/README.md
@@ -122,6 +122,15 @@
     ../scripts/sqlite_cherry_picker.py --continue
     ```
 
+    If the cherry-picking script is unable to cherry-pick a commit, like in
+    https://crbug.com/1162100, manually apply the change from a sqlite or git,
+    in //third_party/sqlite/src's files modified in the sqlite tracker, like at
+    https://sqlite.org/src/info/a0bf931bd712037e. From there, run
+    `../scripts/generate_amalgamation.py` to propagate these changes over to
+    the amalgamation files. The sqlite_cherry_picker should generally be
+    preferred though, as it updates hashes and makes tracking easier.
+
+
 3. Run local tests.
 
     Follow steps in [Running Tests](#running-tests) below to execute all
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 01ac953..c816412 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -803,6 +803,7 @@
       'android-pie-arm64-wpt-rel-non-cq': 'android_release_trybot_arm64_webview_google',
       'android-pie-x86-rel': 'android_release_trybot_x86_fastbuild_webview_google',
       'android-web-platform-pie-x86-fyi-rel': 'android_release_trybot_x86_fastbuild_webview_google',
+      'android-weblayer-10-x86-rel-tests': 'android_release_trybot_minimal_symbols_x86_fastbuild_resource_allowlisting_disable_proguard_chrome_google',
       'android-weblayer-marshmallow-x86-rel-tests': 'android_release_trybot_minimal_symbols_x86_fastbuild_resource_allowlisting_disable_proguard_chrome_google',
       'android-weblayer-pie-x86-rel-tests': 'android_release_trybot_minimal_symbols_x86_fastbuild_webview_google',
       'android-weblayer-pie-x86-fyi-rel': 'android_release_trybot_x86_fastbuild_webview_google',
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.android.json b/tools/mb/mb_config_expectations/tryserver.chromium.android.json
index d41d590..75255b1 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.android.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.android.json
@@ -443,6 +443,24 @@
       "use_goma": true
     }
   },
+  "android-weblayer-10-x86-rel-tests": {
+    "gn_args": {
+      "chrome_public_manifest_package": "com.android.chrome",
+      "dcheck_always_on": true,
+      "disable_android_lint": true,
+      "enable_proguard_obfuscation": false,
+      "enable_resource_allowlist_generation": true,
+      "ffmpeg_branding": "Chrome",
+      "is_component_build": false,
+      "is_debug": false,
+      "proprietary_codecs": true,
+      "symbol_level": 1,
+      "target_cpu": "x86",
+      "target_os": "android",
+      "use_errorprone_java_compiler": false,
+      "use_goma": true
+    }
+  },
   "android-weblayer-marshmallow-x86-rel-tests": {
     "gn_args": {
       "chrome_public_manifest_package": "com.android.chrome",
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 47082ea..4481002 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -7096,7 +7096,7 @@
 <!-- Generated from content/browser/bad_message.h.
 Called by update_bad_message_reasons.py.-->
 
-  <int value="0" label="NC_IN_PAGE_NAVIGATION"/>
+  <int value="0" label="OBSOLETE_NC_IN_PAGE_NAVIGATION"/>
   <int value="1" label="RFH_CAN_COMMIT_URL_BLOCKED"/>
   <int value="2" label="RFH_CAN_ACCESS_FILES_OF_PAGE_STATE"/>
   <int value="3" label="RFH_SANDBOX_FLAGS"/>
@@ -24668,6 +24668,7 @@
   <int value="858" label="TripleDESEnabled"/>
   <int value="859" label="CloudUserPolicyMerge"/>
   <int value="860" label="ManagedAccountRestriction"/>
+  <int value="861" label="LockIconInAddressBarEnabled"/>
 </enum>
 
 <enum name="EnterprisePolicyDeviceIdValidity">
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 7f5b954..70a0c07 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,8 +5,8 @@
             "remote_path": "perfetto_binaries/trace_processor_shell/win/84f640ce02217b5292f3facc4c52d02cefaa7a38/trace_processor_shell.exe"
         },
         "mac": {
-            "hash": "61b7406640bbc3b851c08d8f32e3b8c583132bea",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/57f9d8fdd65b9b3e6a4780fb11b8ff983bb9d2e0/trace_processor_shell"
+            "hash": "c4f2e82abb462d6f28bc706559267e20c455b615",
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/84f640ce02217b5292f3facc4c52d02cefaa7a38/trace_processor_shell"
         },
         "linux": {
             "hash": "39d00dec1e8ca19e36fd963cf765e2d771da6cac",
diff --git a/ui/accessibility/ax_table_info_unittest.cc b/ui/accessibility/ax_table_info_unittest.cc
index fb83b21..9fcfaae 100644
--- a/ui/accessibility/ax_table_info_unittest.cc
+++ b/ui/accessibility/ax_table_info_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "ui/accessibility/ax_table_info.h"
 
-#include "base/stl_util.h"
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/accessibility/ax_enums.mojom.h"
diff --git a/ui/accessibility/platform/uia_registrar_win.cc b/ui/accessibility/platform/uia_registrar_win.cc
index 8a249af..36463e5 100644
--- a/ui/accessibility/platform/uia_registrar_win.cc
+++ b/ui/accessibility/platform/uia_registrar_win.cc
@@ -3,8 +3,9 @@
 // found in the LICENSE file.
 
 #include "ui/accessibility/platform/uia_registrar_win.h"
+
 #include <wrl/implements.h>
-#include "base/stl_util.h"
+
 #include "ui/accessibility/accessibility_features.h"
 
 namespace ui {
diff --git a/ui/accessibility/test_ax_node_helper.cc b/ui/accessibility/test_ax_node_helper.cc
index 4ab41b28..d674d20 100644
--- a/ui/accessibility/test_ax_node_helper.cc
+++ b/ui/accessibility/test_ax_node_helper.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/numerics/ranges.h"
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/accessibility/ax_action_data.h"
 #include "ui/accessibility/ax_role_properties.h"
diff --git a/ui/android/display_android_manager.cc b/ui/android/display_android_manager.cc
index 5c7bdf9..79806b6 100644
--- a/ui/android/display_android_manager.cc
+++ b/ui/android/display_android_manager.cc
@@ -9,7 +9,6 @@
 #include <map>
 
 #include "base/android/jni_android.h"
-#include "base/stl_util.h"
 #include "base/trace_event/trace_event.h"
 #include "components/viz/common/features.h"
 #include "components/viz/common/viz_utils.h"
diff --git a/ui/android/java/src/org/chromium/ui/base/ApplicationViewportInsetSupplier.java b/ui/android/java/src/org/chromium/ui/base/ApplicationViewportInsetSupplier.java
index 5cd35c3..0f7769e 100644
--- a/ui/android/java/src/org/chromium/ui/base/ApplicationViewportInsetSupplier.java
+++ b/ui/android/java/src/org/chromium/ui/base/ApplicationViewportInsetSupplier.java
@@ -7,6 +7,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.Callback;
+import org.chromium.base.lifetime.Destroyable;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 
@@ -27,7 +28,8 @@
  *  - Features only interested in what the current inset is should pass around an
  *    {@link ObservableSupplier<Integer>} object.
  */
-public class ApplicationViewportInsetSupplier extends ObservableSupplierImpl<Integer> {
+public class ApplicationViewportInsetSupplier
+        extends ObservableSupplierImpl<Integer> implements Destroyable {
     /** The list of inset providers that this class manages. */
     private final Set<ObservableSupplier<Integer>> mInsetSuppliers = new HashSet<>();
 
@@ -48,6 +50,7 @@
     }
 
     /** Clean up observers and suppliers. */
+    @Override
     public void destroy() {
         for (ObservableSupplier<Integer> os : mInsetSuppliers) {
             os.removeObserver(mInsetSupplierObserver);
diff --git a/ui/android/window_android.cc b/ui/android/window_android.cc
index ae0f86f..1d670a0 100644
--- a/ui/android/window_android.cc
+++ b/ui/android/window_android.cc
@@ -13,7 +13,6 @@
 #include "base/android/jni_weak_ref.h"
 #include "base/android/scoped_java_ref.h"
 #include "base/observer_list.h"
-#include "base/stl_util.h"
 #include "ui/android/display_android_manager.h"
 #include "ui/android/ui_android_jni_headers/WindowAndroid_jni.h"
 #include "ui/android/window_android_compositor.h"
diff --git a/ui/base/clipboard/clipboard_mac.mm b/ui/base/clipboard/clipboard_mac.mm
index 76b08ef..360a92ae 100644
--- a/ui/base/clipboard/clipboard_mac.mm
+++ b/ui/base/clipboard/clipboard_mac.mm
@@ -18,7 +18,6 @@
 #include "base/mac/scoped_nsobject.h"
 #include "base/no_destructor.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
diff --git a/ui/base/clipboard/clipboard_win.cc b/ui/base/clipboard/clipboard_win.cc
index 868de231..67d0680f 100644
--- a/ui/base/clipboard/clipboard_win.cc
+++ b/ui/base/clipboard/clipboard_win.cc
@@ -19,7 +19,6 @@
 #include "base/macros.h"
 #include "base/notreached.h"
 #include "base/numerics/safe_conversions.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
diff --git a/ui/base/ime/chromeos/component_extension_ime_manager.cc b/ui/base/ime/chromeos/component_extension_ime_manager.cc
index 0639fc9d..78950bd 100644
--- a/ui/base/ime/chromeos/component_extension_ime_manager.cc
+++ b/ui/base/ime/chromeos/component_extension_ime_manager.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/command_line.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "ui/base/ime/chromeos/extension_ime_util.h"
 
diff --git a/ui/base/ime/chromeos/ime_keyboard.cc b/ui/base/ime/chromeos/ime_keyboard.cc
index 347496f..3dccea5 100644
--- a/ui/base/ime/chromeos/ime_keyboard.cc
+++ b/ui/base/ime/chromeos/ime_keyboard.cc
@@ -4,7 +4,6 @@
 
 #include <stddef.h>
 
-#include "base/stl_util.h"
 #include "ui/base/ime/chromeos/ime_keyboard.h"
 
 namespace chromeos {
diff --git a/ui/base/ime/chromeos/ime_keymap.cc b/ui/base/ime/chromeos/ime_keymap.cc
index 3490652..b069736 100644
--- a/ui/base/ime/chromeos/ime_keymap.cc
+++ b/ui/base/ime/chromeos/ime_keymap.cc
@@ -9,7 +9,6 @@
 #include <map>
 
 #include "base/lazy_instance.h"
-#include "base/stl_util.h"
 
 namespace ui {
 
diff --git a/ui/base/x/x11_keyboard_hook.cc b/ui/base/x/x11_keyboard_hook.cc
index 5877761..7ad97dc 100644
--- a/ui/base/x/x11_keyboard_hook.cc
+++ b/ui/base/x/x11_keyboard_hook.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/check_op.h"
-#include "base/stl_util.h"
 #include "ui/events/event.h"
 #include "ui/events/keycodes/dom/dom_code.h"
 #include "ui/events/keycodes/dom/keycode_converter.h"
diff --git a/ui/base/x/x11_whole_screen_move_loop.cc b/ui/base/x/x11_whole_screen_move_loop.cc
index db67879..2a3e4369 100644
--- a/ui/base/x/x11_whole_screen_move_loop.cc
+++ b/ui/base/x/x11_whole_screen_move_loop.cc
@@ -13,7 +13,6 @@
 #include "base/logging.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
 #include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "ui/base/x/x11_pointer_grab.h"
diff --git a/ui/display/manager/configure_displays_task_unittest.cc b/ui/display/manager/configure_displays_task_unittest.cc
index ff33395..104bc044 100644
--- a/ui/display/manager/configure_displays_task_unittest.cc
+++ b/ui/display/manager/configure_displays_task_unittest.cc
@@ -7,7 +7,6 @@
 
 #include "base/bind.h"
 #include "base/run_loop.h"
-#include "base/stl_util.h"
 #include "base/test/task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/display/fake/fake_display_snapshot.h"
diff --git a/ui/display/manager/managed_display_info.cc b/ui/display/manager/managed_display_info.cc
index f9c5b726..4f53260 100644
--- a/ui/display/manager/managed_display_info.cc
+++ b/ui/display/manager/managed_display_info.cc
@@ -11,7 +11,6 @@
 
 #include "base/format_macros.h"
 #include "base/logging.h"
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
diff --git a/ui/display/util/edid_parser.h b/ui/display/util/edid_parser.h
index c74ff43..8478d12 100644
--- a/ui/display/util/edid_parser.h
+++ b/ui/display/util/edid_parser.h
@@ -13,7 +13,6 @@
 #include "base/compiler_specific.h"
 #include "base/containers/flat_set.h"
 #include "base/macros.h"
-#include "base/stl_util.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkColorSpace.h"
 #include "ui/display/util/display_util_export.h"
diff --git a/ui/display/win/screen_win.cc b/ui/display/win/screen_win.cc
index e173772..d9599e0 100644
--- a/ui/display/win/screen_win.cc
+++ b/ui/display/win/screen_win.cc
@@ -328,6 +328,9 @@
     const std::vector<DisplayInfo>& display_infos,
     ColorProfileReader* color_profile_reader,
     bool hdr_enabled) {
+  if (display_infos.empty()) {
+    return {};
+  }
   // Find and extract the primary display.
   std::vector<DisplayInfo> display_infos_remaining = display_infos;
   auto primary_display_iter = std::find_if(
diff --git a/ui/display/win/screen_win_unittest.cc b/ui/display/win/screen_win_unittest.cc
index 748159c..049dc24e 100644
--- a/ui/display/win/screen_win_unittest.cc
+++ b/ui/display/win/screen_win_unittest.cc
@@ -3716,5 +3716,42 @@
   EXPECT_NE(Display::InternalDisplayId(), displays[1].id());
 }
 
+namespace {
+
+// Zero displays.
+class ScreenWinTestNoDisplay : public ScreenWinTest {
+ public:
+  ScreenWinTestNoDisplay() = default;
+
+  void SetUpScreen(TestScreenWinInitializer* initializer) override {}
+};
+
+}  // namespace
+
+TEST_F(ScreenWinTestNoDisplay, DIPToScreenPoints) {
+  gfx::Point origin(0, 0);
+  gfx::Point middle(365, 694);
+  gfx::Point lower_right(1919, 1199);
+  EXPECT_EQ(origin, ScreenWin::DIPToScreenPoint(origin));
+  EXPECT_EQ(middle, ScreenWin::DIPToScreenPoint(middle));
+  EXPECT_EQ(lower_right, ScreenWin::DIPToScreenPoint(lower_right));
+}
+
+TEST_F(ScreenWinTestNoDisplay, DIPToScreenRectNullHWND) {
+  gfx::Rect origin(0, 0, 50, 100);
+  gfx::Rect middle(253, 495, 41, 52);
+  EXPECT_EQ(origin, ScreenWin::DIPToScreenRect(nullptr, origin));
+  EXPECT_EQ(middle, ScreenWin::DIPToScreenRect(nullptr, middle));
+}
+
+TEST_F(ScreenWinTestNoDisplay, GetDisplays) {
+  std::vector<Display> displays = GetScreen()->GetAllDisplays();
+  ASSERT_EQ(0u, displays.size());
+}
+
+TEST_F(ScreenWinTestNoDisplay, GetNumDisplays) {
+  EXPECT_EQ(0, GetScreen()->GetNumDisplays());
+}
+
 }  // namespace win
 }  // namespace display
diff --git a/ui/gfx/bidi_line_iterator_unittest.cc b/ui/gfx/bidi_line_iterator_unittest.cc
index 73032f2..94100d1 100644
--- a/ui/gfx/bidi_line_iterator_unittest.cc
+++ b/ui/gfx/bidi_line_iterator_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "ui/gfx/bidi_line_iterator.h"
 
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/ui/gfx/mojom/color_space_mojom_traits.cc b/ui/gfx/mojom/color_space_mojom_traits.cc
index f8205b1..6aa83b18 100644
--- a/ui/gfx/mojom/color_space_mojom_traits.cc
+++ b/ui/gfx/mojom/color_space_mojom_traits.cc
@@ -4,7 +4,6 @@
 
 #include "ui/gfx/mojom/color_space_mojom_traits.h"
 
-#include "base/stl_util.h"
 
 namespace mojo {
 
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index fbefbf00..898db4f 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -16,7 +16,6 @@
 #include "base/notreached.h"
 #include "base/numerics/ranges.h"
 #include "base/numerics/safe_conversions.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/trace_event/trace_event.h"
diff --git a/ui/gfx/text_utils_unittest.cc b/ui/gfx/text_utils_unittest.cc
index 7d7a4d74..f1824dc 100644
--- a/ui/gfx/text_utils_unittest.cc
+++ b/ui/gfx/text_utils_unittest.cc
@@ -9,7 +9,6 @@
 #include <vector>
 
 #include "base/logging.h"
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ui/gl/gl_surface.cc b/ui/gl/gl_surface.cc
index 80c8725f..9581d9c 100644
--- a/ui/gl/gl_surface.cc
+++ b/ui/gl/gl_surface.cc
@@ -10,7 +10,6 @@
 #include "base/command_line.h"
 #include "base/lazy_instance.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "base/threading/thread_local.h"
 #include "base/trace_event/trace_event.h"
 #include "ui/gfx/gpu_fence.h"
diff --git a/ui/gl/gl_version_info.cc b/ui/gl/gl_version_info.cc
index 2a1fa2f..f0c85d9 100644
--- a/ui/gl/gl_version_info.cc
+++ b/ui/gl/gl_version_info.cc
@@ -6,7 +6,6 @@
 
 #include "base/check_op.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
diff --git a/ui/gl/vsync_thread_win.cc b/ui/gl/vsync_thread_win.cc
index ec027e33..c24b708 100644
--- a/ui/gl/vsync_thread_win.cc
+++ b/ui/gl/vsync_thread_win.cc
@@ -7,7 +7,6 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
-#include "base/stl_util.h"
 #include "ui/gl/gl_angle_util_win.h"
 #include "ui/gl/vsync_observer.h"
 
diff --git a/ui/gtk/gtk_key_bindings_handler.cc b/ui/gtk/gtk_key_bindings_handler.cc
index 70edaed..f8eb76d5 100644
--- a/ui/gtk/gtk_key_bindings_handler.cc
+++ b/ui/gtk/gtk_key_bindings_handler.cc
@@ -8,7 +8,6 @@
 #include <string>
 
 #include "base/logging.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "ui/base/glib/glib_cast.h"
 #include "ui/base/ime/text_edit_commands.h"
diff --git a/ui/native_theme/native_theme.h b/ui/native_theme/native_theme.h
index 519e969..2ba7ea7 100644
--- a/ui/native_theme/native_theme.h
+++ b/ui/native_theme/native_theme.h
@@ -271,6 +271,7 @@
     bool is_overlay;
     ScrollbarOverlayColorTheme scrollbar_theme;
     ScrollbarOrientation orientation;  // Used on Mac for drawing gradients.
+    float scale_from_dip;
   };
 #endif
 
diff --git a/ui/native_theme/native_theme_mac.h b/ui/native_theme/native_theme_mac.h
index 68fafcb..61736e0 100644
--- a/ui/native_theme/native_theme_mac.h
+++ b/ui/native_theme/native_theme_mac.h
@@ -140,12 +140,15 @@
       ColorScheme color_scheme,
       const ScrollbarExtraParams& extra_params) const;
 
-  int ScrollbarTrackBorderWidth() const { return 1; }
+  int ScrollbarTrackBorderWidth(float scale_from_dip) const {
+    constexpr float border_width = 1.0f;
+    return scale_from_dip * border_width;
+  }
 
   // The amount the thumb is inset from the ends and the inside edge of track
   // border.
-  int GetScrollbarThumbInset(bool is_overlay) const {
-    return is_overlay ? 2 : 3;
+  int GetScrollbarThumbInset(bool is_overlay, float scale_from_dip) const {
+    return scale_from_dip * (is_overlay ? 2.0f : 3.0f);
   }
 
   // Returns the minimum size for the thumb. We will not inset the thumb if it
diff --git a/ui/native_theme/native_theme_mac.mm b/ui/native_theme/native_theme_mac.mm
index 6b79fe1..c96746c 100644
--- a/ui/native_theme/native_theme_mac.mm
+++ b/ui/native_theme/native_theme_mac.mm
@@ -383,13 +383,16 @@
   // Compute the rect for the border.
   gfx::Rect inner_border(rect);
   if (extra_params.orientation == ScrollbarOrientation::kVerticalOnLeft)
-    inner_border.set_x(rect.right() - ScrollbarTrackBorderWidth());
+    inner_border.set_x(rect.right() -
+                       ScrollbarTrackBorderWidth(extra_params.scale_from_dip));
   if (is_corner ||
       extra_params.orientation == ScrollbarOrientation::kHorizontal)
-    inner_border.set_height(ScrollbarTrackBorderWidth());
+    inner_border.set_height(
+        ScrollbarTrackBorderWidth(extra_params.scale_from_dip));
   if (is_corner ||
       extra_params.orientation != ScrollbarOrientation::kHorizontal)
-    inner_border.set_width(ScrollbarTrackBorderWidth());
+    inner_border.set_width(
+        ScrollbarTrackBorderWidth(extra_params.scale_from_dip));
 
   // And draw.
   cc::PaintFlags flags;
@@ -419,8 +422,10 @@
   if (is_corner ||
       extra_params.orientation == ScrollbarOrientation::kHorizontal) {
     gfx::Rect outer_border(rect);
-    outer_border.set_height(ScrollbarTrackBorderWidth());
-    outer_border.set_y(rect.bottom() - ScrollbarTrackBorderWidth());
+    outer_border.set_height(
+        ScrollbarTrackBorderWidth(extra_params.scale_from_dip));
+    outer_border.set_y(rect.bottom() -
+                       ScrollbarTrackBorderWidth(extra_params.scale_from_dip));
     paint_canvas.DrawRect(outer_border, flags);
   }
 
@@ -428,9 +433,11 @@
   if (is_corner ||
       extra_params.orientation != ScrollbarOrientation::kHorizontal) {
     gfx::Rect outer_border(rect);
-    outer_border.set_width(ScrollbarTrackBorderWidth());
+    outer_border.set_width(
+        ScrollbarTrackBorderWidth(extra_params.scale_from_dip));
     if (extra_params.orientation == ScrollbarOrientation::kVerticalOnRight)
-      outer_border.set_x(rect.right() - ScrollbarTrackBorderWidth());
+      outer_border.set_x(rect.right() - ScrollbarTrackBorderWidth(
+                                            extra_params.scale_from_dip));
     paint_canvas.DrawRect(outer_border, flags);
   }
 }
@@ -456,14 +463,19 @@
   gfx::Rect bounds(rect);
   {
     // Shrink the thumb evenly in length and girth to fit within the track.
-    gfx::Insets thumb_insets(GetScrollbarThumbInset(scroll_thumb.is_overlay));
+    gfx::Insets thumb_insets(GetScrollbarThumbInset(
+        scroll_thumb.is_overlay, scroll_thumb.scale_from_dip));
 
     // Also shrink the thumb in girth to not touch the border.
     if (scroll_thumb.orientation == ScrollbarOrientation::kHorizontal) {
-      thumb_insets.set_top(thumb_insets.top() + ScrollbarTrackBorderWidth());
+      thumb_insets.set_top(
+          thumb_insets.top() +
+          ScrollbarTrackBorderWidth(scroll_thumb.scale_from_dip));
       ConstrainedInset(&bounds, GetThumbMinSize(false), thumb_insets);
     } else {
-      thumb_insets.set_left(thumb_insets.left() + ScrollbarTrackBorderWidth());
+      thumb_insets.set_left(
+          thumb_insets.left() +
+          ScrollbarTrackBorderWidth(scroll_thumb.scale_from_dip));
       ConstrainedInset(&bounds, GetThumbMinSize(true), thumb_insets);
     }
   }
diff --git a/ui/native_theme/native_theme_win.cc b/ui/native_theme/native_theme_win.cc
index 5e1dcf9..a02662f 100644
--- a/ui/native_theme/native_theme_win.cc
+++ b/ui/native_theme/native_theme_win.cc
@@ -16,7 +16,6 @@
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/notreached.h"
-#include "base/stl_util.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/win/scoped_gdi_object.h"
 #include "base/win/scoped_hdc.h"
diff --git a/ui/ozone/platform/drm/common/drm_util_unittest.cc b/ui/ozone/platform/drm/common/drm_util_unittest.cc
index 3be4bc9..e441bb7 100644
--- a/ui/ozone/platform/drm/common/drm_util_unittest.cc
+++ b/ui/ozone/platform/drm/common/drm_util_unittest.cc
@@ -9,7 +9,6 @@
 
 #include <map>
 
-#include "base/stl_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkColorSpace.h"
 #include "third_party/skia/include/core/SkMatrix44.h"
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
index ae3a9a2..d8f6da5 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
+++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
@@ -19,12 +19,14 @@
 #include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
 #include "ui/base/dragdrop/os_exchange_data.h"
 #include "ui/base/dragdrop/os_exchange_data_provider_non_backed.h"
+#include "ui/events/event_constants.h"
 #include "ui/ozone/platform/wayland/common/data_util.h"
 #include "ui/ozone/platform/wayland/common/wayland_util.h"
 #include "ui/ozone/platform/wayland/host/wayland_connection.h"
 #include "ui/ozone/platform/wayland/host/wayland_data_device_manager.h"
 #include "ui/ozone/platform/wayland/host/wayland_data_offer.h"
 #include "ui/ozone/platform/wayland/host/wayland_data_source.h"
+#include "ui/ozone/platform/wayland/host/wayland_event_source.h"
 #include "ui/ozone/platform/wayland/host/wayland_shm_buffer.h"
 #include "ui/ozone/platform/wayland/host/wayland_surface.h"
 #include "ui/ozone/platform/wayland/host/wayland_window.h"
@@ -91,7 +93,7 @@
 
 WaylandDataDragController::~WaylandDataDragController() = default;
 
-void WaylandDataDragController::StartSession(const OSExchangeData& data,
+bool WaylandDataDragController::StartSession(const OSExchangeData& data,
                                              int operation) {
   DCHECK_EQ(state_, State::kIdle);
   DCHECK(!origin_window_);
@@ -99,7 +101,20 @@
   origin_window_ = window_manager_->GetCurrentFocusedWindow();
   if (!origin_window_) {
     LOG(ERROR) << "Failed to get focused window.";
-    return;
+    return false;
+  }
+
+  // Drag start may be triggered asynchronously. Due this, it is possible that
+  // by the time "start drag" gets processed by Ozone/Wayland, the origin
+  // pointer event (touch or mouse) has already been released. In this case,
+  // make sure the flow bails earlier, otherwise the drag loop keeps running,
+  // causing hangs as observerd in crbug.com/1209269.
+  //
+  // TODO(crbug.com/1211874): Improve serial tracking so that it can be used for
+  // this validatation, covering both mouse and touch-triggered drags.
+  if (!connection_->event_source()->IsPointerButtonPressed(
+          EF_LEFT_MOUSE_BUTTON)) {
+    return false;
   }
 
   // Create new new data source and offers |data|.
@@ -127,6 +142,7 @@
                           this);
 
   window_manager_->AddObserver(this);
+  return true;
 }
 
 // Sessions initiated from Chromium, will have |data_source_| set. In which
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h
index 81f50f3e..17c9605 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h
+++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h
@@ -73,9 +73,10 @@
       delete;
   ~WaylandDataDragController() override;
 
-  // Starts a data drag and drop session for |data|. Only one DND session can
-  // run at a given time.
-  void StartSession(const ui::OSExchangeData& data, int operation);
+  // Starts a data drag and drop session for |data|. Returns true if it is
+  // successfully started, false otherwise. Only one DND session can run at a
+  // given time.
+  bool StartSession(const ui::OSExchangeData& data, int operation);
 
   State state() const { return state_; }
 
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
index 8d1c7c68..d59919b1 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
+++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <linux/input.h>
 #include <wayland-server.h>
 
 #include <memory>
@@ -217,6 +218,15 @@
         base::Unretained(this)));
   }
 
+  void FocusAndPressLeftPointerButton(WaylandWindow* window,
+                                      MockPlatformWindowDelegate* delegate) {
+    SendPointerEnter(window, delegate);
+    SendPointerButton(window, delegate, BTN_LEFT, /*pressed=*/true);
+    Sync();
+  }
+
+  MockPlatformWindowDelegate* delegate() { return &delegate_; }
+
  protected:
   std::unique_ptr<MockDropHandler> drop_handler_;
   std::unique_ptr<MockDragHandlerDelegate> drag_handler_delegate_;
@@ -224,7 +234,7 @@
 
 TEST_P(WaylandDataDragControllerTest, StartDrag) {
   const bool restored_focus = window_->has_pointer_focus();
-  window_->SetPointerFocus(true);
+  FocusAndPressLeftPointerButton(window_.get(), &delegate_);
 
   auto test = [](WaylandDataDragControllerTest* self) {
     // Now the server can read the data and give it to our callback.
@@ -258,7 +268,7 @@
 
 TEST_P(WaylandDataDragControllerTest, StartDragWithWrongMimeType) {
   bool restored_focus = window_->has_pointer_focus();
-  window_->SetPointerFocus(true);
+  FocusAndPressLeftPointerButton(window_.get(), &delegate_);
 
   // The client starts dragging offering data with |kMimeTypeHTML|
   OSExchangeData os_exchange_data;
@@ -285,7 +295,7 @@
 
 TEST_P(WaylandDataDragControllerTest, StartDragWithText) {
   bool restored_focus = window_->has_pointer_focus();
-  window_->SetPointerFocus(true);
+  FocusAndPressLeftPointerButton(window_.get(), &delegate_);
 
   // The client starts dragging offering text mime type.
   OSExchangeData os_exchange_data;
@@ -313,7 +323,7 @@
 
 TEST_P(WaylandDataDragControllerTest, StartDragWithFileContents) {
   bool restored_focus = window_->has_pointer_focus();
-  window_->SetPointerFocus(true);
+  FocusAndPressLeftPointerButton(window_.get(), &delegate_);
 
   // The client starts dragging offering text mime type.
   OSExchangeData os_exchange_data;
@@ -532,7 +542,7 @@
 // started and cancelled within the same surface.
 TEST_P(WaylandDataDragControllerTest, StartAndCancel) {
   const bool restored_focus = window_->has_pointer_focus();
-  window_->SetPointerFocus(true);
+  FocusAndPressLeftPointerButton(window_.get(), &delegate_);
 
   // Schedule a wl_data_source::cancelled event to be sent asynchronously
   // once the drag session gets started.
@@ -581,7 +591,8 @@
 TEST_P(WaylandDataDragControllerTest, DestroyEnteredSurface) {
   auto* window_1 = window_.get();
   const bool restored_focus = window_1->has_pointer_focus();
-  window_1->SetPointerFocus(true);
+  FocusAndPressLeftPointerButton(window_1, &delegate_);
+
   ASSERT_EQ(PlatformWindowType::kWindow, window_1->type());
 
   auto test = [](WaylandDataDragControllerTest* self) {
@@ -642,8 +653,7 @@
   MockPlatformWindowDelegate delegate_2;
   auto window_2 = CreateTestWindow(PlatformWindowType::kPopup,
                                    gfx::Size(80, 80), &delegate_2);
-  window_2->SetPointerFocus(true);
-  Sync();
+  FocusAndPressLeftPointerButton(window_2.get(), &delegate_);
 
   // Post test task to be performed asynchronously once the drag session gets
   // started.
@@ -670,7 +680,7 @@
 TEST_P(WaylandDataDragControllerTest, DragToNonToplevelWindows) {
   auto* origin_window = window_.get();
   const bool restored_focus = origin_window->has_pointer_focus();
-  origin_window->SetPointerFocus(true);
+  FocusAndPressLeftPointerButton(origin_window, &delegate_);
 
   auto test = [](WaylandDataDragControllerTest* self,
                  PlatformWindowType window_type) {
@@ -724,7 +734,7 @@
 TEST_P(WaylandDataDragControllerTest, PopupRequestCreatesAuxiliaryWindow) {
   auto* origin_window = window_.get();
   const bool restored_focus = origin_window->has_pointer_focus();
-  origin_window->SetPointerFocus(true);
+  FocusAndPressLeftPointerButton(origin_window, &delegate_);
 
   auto test = [](WaylandDataDragControllerTest* self) {
     MockPlatformWindowDelegate delegate;
@@ -756,7 +766,7 @@
 TEST_P(WaylandDataDragControllerTest, MenuRequestCreatesPopupWindow) {
   auto* origin_window = window_.get();
   const bool restored_focus = origin_window->has_pointer_focus();
-  origin_window->SetPointerFocus(true);
+  FocusAndPressLeftPointerButton(origin_window, &delegate_);
 
   auto test = [](WaylandDataDragControllerTest* self) {
     MockPlatformWindowDelegate delegate;
@@ -783,6 +793,39 @@
   origin_window->SetPointerFocus(restored_focus);
 }
 
+// Regression test for https://crbug.com/1209269.
+TEST_P(WaylandDataDragControllerTest, AsyncNoopStartDrag) {
+  const bool restored_focus = window_->has_pointer_focus();
+  OSExchangeData os_exchange_data;
+  os_exchange_data.SetString(sample_text_for_dnd());
+
+  // Override test server's data device drag delegate such that
+  // wl_data_device.start_drag no-ops.
+  struct NoopDragDeviceDelegate : public wl::TestDataDevice::Delegate {
+    void StartDrag(wl::TestDataSource* source,
+                   wl::MockSurface* origin,
+                   uint32_t serial) override {}
+  } noop_drag_delegate;
+  data_device_manager_->data_device()->set_delegate(&noop_drag_delegate);
+
+  FocusAndPressLeftPointerButton(window_.get(), &delegate_);
+
+  // Emulate a "quick" wl_pointer.button release event being processed by the
+  // compositor, which leads to a no-op subsequent wl_data_device.start_drag.
+  // In this case, the client is expected to gracefully reset state and quit
+  // drag loop as if the drag session was cancelled as usual.
+  SendPointerButton(window_.get(), &delegate_, BTN_LEFT, /*pressed=*/false);
+  Sync();
+
+  // Attempt to start drag session and ensure it fails.
+  bool result = window_->StartDrag(
+      os_exchange_data, DragDropTypes::DRAG_COPY, /*cursor=*/{},
+      /*can_grab_pointer=*/true, drag_handler_delegate_.get());
+  EXPECT_FALSE(result);
+
+  window_->SetPointerFocus(restored_focus);
+}
+
 INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
                          WaylandDataDragControllerTest,
                          Values(wl::ServerConfig{
diff --git a/ui/ozone/platform/wayland/host/wayland_window.cc b/ui/ozone/platform/wayland/host/wayland_window.cc
index 091e80f..58bcf94a 100644
--- a/ui/ozone/platform/wayland/host/wayland_window.cc
+++ b/ui/ozone/platform/wayland/host/wayland_window.cc
@@ -184,9 +184,11 @@
                               gfx::NativeCursor cursor,
                               bool can_grab_pointer,
                               WmDragHandler::Delegate* delegate) {
+  if (!connection_->data_drag_controller()->StartSession(data, operation))
+    return false;
+
   DCHECK(!drag_handler_delegate_);
   drag_handler_delegate_ = delegate;
-  connection()->data_drag_controller()->StartSession(data, operation);
 
   base::RunLoop drag_loop(base::RunLoop::Type::kNestableTasksAllowed);
   drag_loop_quit_closure_ = drag_loop.QuitClosure();
diff --git a/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc b/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc
index e4b83ef..e4e59a92 100644
--- a/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc
+++ b/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc
@@ -52,14 +52,6 @@
   void SetUp() override {
     WaylandDragDropTest::SetUp();
 
-    screen_ = std::make_unique<WaylandScreen>(connection_.get());
-
-    wl_seat_send_capabilities(server_.seat()->resource(),
-                              WL_SEAT_CAPABILITY_POINTER);
-    Sync();
-    pointer_ = server_.seat()->pointer();
-    ASSERT_TRUE(pointer_);
-
     EXPECT_FALSE(window_->has_pointer_focus());
     EXPECT_EQ(State::kIdle, drag_controller()->state());
   }
@@ -68,44 +60,32 @@
     return connection_->window_drag_controller();
   }
 
-  WaylandWindowManager* window_manager() const {
-    return connection_->wayland_window_manager();
-  }
-
   MockPlatformWindowDelegate& delegate() { return delegate_; }
 
  protected:
   using State = WaylandWindowDragController::State;
 
   void SendPointerEnter(WaylandWindow* window,
-                        MockPlatformWindowDelegate* delegate) {
-    auto* surface = server_.GetObject<wl::MockSurface>(
-        window->root_surface()->GetSurfaceId());
-    wl_pointer_send_enter(pointer_->resource(), NextSerial(),
-                          surface->resource(), 0, 0);
+                        MockPlatformWindowDelegate* delegate) override {
     EXPECT_CALL(*delegate, DispatchEvent(_)).Times(1);
+    WaylandDragDropTest::SendPointerEnter(window, delegate);
     Sync();
-
     EXPECT_EQ(window, window_manager()->GetCurrentFocusedWindow());
   }
 
   void SendPointerLeave(WaylandWindow* window,
-                        MockPlatformWindowDelegate* delegate) {
-    auto* surface = server_.GetObject<wl::MockSurface>(
-        window->root_surface()->GetSurfaceId());
-    wl_pointer_send_leave(pointer_->resource(), NextSerial(),
-                          surface->resource());
+                        MockPlatformWindowDelegate* delegate) override {
     EXPECT_CALL(*delegate, DispatchEvent(_)).Times(1);
+    WaylandDragDropTest::SendPointerLeave(window, delegate);
     Sync();
-
     EXPECT_EQ(nullptr, window_manager()->GetCurrentFocusedWindow());
   }
 
   void SendPointerPress(WaylandWindow* window,
                         MockPlatformWindowDelegate* delegate,
                         int button) {
-    wl_pointer_send_button(pointer_->resource(), NextSerial(), NextTime(),
-                           button, WL_POINTER_BUTTON_STATE_PRESSED);
+    WaylandDragDropTest::SendPointerButton(window, delegate, button,
+                                           /*pressed=*/true);
     EXPECT_CALL(*delegate, DispatchEvent(_)).Times(1);
     Sync();
 
@@ -139,12 +119,6 @@
   //
   // TODO(crbug.com/1116431): Support extended-drag in test compositor.
   void SendDndDrop() { SendDndCancelled(); }
-
-  // client objects
-  std::unique_ptr<WaylandScreen> screen_;
-
-  // server objects
-  wl::MockPointer* pointer_;
 };
 
 // Check the following flow works as expected:
diff --git a/ui/ozone/platform/wayland/test/wayland_drag_drop_test.cc b/ui/ozone/platform/wayland/test/wayland_drag_drop_test.cc
index 259e8541..cf0b379f 100644
--- a/ui/ozone/platform/wayland/test/wayland_drag_drop_test.cc
+++ b/ui/ozone/platform/wayland/test/wayland_drag_drop_test.cc
@@ -4,6 +4,7 @@
 
 #include "ui/ozone/platform/wayland/test/wayland_drag_drop_test.h"
 
+#include <wayland-server-protocol.h>
 #include <wayland-util.h>
 
 #include <cstdint>
@@ -12,12 +13,15 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/ozone/platform/wayland/host/wayland_window.h"
+#include "ui/ozone/platform/wayland/test/mock_pointer.h"
 #include "ui/ozone/platform/wayland/test/mock_surface.h"
 #include "ui/ozone/platform/wayland/test/test_data_device.h"
 #include "ui/ozone/platform/wayland/test/test_data_device_manager.h"
 #include "ui/ozone/platform/wayland/test/test_data_offer.h"
 #include "ui/ozone/platform/wayland/test/test_data_source.h"
 
+using testing::_;
+
 namespace ui {
 
 WaylandDragDropTest::WaylandDragDropTest() = default;
@@ -52,9 +56,43 @@
   data_source_->ReadData(mime_type, std::move(callback));
 }
 
+void WaylandDragDropTest::SendPointerEnter(
+    WaylandWindow* window,
+    MockPlatformWindowDelegate* delegate) {
+  auto* surface = server_.GetObject<wl::MockSurface>(
+      window->root_surface()->GetSurfaceId());
+  wl_pointer_send_enter(pointer_->resource(), NextSerial(), surface->resource(),
+                        0, 0);
+}
+
+void WaylandDragDropTest::SendPointerLeave(
+    WaylandWindow* window,
+    MockPlatformWindowDelegate* delegate) {
+  auto* surface = server_.GetObject<wl::MockSurface>(
+      window->root_surface()->GetSurfaceId());
+  wl_pointer_send_leave(pointer_->resource(), NextSerial(),
+                        surface->resource());
+}
+
+void WaylandDragDropTest::SendPointerButton(
+    WaylandWindow* window,
+    MockPlatformWindowDelegate* delegate,
+    int button,
+    bool pressed) {
+  uint32_t state = pressed ? WL_POINTER_BUTTON_STATE_PRESSED
+                           : WL_POINTER_BUTTON_STATE_RELEASED;
+  wl_pointer_send_button(pointer_->resource(), NextSerial(), NextTime(), button,
+                         state);
+}
+
 void WaylandDragDropTest::SetUp() {
   WaylandTest::SetUp();
+
+  wl_seat_send_capabilities(server_.seat()->resource(),
+                            WL_SEAT_CAPABILITY_POINTER);
   Sync();
+  pointer_ = server_.seat()->pointer();
+  ASSERT_TRUE(pointer_);
 
   data_device_manager_ = server_.data_device_manager();
   ASSERT_TRUE(data_device_manager_);
diff --git a/ui/ozone/platform/wayland/test/wayland_drag_drop_test.h b/ui/ozone/platform/wayland/test/wayland_drag_drop_test.h
index 3455909..0bf5e67 100644
--- a/ui/ozone/platform/wayland/test/wayland_drag_drop_test.h
+++ b/ui/ozone/platform/wayland/test/wayland_drag_drop_test.h
@@ -42,6 +42,15 @@
   void ReadData(const std::string& mime_type,
                 wl::TestDataSource::ReadDataCallback callback);
 
+  virtual void SendPointerEnter(WaylandWindow* window,
+                                MockPlatformWindowDelegate* delegate);
+  virtual void SendPointerLeave(WaylandWindow* window,
+                                MockPlatformWindowDelegate* delegate);
+  virtual void SendPointerButton(WaylandWindow* window,
+                                 MockPlatformWindowDelegate* delegate,
+                                 int button,
+                                 bool pressed);
+
  protected:
   // WaylandTest:
   void SetUp() override;
@@ -58,9 +67,14 @@
   void ScheduleTestTask(base::OnceClosure test_task);
   void RunTestTask(base::OnceClosure test_task);
 
+  WaylandWindowManager* window_manager() const {
+    return connection_->wayland_window_manager();
+  }
+
   // Server objects
   wl::TestDataDeviceManager* data_device_manager_;
   wl::TestDataSource* data_source_;
+  wl::MockPointer* pointer_;
 };
 
 }  // namespace ui
diff --git a/ui/platform_window/x11/test/events_x_unittest.cc b/ui/platform_window/x11/test/events_x_unittest.cc
index 15b8869..a94d286 100644
--- a/ui/platform_window/x11/test/events_x_unittest.cc
+++ b/ui/platform_window/x11/test/events_x_unittest.cc
@@ -10,7 +10,6 @@
 #include <set>
 #include <utility>
 
-#include "base/stl_util.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "build/build_config.h"
diff --git a/ui/views/animation/square_ink_drop_ripple_unittest.cc b/ui/views/animation/square_ink_drop_ripple_unittest.cc
index a43c517..1ec6a757 100644
--- a/ui/views/animation/square_ink_drop_ripple_unittest.cc
+++ b/ui/views/animation/square_ink_drop_ripple_unittest.cc
@@ -8,7 +8,6 @@
 #include <vector>
 
 #include "base/numerics/safe_conversions.h"
-#include "base/stl_util.h"
 #include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/geometry/point.h"
diff --git a/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc b/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc
index 31647fb6..6e1b3c0 100644
--- a/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc
+++ b/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc
@@ -12,7 +12,6 @@
 
 #include "base/i18n/rtl.h"
 #include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "ui/base/hit_test.h"
diff --git a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
index f39d1db..6a44ed8 100644
--- a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
+++ b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/i18n/rtl.h"
-#include "base/stl_util.h"
 #include "cc/paint/paint_shader.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
@@ -424,6 +423,7 @@
   }
   params.scrollbar_extra.is_overlay =
       GetScrollerStyle() == NSScrollerStyleOverlay;
+  params.scrollbar_extra.scale_from_dip = 1.0f;
   return params;
 }
 
diff --git a/ui/views/examples/radio_button_example.cc b/ui/views/examples/radio_button_example.cc
index fca16b2..1b888ce 100644
--- a/ui/views/examples/radio_button_example.cc
+++ b/ui/views/examples/radio_button_example.cc
@@ -8,7 +8,6 @@
 
 #include <memory>
 
-#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/ui/views/touchui/touch_selection_menu_views.cc b/ui/views/touchui/touch_selection_menu_views.cc
index 7f5e5f81..0c6aa43 100644
--- a/ui/views/touchui/touch_selection_menu_views.cc
+++ b/ui/views/touchui/touch_selection_menu_views.cc
@@ -7,7 +7,6 @@
 #include <memory>
 #include <utility>
 
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/aura/window.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/ui/views/window/dialog_delegate_unittest.cc b/ui/views/window/dialog_delegate_unittest.cc
index 89d71cd0..bdb0bd1 100644
--- a/ui/views/window/dialog_delegate_unittest.cc
+++ b/ui/views/window/dialog_delegate_unittest.cc
@@ -4,7 +4,6 @@
 
 #include <stddef.h>
 
-#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind.h"
 #include "build/build_config.h"
diff --git a/url/url_util.cc b/url/url_util.cc
index c2456e2..00da5707 100644
--- a/url/url_util.cc
+++ b/url/url_util.cc
@@ -11,7 +11,6 @@
 #include "base/check_op.h"
 #include "base/compiler_specific.h"
 #include "base/no_destructor.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "url/url_canon_internal.h"
 #include "url/url_constants.h"
diff --git a/weblayer/browser/autofill_client_impl.cc b/weblayer/browser/autofill_client_impl.cc
index eed753d..431aee38 100644
--- a/weblayer/browser/autofill_client_impl.cc
+++ b/weblayer/browser/autofill_client_impl.cc
@@ -4,7 +4,6 @@
 
 #include "weblayer/browser/autofill_client_impl.h"
 
-#include "base/stl_util.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/ui/suggestion.h"
 #include "components/ukm/content/source_url_recorder.h"
diff --git a/weblayer/browser/browser_impl.cc b/weblayer/browser/browser_impl.cc
index 46fda6a..da2c667 100644
--- a/weblayer/browser/browser_impl.cc
+++ b/weblayer/browser/browser_impl.cc
@@ -9,7 +9,6 @@
 #include "base/containers/unique_ptr_adapters.h"
 #include "base/memory/ptr_util.h"
 #include "base/path_service.h"
-#include "base/stl_util.h"
 #include "components/base32/base32.h"
 #include "content/public/browser/web_contents.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"