diff --git a/DEPS b/DEPS
index b066896..9acef3c 100644
--- a/DEPS
+++ b/DEPS
@@ -312,15 +312,15 @@
   # 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': 'ffbe23b3b3b97564ad18f997f750596936db00a4',
+  'skia_revision': 'a57372ca2e66d24db942f406404b8be92870afb2',
   # 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': '68087ab41a76501a5364273a52cd395f0e7033b3',
+  'v8_revision': '5a0470b96e8446ef6d29fa7847b8ca28ccf504dd',
   # 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': '1ceddbf6977926d674c0c5a78b398f684d0052b1',
+  'angle_revision': '21381f5e1c4dffe6ce43121e8cd55803647896ca',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # 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 PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'f1805084d8ec1a854ffa6e4f3d489aaa5c9818ab',
+  'pdfium_revision': 'ef0eeaa9e423c5aa002180cbc448f784c8e621ae',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -383,11 +383,11 @@
   # 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': '2ee42b4fee621515571f90e0aac3098caad8e712',
+  'catapult_revision': 'f226e76aa5f1014892221b2d426ad63f04b8ed07',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling chromium_variations
   # and whatever else without interference from each other.
-  'chromium_variations_revision': '2f49c50b79ab7a6ee16f324656f0185a44fa50a6',
+  'chromium_variations_revision': '2c5458c1057e9a8d69cfa6c15f42ef6446b1629a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling CrossBench
   # and whatever else without interference from each other.
@@ -827,7 +827,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    'eadffcd4b5ec79ec69e29f75c6695edf9c69aff1',
+    '8a57d2d318a0d62648d9590be11bc6d60f247b7d',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -989,7 +989,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'iX0cDzVg1LYwl-VFNJPfNgZUPK5RCN7PUW7VBxtqx_8C',
+          'version': '-hKL4aNs2f-WxaYX42KZQqg7ytafBADY8TVVzhUQtVAC',
       },
     ],
     'condition': 'checkout_android',
@@ -1060,7 +1060,7 @@
       'packages': [
           {
                'package': 'chromium/third_party/android_build_tools/manifest_merger',
-               'version': 'ebz_Y3LqXzAa7YSsVInCAghbwoZuC4tySvJ1XPJLCzIC',
+               'version': 'bmxKmBbioYv3d9nmRIo_xYGXwobb91K5RM7xU0RUQu4C',
           },
       ],
       'condition': 'checkout_android',
@@ -1205,7 +1205,7 @@
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '196ae62399105a2fe043fcd30a1446e2fe80d7b3',
+      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '9c278bd6f25a7da69b438b262acd0da6d2f78b1a',
     'condition': 'checkout_src_internal',
   },
 
@@ -1665,7 +1665,7 @@
     Var('pdfium_git') + '/pdfium.git' + '@' +  Var('pdfium_revision'),
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '77ac4b7528eeb8444b6f829264a2e82be99a8cd0',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '98921c2a0c99fa8e97f5e6c369cc3e16473c695e',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '8ef97ff3b7332e38e61b347a2fbed425a4617151',
@@ -1705,7 +1705,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/r8',
-              'version': 'XyJJ5GEKJUXldBnoKKraiUIjSbnXGqjNBcLoNuJvKccC',
+              'version': 'dlcpQz73JQc8czs_ASn1itNoISc9wNEMBb5YTvTyQtEC',
           },
       ],
       'condition': 'checkout_android',
@@ -1973,7 +1973,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': '8JzZqNVdXxldkyjip1lFzdsZYeUqHsUxmm7JaEKEku0C',
+        'version': 'yX3aqwi1ZvCy5HEUQqzEtnnnhPoKQZo8g1SkFgDTxEYC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -2017,7 +2017,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': 'DZBWu_gDTcO8mVYLHW38B-bCWgvLZG4RRjsxywx5roEC',
+        'version': 'GB7HSiK_48sadKBTgeQVvHWsliSshLDgAwJsQAKt1_QC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index 11fea44..ae86a87 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -7445,6 +7445,9 @@
 
       <!-- TODO(b/286455407): Update strings once finalized with UX Writing -->
       <!-- Game Dashboard strings -->
+      <message name="IDS_ASH_GAME_DASHBOARD_BACK_TOOLTIP" translateable="false" desc="Tooltip for the Game Dashboard back button.">
+        Back
+      </message>
       <message name="IDS_ASH_GAME_DASHBOARD_CONTROLS_TILE_BUTTON_TITLE" translateable="false" desc="The display name for the Game Dashboard game controls tile.">
         Controls
       </message>
@@ -7475,9 +7478,21 @@
       <message name="IDS_ASH_GAME_DASHBOARD_SEND_FEEDBACK_TITLE" translateable="false" desc="The display name for the Game Dashboard send feedback button.">
         Send feedback
       </message>
+      <message name="IDS_ASH_GAME_DASHBOARD_SETTINGS_TITLE" translateable="false" desc="The display name for the Game Dashboard settings.">
+        Game dashboard options
+      </message>
       <message name="IDS_ASH_GAME_DASHBOARD_SETTINGS_TOOLTIP" translateable="false" desc="Tooltip for the Game Dashboard settings icon button.">
         Game dashboard settings
       </message>
+      <message name="IDS_ASH_GAME_DASHBOARD_SETTINGS_WELCOME_DIALOG_A11Y_LABEL" translateable="false" desc="The accessibility label for the welcome dialog switch in the Game Dashboard Settings.">
+        Welcome notification is <ph name="STATE">$1<ex>on</ex></ph>
+      </message>
+      <message name="IDS_ASH_GAME_DASHBOARD_SETTINGS_WELCOME_DIALOG_TITLE" translateable="false" desc="The label displayed for the welcome dialog row of the Game Dashboard Settings.">
+        Welcome notification
+      </message>
+      <message name="IDS_ASH_GAME_DASHBOARD_TILE_ON" desc="The label for enabled Game Dashboard tiles.">
+        On
+      </message>
       <message name="IDS_ASH_GAME_DASHBOARD_TOOLBAR_TILE_BUTTON_TITLE" translateable="false" desc="The display name for the Game Dashboard toolbar tile.">
         Toolbar
       </message>
diff --git a/ash/ash_strings_grd/IDS_ASH_GAME_DASHBOARD_BACK_TOOLTIP.png.sha1 b/ash/ash_strings_grd/IDS_ASH_GAME_DASHBOARD_BACK_TOOLTIP.png.sha1
new file mode 100644
index 0000000..48c84a4f
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_GAME_DASHBOARD_BACK_TOOLTIP.png.sha1
@@ -0,0 +1 @@
+0018c6996a4d3cbf721392d2e00d5cf59a7c9a77
\ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_GAME_DASHBOARD_SETTINGS_TITLE.png.sha1 b/ash/ash_strings_grd/IDS_ASH_GAME_DASHBOARD_SETTINGS_TITLE.png.sha1
new file mode 100644
index 0000000..d3474426
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_GAME_DASHBOARD_SETTINGS_TITLE.png.sha1
@@ -0,0 +1 @@
+a73fb5b9b2ab77d078978bc33c0415c4a44e71ff
\ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_GAME_DASHBOARD_SETTINGS_WELCOME_DIALOG_A11Y_LABEL.png.sha1 b/ash/ash_strings_grd/IDS_ASH_GAME_DASHBOARD_SETTINGS_WELCOME_DIALOG_A11Y_LABEL.png.sha1
new file mode 100644
index 0000000..013ff96
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_GAME_DASHBOARD_SETTINGS_WELCOME_DIALOG_A11Y_LABEL.png.sha1
@@ -0,0 +1 @@
+6e5fe7a9411f4b9c2187b24640a13e2d841c30d6
\ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_GAME_DASHBOARD_SETTINGS_WELCOME_DIALOG_TITLE.png.sha1 b/ash/ash_strings_grd/IDS_ASH_GAME_DASHBOARD_SETTINGS_WELCOME_DIALOG_TITLE.png.sha1
new file mode 100644
index 0000000..bae4495
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_GAME_DASHBOARD_SETTINGS_WELCOME_DIALOG_TITLE.png.sha1
@@ -0,0 +1 @@
+9be1472e729665d8e410e14c8e99f11602f598ee
\ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_GAME_DASHBOARD_TILE_ON.png.sha1 b/ash/ash_strings_grd/IDS_ASH_GAME_DASHBOARD_TILE_ON.png.sha1
new file mode 100644
index 0000000..013ff96
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_GAME_DASHBOARD_TILE_ON.png.sha1
@@ -0,0 +1 @@
+6e5fe7a9411f4b9c2187b24640a13e2d841c30d6
\ No newline at end of file
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index aea364a..472bc9c 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -2122,7 +2122,7 @@
 // Enables the wayfinding improvements for the ChromeOS Settings revamp
 BASE_FEATURE(kOsSettingsRevampWayfinding,
              "OsSettingsRevampWayfinding",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 // Enables staying in overview when navigating between desks using a swipe
 // gesture or keyboard shortcut.
@@ -2700,11 +2700,6 @@
              "TelemetryExtension",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-// Enables the alternative emulator for the Terminal app.
-BASE_FEATURE(kTerminalAlternativeEmulator,
-             "TerminalAlternativeEmulator",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-//
 // Enables Terminal System App to load from Downloads for developer testing.
 // Only works in dev and canary channels.
 BASE_FEATURE(kTerminalDev, "TerminalDev", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index 2fb4dea..e9df4f4 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -821,8 +821,6 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kTelemetryExtension);
 COMPONENT_EXPORT(ASH_CONSTANTS)
 BASE_DECLARE_FEATURE(kTetheringExperimentalFunctionality);
-COMPONENT_EXPORT(ASH_CONSTANTS)
-BASE_DECLARE_FEATURE(kTerminalAlternativeEmulator);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kTerminalDev);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kTilingWindowResize);
 COMPONENT_EXPORT(ASH_CONSTANTS)
diff --git a/ash/game_dashboard/game_dashboard_context.cc b/ash/game_dashboard/game_dashboard_context.cc
index b5b3aa9e..54a20a3 100644
--- a/ash/game_dashboard/game_dashboard_context.cc
+++ b/ash/game_dashboard/game_dashboard_context.cc
@@ -93,7 +93,7 @@
     : game_window_(game_window),
       toolbar_snap_location_(ToolbarSnapLocation::kTopRight) {
   DCHECK(game_window_);
-  show_welcome_dialog_ = ShouldShowWelcomeDialog();
+  show_welcome_dialog_ = game_dashboard_utils::ShouldShowWelcomeDialog();
   CreateAndAddGameDashboardButtonWidget();
   // ARC windows handle displaying the welcome dialog once the
   // `game_dashboard_button_` becomes available.
@@ -512,14 +512,6 @@
   }
 }
 
-bool GameDashboardContext::ShouldShowWelcomeDialog() const {
-  PrefService* prefs =
-      Shell::Get()->session_controller()->GetActivePrefService();
-  DCHECK(prefs) << "A valid PrefService is needed to determine whether to show "
-                   "the welcome dialog.";
-  return prefs->GetBoolean(prefs::kGameDashboardShowWelcomeDialog);
-}
-
 void GameDashboardContext::UpdateOnMainMenuClosed() {
   DCHECK(main_menu_view_);
   RemoveCursorHandler();
diff --git a/ash/game_dashboard/game_dashboard_context.h b/ash/game_dashboard/game_dashboard_context.h
index 5a19bdc..a70ffd8 100644
--- a/ash/game_dashboard/game_dashboard_context.h
+++ b/ash/game_dashboard/game_dashboard_context.h
@@ -164,10 +164,6 @@
   // needed.
   void CloseWelcomeDialog();
 
-  // Checks whether the welcome dialog should be displayed when the game window
-  // opens.
-  bool ShouldShowWelcomeDialog() const;
-
   // Resets the `main_menu_view_`, removes the cursor handler, and updates the
   // `game_dashboard_button_` UI.
   void UpdateOnMainMenuClosed();
@@ -177,7 +173,8 @@
   // Game Dashboard button widget for the Game Dashboard.
   std::unique_ptr<views::Widget> game_dashboard_button_widget_;
 
-  // Expanded main menu for the Game Dashboard.
+  // Expanded main menu for the Game Dashboard, which displays the main menu and
+  // the settings view.
   views::UniqueWidgetPtr main_menu_widget_;
 
   // The toolbar for the Game Dashboard.
@@ -194,8 +191,8 @@
   raw_ptr<GameDashboardButton> game_dashboard_button_ = nullptr;
 
   // The `GameDashboardMainMenuView` when the user presses the Game Dashboard
-  // button.
-  // Owned by the views hierarchy.
+  // button to display all Game Dashboard views. This displays the main menu and
+  // settings views. Owned by the views hierarchy.
   raw_ptr<GameDashboardMainMenuView, DanglingUntriaged> main_menu_view_ =
       nullptr;
 
diff --git a/ash/game_dashboard/game_dashboard_context_test_api.cc b/ash/game_dashboard/game_dashboard_context_test_api.cc
index 79cbe957..959aa1ef 100644
--- a/ash/game_dashboard/game_dashboard_context_test_api.cc
+++ b/ash/game_dashboard/game_dashboard_context_test_api.cc
@@ -15,6 +15,7 @@
 #include "ash/public/cpp/ash_view_ids.h"
 #include "ash/style/icon_button.h"
 #include "ash/style/pill_button.h"
+#include "ash/style/switch.h"
 #include "ash/system/toast/anchored_nudge.h"
 #include "ash/system/unified/feature_tile.h"
 #include "base/timer/timer.h"
@@ -135,6 +136,30 @@
       GetMainMenuViewById(VIEW_ID_GD_GENERAL_SETTINGS_BUTTON));
 }
 
+views::BoxLayoutView* GameDashboardContextTestApi::GetMainMenuContainer() {
+  auto* main_menu_view = GetMainMenuView();
+  CHECK(main_menu_view);
+  return main_menu_view->main_menu_container_;
+}
+
+views::BoxLayoutView* GameDashboardContextTestApi::GetSettingsContainer() {
+  auto* main_menu_view = GetMainMenuView();
+  CHECK(main_menu_view);
+  return main_menu_view->settings_view_container_;
+}
+
+IconButton* GameDashboardContextTestApi::GetSettingsViewBackButton() {
+  auto* main_menu_view = GetMainMenuView();
+  CHECK(main_menu_view);
+  return main_menu_view->settings_view_back_button_;
+}
+
+Switch* GameDashboardContextTestApi::GetSettingsViewWelcomeDialogSwitch() {
+  auto* main_menu_view = GetMainMenuView();
+  CHECK(main_menu_view);
+  return main_menu_view->welcome_dialog_settings_switch_;
+}
+
 AnchoredNudge* GameDashboardContextTestApi::GetGameControlsSetupNudge() {
   if (auto* main_menu = GetMainMenuView()) {
     return main_menu->GetGameControlsSetupNudgeForTesting();
@@ -226,6 +251,8 @@
       << "The main menu widget must be opened first before opening the toolbar";
   ASSERT_TRUE(GetMainMenuView())
       << "The main menu view must be opened first before opening the toolbar";
+  ASSERT_TRUE(GetMainMenuContainer()->GetVisible())
+      << "The main menu container must be open before opening the toolbar";
   ASSERT_FALSE(GetToolbarView())
       << "The toolbar view must be closed before opening it";
   ASSERT_FALSE(GetToolbarWidget())
@@ -248,6 +275,8 @@
   ASSERT_TRUE(GetMainMenuWidget())
       << "The main menu widget must be opened first before closing the toolbar";
   ASSERT_TRUE(GetMainMenuView())
+      << "The main menu view must be open before closing the toolbar.";
+  ASSERT_TRUE(GetMainMenuContainer()->GetVisible())
       << "The main menu must be opened first before closing the toolbar";
   ASSERT_TRUE(GetToolbarView())
       << "The toolbar view must be opened before closing it";
@@ -261,6 +290,54 @@
   ASSERT_FALSE(GetToolbarWidget());
 }
 
+void GameDashboardContextTestApi::OpenMainMenuSettings() {
+  ASSERT_TRUE(GetMainMenuWidget()) << "The main menu widget must be opened "
+                                      "first before opening the settings view.";
+  ASSERT_TRUE(GetMainMenuView())
+      << "The main menu view must be open first to open the settings view.";
+  ASSERT_TRUE(GetMainMenuContainer()->GetVisible())
+      << "The main menu view must be displayed to open the settings view.";
+  auto* settings_container = GetSettingsContainer();
+  ASSERT_TRUE(!settings_container || !settings_container->GetVisible())
+      << "The settings container must either not be created or not visible "
+         "when opening the settings view.";
+  ClickOnView(GetMainMenuSettingsButton(), event_generator_);
+  ASSERT_TRUE(GetSettingsContainer()->GetVisible());
+  ASSERT_FALSE(GetMainMenuContainer()->GetVisible());
+}
+
+void GameDashboardContextTestApi::CloseTheSettings() {
+  ASSERT_TRUE(GetMainMenuWidget()) << "The main menu widget must be open "
+                                      "already when closing the settings view.";
+  ASSERT_TRUE(GetMainMenuView()) << "The main menu view must be open already "
+                                    "when closing the settings view.";
+  ASSERT_TRUE(GetSettingsContainer()->GetVisible())
+      << "The settings container must be visible when closing the settings "
+         "view.";
+  ASSERT_TRUE(!GetMainMenuContainer()->GetVisible())
+      << "The main menu container must not be visible when closing the "
+         "settings.";
+  ClickOnView(GetSettingsViewBackButton(), event_generator_);
+  ASSERT_FALSE(GetSettingsContainer()->GetVisible());
+  ASSERT_TRUE(GetMainMenuContainer()->GetVisible());
+}
+
+void GameDashboardContextTestApi::ToggleWelcomeDialogSettingsSwitch() {
+  ASSERT_TRUE(GetMainMenuWidget())
+      << "The main menu widget must be open already "
+         "when toggling the welcome dialog switch.";
+  ASSERT_TRUE(GetMainMenuView())
+      << "The main menu view must be open already when "
+         "toggling the welcome dialog switch.";
+  ASSERT_TRUE(GetSettingsContainer()->GetVisible())
+      << "The settings container must be visible when toggling the welcome "
+         "dialog switch.";
+  auto* welcome_dialog_switch = GetSettingsViewWelcomeDialogSwitch();
+  bool initial_state = welcome_dialog_switch->GetIsOn();
+  ClickOnView(welcome_dialog_switch, event_generator_);
+  ASSERT_EQ(GetSettingsViewWelcomeDialogSwitch()->GetIsOn(), !initial_state);
+}
+
 views::View* GameDashboardContextTestApi::GetMainMenuViewById(int view_id) {
   auto* main_menu_view = GetMainMenuView();
   CHECK(main_menu_view) << "The main menu must be opened first before "
diff --git a/ash/game_dashboard/game_dashboard_context_test_api.h b/ash/game_dashboard/game_dashboard_context_test_api.h
index e22ff18d..f515eeb 100644
--- a/ash/game_dashboard/game_dashboard_context_test_api.h
+++ b/ash/game_dashboard/game_dashboard_context_test_api.h
@@ -19,6 +19,7 @@
 }  // namespace ui::test
 
 namespace views {
+class BoxLayoutView;
 class Button;
 class Label;
 class LabelButton;
@@ -72,6 +73,10 @@
   views::LabelButton* GetMainMenuFeedbackButton();
   IconButton* GetMainMenuHelpButton();
   IconButton* GetMainMenuSettingsButton();
+  views::BoxLayoutView* GetMainMenuContainer();
+  views::BoxLayoutView* GetSettingsContainer();
+  IconButton* GetSettingsViewBackButton();
+  Switch* GetSettingsViewWelcomeDialogSwitch();
 
   // Returns the Game Controls setup nudge.
   AnchoredNudge* GetGameControlsSetupNudge();
@@ -116,6 +121,23 @@
   // is null.
   void CloseTheToolbar();
 
+  // Opens the settings view within the main menu view.
+  // Before opening the settings view, verifies the main menu widget and main
+  // menu container are not null. After opening the settings view, verifies it
+  // is open.
+  void OpenMainMenuSettings();
+
+  // Closes the settings view and re-opens the main menu within the main menu
+  // view. Before closing the settings view, verifies the main menu widget and
+  // settings container are not null. After closing the settings view, verifies
+  // the settings view is hidden and the main menu is visible.
+  void CloseTheSettings();
+
+  // Toggles the Welcome Dialog switch in the settings view.
+  // Before toggling the switch, verifies the settings view view is visible.
+  // After toggling the switch, verifies the switch state has changed.
+  void ToggleWelcomeDialogSettingsSwitch();
+
  private:
   // Returns a view from the `GameDashboardMainMenuView` for the given
   // `view_id`.
diff --git a/ash/game_dashboard/game_dashboard_context_unittest.cc b/ash/game_dashboard/game_dashboard_context_unittest.cc
index 8ee5711..34b04427 100644
--- a/ash/game_dashboard/game_dashboard_context_unittest.cc
+++ b/ash/game_dashboard/game_dashboard_context_unittest.cc
@@ -1576,6 +1576,44 @@
             ToolbarSnapLocation::kBottomLeft);
 }
 
+// Verifies the settings view can be closed via the back arrow and the Game
+// Dashboard button.
+TEST_P(GameTypeGameDashboardContextTest, OpenAndCloseSettingsView) {
+  test_api_->OpenTheMainMenu();
+  test_api_->OpenMainMenuSettings();
+
+  // Close the settings page via the back button and verify the main menu is now
+  // displayed.
+  test_api_->CloseTheSettings();
+  auto* main_menu_container = test_api_->GetMainMenuContainer();
+  EXPECT_TRUE(test_api_->GetMainMenuView());
+  EXPECT_TRUE(main_menu_container && main_menu_container->GetVisible());
+
+  // Re-open the settings view and close it via the Game Dashboard button.
+  test_api_->OpenMainMenuSettings();
+  test_api_->CloseTheMainMenu();
+}
+
+// Verifies the Welcome Dialog switch can be toggled off in the settings and its
+// state preserved.
+TEST_P(GameTypeGameDashboardContextTest, ToggleWelcomeDialogSettings) {
+  // Open the settings with the welcome dialog flag disabled.
+  test_api_->OpenTheMainMenu();
+  test_api_->OpenMainMenuSettings();
+
+  // Verify the initial welcome dialog switch state is disabled.
+  EXPECT_FALSE(test_api_->GetSettingsViewWelcomeDialogSwitch()->GetIsOn());
+
+  // Toggle the switch on, close the main menu, then reopen settings and verify
+  // the switch is still on.
+  test_api_->ToggleWelcomeDialogSettingsSwitch();
+  EXPECT_TRUE(test_api_->GetSettingsViewWelcomeDialogSwitch()->GetIsOn());
+  test_api_->CloseTheMainMenu();
+  test_api_->OpenTheMainMenu();
+  test_api_->OpenMainMenuSettings();
+  EXPECT_TRUE(test_api_->GetSettingsViewWelcomeDialogSwitch()->GetIsOn());
+}
+
 // -----------------------------------------------------------------------------
 // OnOverviewModeEndedWaiter:
 class OnOverviewModeEndedWaiter : public OverviewObserver {
diff --git a/ash/game_dashboard/game_dashboard_main_menu_view.cc b/ash/game_dashboard/game_dashboard_main_menu_view.cc
index 0e17f5cd..b04b488 100644
--- a/ash/game_dashboard/game_dashboard_main_menu_view.cc
+++ b/ash/game_dashboard/game_dashboard_main_menu_view.cc
@@ -40,6 +40,7 @@
 #include "base/task/sequenced_task_runner.h"
 #include "base/time/time.h"
 #include "components/strings/grit/components_strings.h"
+#include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -48,6 +49,7 @@
 #include "ui/compositor/layer_type.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/rounded_corners_f.h"
+#include "ui/gfx/text_constants.h"
 #include "ui/views/animation/animation_builder.h"
 #include "ui/views/animation/ink_drop.h"
 #include "ui/views/background.h"
@@ -56,7 +58,9 @@
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/highlight_path_generator.h"
 #include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/box_layout_view.h"
 #include "ui/views/layout/fill_layout.h"
+#include "ui/views/layout/flex_layout_view.h"
 #include "ui/views/view.h"
 #include "ui/views/view_class_properties.h"
 #include "ui/views/widget/widget.h"
@@ -527,9 +531,9 @@
       gfx::Insets::VH(kPaddingHeight, kPaddingWidth),
       /*between_child_spacing=*/16));
 
-  AddShortcutTilesRow();
-  MaybeAddArcFeatureRows();
-  AddUtilityClusterRow();
+  // TODO(b/326259321): Move the main menu view and settings view panels into
+  // separate class containers and show/hide the view containers
+  AddMainMenuViews();
 
   SizeToPreferredSize();
 }
@@ -595,6 +599,21 @@
       context_->game_window());
 }
 
+void GameDashboardMainMenuView::OnSettingsBackButtonPressed() {
+  DCHECK(settings_view_container_ && main_menu_container_);
+  DCHECK(settings_view_container_->GetVisible() &&
+         !main_menu_container_->GetVisible());
+  settings_view_container_->SetVisible(false);
+  main_menu_container_->SetVisible(true);
+  SizeToContents();
+}
+
+void GameDashboardMainMenuView::OnWelcomeDialogSwitchPressed() {
+  const bool new_state = welcome_dialog_settings_switch_->GetIsOn();
+  game_dashboard_utils::SetShowWelcomeDialog(new_state);
+  OnWelcomeDialogSwitchStateChanged(new_state);
+}
+
 void GameDashboardMainMenuView::OnGameControlsTilePressed() {
   auto* game_window = context_->game_window();
   game_window->SetProperty(
@@ -638,12 +657,32 @@
 }
 
 void GameDashboardMainMenuView::OnSettingsButtonPressed() {
-  // TODO(b/281773221): Add support when settings button is pressed.
+  DCHECK(main_menu_container_ && main_menu_container_->GetVisible());
+  main_menu_container_->SetVisible(false);
+  if (settings_view_container_) {
+    settings_view_container_->SetVisible(true);
+  } else {
+    AddSettingsViews();
+  }
+  SizeToContents();
+}
+
+void GameDashboardMainMenuView::AddMainMenuViews() {
+  DCHECK(!main_menu_container_);
+  main_menu_container_ = AddChildView(std::make_unique<views::BoxLayoutView>());
+  main_menu_container_->SetOrientation(
+      views::BoxLayout::Orientation::kVertical);
+  main_menu_container_->SetBetweenChildSpacing(16);
+
+  AddShortcutTilesRow();
+  MaybeAddArcFeatureRows();
+  AddUtilityClusterRow();
 }
 
 void GameDashboardMainMenuView::AddShortcutTilesRow() {
-  views::BoxLayoutView* container =
-      AddChildView(std::make_unique<views::BoxLayoutView>());
+  DCHECK(main_menu_container_);
+  views::BoxLayoutView* container = main_menu_container_->AddChildView(
+      std::make_unique<views::BoxLayoutView>());
   container->SetOrientation(views::BoxLayout::Orientation::kHorizontal);
   container->SetBetweenChildSpacing(kCenterPadding);
 
@@ -697,9 +736,9 @@
   if (!IsArcWindow(context_->game_window())) {
     return;
   }
-
+  DCHECK(main_menu_container_);
   auto* feature_details_container =
-      AddChildView(std::make_unique<views::View>());
+      main_menu_container_->AddChildView(std::make_unique<views::View>());
   feature_details_container->SetLayoutManager(
       std::make_unique<views::BoxLayout>(
           views::BoxLayout::Orientation::kVertical,
@@ -754,7 +793,9 @@
 }
 
 void GameDashboardMainMenuView::AddUtilityClusterRow() {
-  auto* container = AddChildView(std::make_unique<views::View>());
+  DCHECK(main_menu_container_);
+  auto* container =
+      main_menu_container_->AddChildView(std::make_unique<views::View>());
   auto* layout = container->SetLayoutManager(std::make_unique<views::BoxLayout>(
       views::BoxLayout::Orientation::kHorizontal,
       /*inside_border_insets=*/gfx::Insets(),
@@ -918,6 +959,104 @@
   Shell::Get()->anchored_nudge_manager()->Show(nudge_data);
 }
 
+void GameDashboardMainMenuView::AddSettingsViews() {
+  DCHECK(!settings_view_container_);
+  settings_view_container_ =
+      AddChildView(std::make_unique<views::BoxLayoutView>());
+  settings_view_container_->SetOrientation(
+      views::BoxLayout::Orientation::kVertical);
+  settings_view_container_->SetBetweenChildSpacing(16);
+
+  AddSettingsTitleRow();
+  AddWelcomeDialogSettingsRow();
+}
+
+void GameDashboardMainMenuView::AddSettingsTitleRow() {
+  auto* title_container = settings_view_container_->AddChildView(
+      std::make_unique<views::BoxLayoutView>());
+  title_container->SetOrientation(views::BoxLayout::Orientation::kHorizontal);
+  title_container->SetInsideBorderInsets(
+      gfx::Insets::TLBR(0, 0, 0, /*padding to offset back button size=*/32));
+
+  // Add back button to the title container.
+  settings_view_back_button_ =
+      title_container->AddChildView(std::make_unique<IconButton>(
+          base::BindRepeating(
+              &GameDashboardMainMenuView::OnSettingsBackButtonPressed,
+              base::Unretained(this)),
+          IconButton::Type::kMedium, &kQuickSettingsLeftArrowIcon,
+          IDS_ASH_GAME_DASHBOARD_BACK_TOOLTIP));
+
+  // Add title label to the title container.
+  auto* title = title_container->AddChildView(bubble_utils::CreateLabel(
+      TypographyToken::kCrosTitle1,
+      l10n_util::GetStringUTF16(IDS_ASH_GAME_DASHBOARD_SETTINGS_TITLE),
+      cros_tokens::kCrosSysOnSurface));
+  title->SetMultiLine(true);
+  title->SetHorizontalAlignment(gfx::ALIGN_CENTER);
+  // Flex `title` to fill empty space in row.
+  title_container->SetFlexForView(title, /*flex=*/1);
+}
+
+void GameDashboardMainMenuView::AddWelcomeDialogSettingsRow() {
+  auto* welcome_settings_container = settings_view_container_->AddChildView(
+      std::make_unique<views::BoxLayoutView>());
+  welcome_settings_container->SetOrientation(
+      views::BoxLayout::Orientation::kHorizontal);
+  welcome_settings_container->SetInsideBorderInsets(gfx::Insets::VH(16, 16));
+  welcome_settings_container->SetBackground(
+      views::CreateThemedRoundedRectBackground(
+          cros_tokens::kCrosSysSystemOnBase, kBubbleCornerRadius));
+
+  // Add icon.
+  auto* icon_container = welcome_settings_container->AddChildView(
+      std::make_unique<views::FlexLayoutView>());
+  icon_container->SetBackground(views::CreateThemedRoundedRectBackground(
+      cros_tokens::kCrosSysSystemOnBase,
+      /*radius=*/12.0f));
+  icon_container->SetBorder(views::CreateEmptyBorder(gfx::Insets::VH(6, 6)));
+  icon_container->SetProperty(views::kMarginsKey,
+                              gfx::Insets::TLBR(0, 0, 0, 16));
+  icon_container->AddChildView(
+      std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
+          kGdNotificationIcon, cros_tokens::kCrosSysOnSurface,
+          /*icon_size=*/20)));
+
+  // Add title.
+  auto* feature_title = welcome_settings_container->AddChildView(
+      std::make_unique<views::Label>(l10n_util::GetStringUTF16(
+          IDS_ASH_GAME_DASHBOARD_SETTINGS_WELCOME_DIALOG_TITLE)));
+  feature_title->SetAutoColorReadabilityEnabled(false);
+  feature_title->SetEnabledColorId(cros_tokens::kCrosSysOnSurface);
+  feature_title->SetFontList(TypographyProvider::Get()->ResolveTypographyToken(
+      TypographyToken::kCrosTitle2));
+  feature_title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  feature_title->SetMultiLine(true);
+  feature_title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  // Flex `feature_title` to fill empty space in row.
+  welcome_settings_container->SetFlexForView(feature_title, /*flex=*/1);
+
+  // Add welcome dialog switch.
+  welcome_dialog_settings_switch_ = welcome_settings_container->AddChildView(
+      std::make_unique<Switch>(base::BindRepeating(
+          &GameDashboardMainMenuView::OnWelcomeDialogSwitchPressed,
+          base::Unretained(this))));
+  const bool is_enabled = game_dashboard_utils::ShouldShowWelcomeDialog();
+  OnWelcomeDialogSwitchStateChanged(is_enabled);
+  welcome_dialog_settings_switch_->SetProperty(views::kMarginsKey,
+                                               gfx::Insets::TLBR(0, 8, 0, 0));
+  welcome_dialog_settings_switch_->SetIsOn(is_enabled);
+}
+
+void GameDashboardMainMenuView::OnWelcomeDialogSwitchStateChanged(
+    bool is_enabled) {
+  welcome_dialog_settings_switch_->SetAccessibleName(l10n_util::GetStringFUTF16(
+      IDS_ASH_GAME_DASHBOARD_SETTINGS_WELCOME_DIALOG_A11Y_LABEL,
+      l10n_util::GetStringUTF16(is_enabled
+                                    ? IDS_ASH_GAME_DASHBOARD_TILE_ON
+                                    : IDS_ASH_GAME_DASHBOARD_GC_TILE_OFF)));
+}
+
 PillButton* GameDashboardMainMenuView::GetGameControlsSetupButton() {
   return game_controls_details_ ? game_controls_details_->setup_button()
                                 : nullptr;
diff --git a/ash/game_dashboard/game_dashboard_main_menu_view.h b/ash/game_dashboard/game_dashboard_main_menu_view.h
index fe5e0ccd..3236fba 100644
--- a/ash/game_dashboard/game_dashboard_main_menu_view.h
+++ b/ash/game_dashboard/game_dashboard_main_menu_view.h
@@ -12,11 +12,16 @@
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
 
+namespace views {
+class BoxLayoutView;
+}  // namespace views
+
 namespace ash {
 
 class AnchoredNudge;
 class FeatureTile;
 class GameDashboardContext;
+class IconButton;
 class PillButton;
 class Switch;
 
@@ -64,6 +69,13 @@
   // Handles taking a screenshot of the game window when pressed.
   void OnScreenshotTilePressed();
 
+  // Callbacks for the buttons in the settings view.
+  // Handles going back to the main menu view when pressed.
+  void OnSettingsBackButtonPressed();
+  // Handles toggling the welcome dialog preference and updating the Switch
+  // state.
+  void OnWelcomeDialogSwitchPressed();
+
   // Handles functions for Game Controls buttons.
   void OnGameControlsTilePressed();
 
@@ -76,12 +88,16 @@
   // Opens up the Game Dashboard Settings.
   void OnSettingsButtonPressed();
 
-  // Adds a row of shortcut tiles to the main menu view for users to quickly
-  // access common functionality.
+  // Creates the `main_menu_container_` and adds all rows of views pertaining to
+  // the main menu view to it.
+  void AddMainMenuViews();
+
+  // Adds a row of shortcut tiles to the `main_menu_container_` for users to
+  // quickly access common functionality.
   void AddShortcutTilesRow();
 
   // Adds feature details rows, for example, including Game Controls or window
-  // size.
+  // size to the `main_menu_container_`.
   void MaybeAddArcFeatureRows();
 
   // Adds Game Controls feature tile in `container` if it is the ARC game window
@@ -96,7 +112,7 @@
   void AddScreenSizeSettingsRow(views::View* container);
 
   // Adds the dashboard cluster (containing feedback, settings, and help
-  // buttons) to the Game Controls tile view.
+  // buttons) to the `main_menu_container_`.
   void AddUtilityClusterRow();
 
   // views::View:
@@ -116,6 +132,19 @@
   // Shows education nudge for `game_controls_setup_button_`.
   void ShowNudgeForSetupButton();
 
+  // Creates the `settings_view_container_` and adds all rows pertaining to the
+  // settings view to it.
+  void AddSettingsViews();
+
+  // Adds a row displaying the title and back button.
+  void AddSettingsTitleRow();
+
+  // Adds a row displaying the welcome dialog setting.
+  void AddWelcomeDialogSettingsRow();
+
+  // Updates the accessible name for the `welcome_dialog_settings_switch_`.
+  void OnWelcomeDialogSwitchStateChanged(bool is_enabled);
+
   // Gets UI elements from Game Controls details row.
   PillButton* GetGameControlsSetupButton();
   Switch* GetGameControlsFeatureSwith();
@@ -129,6 +158,12 @@
   // Allows this class to access `GameDashboardContext` owned functions/objects.
   const raw_ptr<GameDashboardContext> context_;
 
+  // Container holding all views displayed in the main menu view.
+  raw_ptr<views::BoxLayoutView> main_menu_container_ = nullptr;
+
+  // Container holding all views displayed in the settings view.
+  raw_ptr<views::BoxLayoutView> settings_view_container_ = nullptr;
+
   // Shortcut Tiles:
   // Toolbar button to toggle the `GameDashboardToolbarView`.
   raw_ptr<FeatureTile> toolbar_tile_ = nullptr;
@@ -143,6 +178,12 @@
   // Game Controls details row to configure Game Controls.
   raw_ptr<GameControlsDetailsRow> game_controls_details_ = nullptr;
 
+  // The `Switch` representing toggling the welcome dialog within the settings.
+  raw_ptr<Switch> welcome_dialog_settings_switch_ = nullptr;
+
+  // Back button in the `settings_view_container_`. Visible for testing.
+  raw_ptr<IconButton> settings_view_back_button_ = nullptr;
+
   // Layer for setup button pulse animation.
   std::unique_ptr<ui::Layer> gc_setup_button_pulse_layer_;
 };
diff --git a/ash/game_dashboard/game_dashboard_utils.cc b/ash/game_dashboard/game_dashboard_utils.cc
index a0f66a2..40a2121 100644
--- a/ash/game_dashboard/game_dashboard_utils.cc
+++ b/ash/game_dashboard/game_dashboard_utils.cc
@@ -4,11 +4,14 @@
 
 #include "ash/game_dashboard/game_dashboard_utils.h"
 
+#include "ash/constants/ash_pref_names.h"
 #include "ash/public/cpp/app_types_util.h"
 #include "ash/public/cpp/window_properties.h"
+#include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/style/icon_button.h"
 #include "ash/system/unified/feature_tile.h"
+#include "components/prefs/pref_service.h"
 #include "ui/aura/window.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/views/controls/button/button.h"
@@ -100,4 +103,20 @@
          !IsFlagSet(flags, ArcGameControlsFlag::kEdit);
 }
 
+bool ShouldShowWelcomeDialog() {
+  PrefService* prefs =
+      Shell::Get()->session_controller()->GetActivePrefService();
+  DCHECK(prefs) << "A valid PrefService is needed to determine whether to show "
+                   "the welcome dialog.";
+  return prefs->GetBoolean(prefs::kGameDashboardShowWelcomeDialog);
+}
+
+void SetShowWelcomeDialog(bool show_dialog) {
+  PrefService* prefs =
+      Shell::Get()->session_controller()->GetActivePrefService();
+  DCHECK(prefs) << "A valid PrefService is needed to update the show welcome "
+                   "dialog param.";
+  prefs->SetBoolean(prefs::kGameDashboardShowWelcomeDialog, show_dialog);
+}
+
 }  // namespace ash::game_dashboard_utils
diff --git a/ash/game_dashboard/game_dashboard_utils.h b/ash/game_dashboard/game_dashboard_utils.h
index 6326f627..9f3d09c5 100644
--- a/ash/game_dashboard/game_dashboard_utils.h
+++ b/ash/game_dashboard/game_dashboard_utils.h
@@ -49,6 +49,14 @@
 // known and not in edit mode.
 bool ShouldEnableGameDashboardButton(aura::Window* window);
 
+// Checks whether the welcome dialog should be displayed when the game window
+// opens.
+bool ShouldShowWelcomeDialog();
+
+// Updates the `PrefService` preference for showing the welcome dialog with
+// the new value specified in `show_dialog`.
+void SetShowWelcomeDialog(bool show_dialog);
+
 }  // namespace ash::game_dashboard_utils
 
 #endif  // ASH_GAME_DASHBOARD_GAME_DASHBOARD_UTILS_H_
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn
index 241cf0e2..f5d0d77b 100644
--- a/ash/resources/vector_icons/BUILD.gn
+++ b/ash/resources/vector_icons/BUILD.gn
@@ -133,6 +133,7 @@
     "gd_button_up_arrow.icon",
     "gd_game_controls.icon",
     "gd_help.icon",
+    "gd_notification.icon",
     "gd_record_game.icon",
     "gd_screen_size_settings.icon",
     "gd_screenshot.icon",
diff --git a/ash/resources/vector_icons/gd_notification.icon b/ash/resources/vector_icons/gd_notification.icon
new file mode 100644
index 0000000..44b6bcd
--- /dev/null
+++ b/ash/resources/vector_icons/gd_notification.icon
@@ -0,0 +1,32 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 18, 14,
+R_V_LINE_TO, 2,
+H_LINE_TO, 2,
+R_V_LINE_TO, -2,
+R_H_LINE_TO, 2,
+V_LINE_TO, 9.5f,
+R_CUBIC_TO, 0, -3.08f, 1.64f, -5.64f, 4.5f, -6.32f,
+V_LINE_TO, 2.5f,
+R_CUBIC_TO, 0, -0.83f, 0.67f, -1.5f, 1.5f, -1.5f,
+R_CUBIC_TO, 0.83f, 0, 1.5f, 0.67f, 1.5f, 1.5f,
+R_V_LINE_TO, 0.68f,
+R_CUBIC_TO, 2.87f, 0.68f, 4.5f, 3.25f, 4.5f, 6.32f,
+V_LINE_TO, 14,
+R_H_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, -4, -4.5f,
+CUBIC_TO, 14, 7.02f, 12.49f, 5, 10, 5,
+CUBIC_TO_SHORTHAND, 6, 7.02f, 6, 9.5f,
+V_LINE_TO, 14,
+R_H_LINE_TO, 8,
+V_LINE_TO, 9.5f,
+CLOSE,
+MOVE_TO, 10, 19,
+R_CUBIC_TO, 1.1f, 0, 2, -0.9f, 2, -2,
+H_LINE_TO, 8,
+R_CUBIC_TO, 0, 1.1f, 0.9f, 2, 2, 2,
+CLOSE
\ No newline at end of file
diff --git a/ash/webui/common/resources/BUILD.gn b/ash/webui/common/resources/BUILD.gn
index 8ecc446..e86233d 100644
--- a/ash/webui/common/resources/BUILD.gn
+++ b/ash/webui/common/resources/BUILD.gn
@@ -245,6 +245,7 @@
     "//ui/webui/resources/mojo:build_ts",
   ]
   definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/chrome_send.d.ts",
     "//tools/typescript/definitions/metrics_private.d.ts",
     "//tools/typescript/definitions/quick_unlock_private.d.ts",
diff --git a/ash/webui/common/resources/cellular_setup/BUILD.gn b/ash/webui/common/resources/cellular_setup/BUILD.gn
index b1174ab0..23bde42 100644
--- a/ash/webui/common/resources/cellular_setup/BUILD.gn
+++ b/ash/webui/common/resources/cellular_setup/BUILD.gn
@@ -59,6 +59,7 @@
   ts_composite = true
   ts_definitions = [
     "//tools/typescript/definitions/context_menus.d.ts",
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/extension_types.d.ts",
     "//tools/typescript/definitions/metrics_private.d.ts",
     "//tools/typescript/definitions/pending.d.ts",
@@ -68,8 +69,8 @@
   ]
   ts_deps = [
     "//ash/webui/common/resources:build_ts",
-    "//third_party/polymer/v3_0:library",
     "//ash/webui/common/resources/cr_elements:build_ts",
+    "//third_party/polymer/v3_0:library",
     "//ui/webui/resources/js:build_ts",
     "//ui/webui/resources/mojo:build_ts",
   ]
diff --git a/ash/webui/common/resources/cr_elements/BUILD.gn b/ash/webui/common/resources/cr_elements/BUILD.gn
index 054def89..6d483ecb 100644
--- a/ash/webui/common/resources/cr_elements/BUILD.gn
+++ b/ash/webui/common/resources/cr_elements/BUILD.gn
@@ -88,6 +88,7 @@
     "//ui/webui/resources/js:build_ts",
   ]
   ts_definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/pending.d.ts",
     "//tools/typescript/definitions/settings_private.d.ts",
   ]
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc
index b89fef7..d6f1262 100644
--- a/ash/wm/splitview/split_view_controller_unittest.cc
+++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -3917,6 +3917,29 @@
       faster_split_screen_enabled() ? 0 : 1);
 }
 
+// Test that there will be no crash when disabling a tablet mode when a window
+// with a transient bubble widget is snapped. Regression test for b/327135981.
+TEST_F(SplitViewControllerTest,
+       ClamshellConversionWithSnappedWindowWithTransient) {
+  // Create a widget with a transient bubble widget.
+  std::unique_ptr<views::Widget> widget(CreateTestWidget());
+  aura::Window* window = widget->GetNativeWindow();
+  window->SetProperty(aura::client::kResizeBehaviorKey,
+                      aura::client::kResizeBehaviorCanResize |
+                          aura::client::kResizeBehaviorCanMaximize);
+  views::Widget* bubble_widget = views::BubbleDialogDelegateView::CreateBubble(
+      new TestBubbleDialogDelegateView(widget->GetContentsView()));
+  aura::Window* bubble_transient = bubble_widget->GetNativeWindow();
+  EXPECT_TRUE(wm::HasTransientAncestor(bubble_transient, window));
+
+  // Snap the window.
+  ToggleOverview();
+  split_view_controller()->SnapWindow(window, SnapPosition::kSecondary);
+
+  // Convert the device to clamshell mode. There should be no crash.
+  Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false);
+}
+
 // The test class that enables the feature flag of portrait mode split view
 // virtual keyboard improvement and the virtual keyboard.
 class SplitViewKeyboardTest : public SplitViewControllerTest {
diff --git a/ash/wm/splitview/split_view_divider.cc b/ash/wm/splitview/split_view_divider.cc
index e545c19..f099c59 100644
--- a/ash/wm/splitview/split_view_divider.cc
+++ b/ash/wm/splitview/split_view_divider.cc
@@ -137,6 +137,7 @@
     wm::TransientWindowManager::GetOrCreate(window)->RemoveObserver(this);
   }
   observed_windows_.clear();
+  transient_windows_observations_.RemoveAllObservations();
 
   dragged_window_ = nullptr;
 
diff --git a/ash/wm/window_restore/pine_contents_view.h b/ash/wm/window_restore/pine_contents_view.h
index 061a349..7c9474997 100644
--- a/ash/wm/window_restore/pine_contents_view.h
+++ b/ash/wm/window_restore/pine_contents_view.h
@@ -37,7 +37,7 @@
 
   static std::unique_ptr<views::Widget> Create(aura::Window* root);
 
-  // TODO(sammiequon): Move these to a test api.
+  // TODO(b/327499182): Move test functions to a Pine test API.
   const PillButton* restore_button_for_testing() const {
     return restore_button_for_testing_;
   }
@@ -45,6 +45,10 @@
     return cancel_button_for_testing_;
   }
 
+  const PineItemsContainerView* container_view_for_testing() const {
+    return container_view_;
+  }
+
  private:
   FRIEND_TEST_ALL_PREFIXES(PineContextMenuModelTest,
                            ShowContextMenuOnSettingsButtonClicked);
diff --git a/ash/wm/window_restore/pine_items_container_view.cc b/ash/wm/window_restore/pine_items_container_view.cc
index bb1e1fc..f9b497e 100644
--- a/ash/wm/window_restore/pine_items_container_view.cc
+++ b/ash/wm/window_restore/pine_items_container_view.cc
@@ -171,7 +171,8 @@
     // If there are more than four elements, we will need to save the last
     // space for the overflow view to condense the remaining info.
     if (elements > pine::kMaxItems && i >= pine::kOverflowMinThreshold) {
-      AddChildView(std::make_unique<PineItemsOverflowView>(apps_infos));
+      overflow_view_for_testing_ =
+          AddChildView(std::make_unique<PineItemsOverflowView>(apps_infos));
       break;
     }
 
diff --git a/ash/wm/window_restore/pine_items_container_view.h b/ash/wm/window_restore/pine_items_container_view.h
index 59cb259..1d57384 100644
--- a/ash/wm/window_restore/pine_items_container_view.h
+++ b/ash/wm/window_restore/pine_items_container_view.h
@@ -11,6 +11,8 @@
 
 namespace ash {
 
+class PineItemsOverflowView;
+
 // The right side contents (in LTR) of the `PineContentsView`. It is a
 // vertical list of `PineItemView`, with each view representing an app. Shows
 // a maximum of `kMaxItems` items.
@@ -23,6 +25,13 @@
   PineItemsContainerView(const PineItemsContainerView&) = delete;
   PineItemsContainerView& operator=(const PineItemsContainerView&) = delete;
   ~PineItemsContainerView() override = default;
+
+  const PineItemsOverflowView* overflow_view_for_testing() const {
+    return overflow_view_for_testing_;
+  }
+
+ private:
+  raw_ptr<PineItemsOverflowView> overflow_view_for_testing_ = nullptr;
 };
 
 }  // namespace ash
diff --git a/ash/wm/window_restore/pine_items_overflow_view.cc b/ash/wm/window_restore/pine_items_overflow_view.cc
index 523a2a8..dec14bd 100644
--- a/ash/wm/window_restore/pine_items_overflow_view.cc
+++ b/ash/wm/window_restore/pine_items_overflow_view.cc
@@ -46,10 +46,6 @@
   // TODO(sammiequon): Handle case where the app is not ready or installed.
   auto* delegate = Shell::Get()->saved_desk_delegate();
 
-  // Save the views so they can be used later (e.g., for callbacks).
-  views::BoxLayoutView* top_row_view;
-  views::BoxLayoutView* bottom_row_view;
-
   // Create a series of `BoxLayoutView`s to represent a 1x2 row, a triangle
   // with one element on top and two on the bottom, or a 2x2 box. The triangle
   // is specific to the 3-window overflow case, and is why we prefer a
@@ -63,7 +59,7 @@
               SK_ColorLTGRAY, kOverflowBackgroundRounding))
           .AddChildren(
               views::Builder<views::BoxLayoutView>()
-                  .CopyAddressTo(&top_row_view)
+                  .CopyAddressTo(&top_row_view_)
                   .SetOrientation(views::BoxLayout::Orientation::kHorizontal)
                   .SetMainAxisAlignment(
                       views::BoxLayout::MainAxisAlignment::kCenter)
@@ -71,7 +67,7 @@
                       views::BoxLayout::CrossAxisAlignment::kStretch)
                   .SetBetweenChildSpacing(kOverflowIconSpacing),
               views::Builder<views::BoxLayoutView>()
-                  .CopyAddressTo(&bottom_row_view)
+                  .CopyAddressTo(&bottom_row_view_)
                   .SetOrientation(views::BoxLayout::Orientation::kHorizontal)
                   .SetMainAxisAlignment(
                       views::BoxLayout::MainAxisAlignment::kCenter)
@@ -87,7 +83,7 @@
     // bottom row to count the remaining windows.
     if (elements > kOverflowMaxElements && i >= kOverflowMaxThreshold) {
       views::Label* count_label;
-      bottom_row_view->AddChildView(
+      bottom_row_view_->AddChildView(
           views::Builder<views::Label>()
               .CopyAddressTo(&count_label)
               // TODO(hewer): Cut off the maximum number of digits to
@@ -116,8 +112,8 @@
                 // == 4) to the top row, as the view will be in a 1x2 or 2x2
                 // configuration.
                 (elements != kOverflowTriangleElements && i <= pine::kMaxItems)
-            ? top_row_view
-            : bottom_row_view;
+            ? top_row_view_
+            : bottom_row_view_;
     views::ImageView* image_view =
         row_view->AddChildView(views::Builder<views::ImageView>()
                                    .SetImageSize(kOverflowIconPreferredSize)
diff --git a/ash/wm/window_restore/pine_items_overflow_view.h b/ash/wm/window_restore/pine_items_overflow_view.h
index 4ccb590..a6f36a2 100644
--- a/ash/wm/window_restore/pine_items_overflow_view.h
+++ b/ash/wm/window_restore/pine_items_overflow_view.h
@@ -30,8 +30,25 @@
 
   void SetIconForIndex(int index, const gfx::ImageSkia& icon);
 
+  const base::flat_map<int, views::ImageView*>& image_view_map_for_testing()
+      const {
+    return image_view_map_;
+  }
+
+  const views::BoxLayoutView* top_row_view_for_testing() const {
+    return top_row_view_;
+  }
+  const views::BoxLayoutView* bottom_row_view_for_testing() const {
+    return bottom_row_view_;
+  }
+
  private:
   base::flat_map<int, views::ImageView*> image_view_map_;
+
+  // These views are stacked vertically to act as rows of window icons.
+  raw_ptr<views::BoxLayoutView> top_row_view_ = nullptr;
+  raw_ptr<views::BoxLayoutView> bottom_row_view_ = nullptr;
+
   base::WeakPtrFactory<PineItemsOverflowView> weak_ptr_factory_{this};
 };
 
diff --git a/ash/wm/window_restore/pine_unittest.cc b/ash/wm/window_restore/pine_unittest.cc
index 421ad92..c7c355d 100644
--- a/ash/wm/window_restore/pine_unittest.cc
+++ b/ash/wm/window_restore/pine_unittest.cc
@@ -10,22 +10,26 @@
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/overview/overview_controller.h"
+#include "ash/wm/overview/overview_grid.h"
+#include "ash/wm/overview/overview_grid_test_api.h"
 #include "ash/wm/overview/overview_session.h"
 #include "ash/wm/overview/overview_test_util.h"
 #include "ash/wm/overview/overview_types.h"
+#include "ash/wm/window_restore/pine_constants.h"
 #include "ash/wm/window_restore/pine_contents_data.h"
 #include "ash/wm/window_restore/pine_contents_view.h"
 #include "ash/wm/window_restore/pine_context_menu_model.h"
 #include "ash/wm/window_restore/pine_controller.h"
+#include "ash/wm/window_restore/pine_items_container_view.h"
+#include "ash/wm/window_restore/pine_items_overflow_view.h"
 #include "base/test/bind.h"
 #include "base/test/scoped_feature_list.h"
+#include "components/app_constants/constants.h"
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/view_utils.h"
 
 namespace ash {
 
-// TODO(b/322358447): Add unit tests for overflow view.
-
 class PineTest : public AshTestBase {
  public:
   PineTest() { switches::SetIgnoreForestSecretKeyForTest(true); }
@@ -33,6 +37,49 @@
   PineTest& operator=(const PineTest&) = delete;
   ~PineTest() override { switches::SetIgnoreForestSecretKeyForTest(false); }
 
+  void StartPineOverviewSession(std::unique_ptr<PineContentsData> data) {
+    Shell::Get()->pine_controller()->MaybeStartPineOverviewSession(
+        std::move(data));
+    WaitForOverviewEntered();
+
+    OverviewSession* overview_session =
+        OverviewController::Get()->overview_session();
+    ASSERT_TRUE(overview_session);
+    EXPECT_EQ(OverviewEnterExitType::kPine,
+              overview_session->enter_exit_overview_type());
+
+    // Check that the pine widget exists.
+    OverviewGrid* grid = GetOverviewGridForRoot(Shell::GetPrimaryRootWindow());
+    ASSERT_TRUE(grid);
+    auto* pine_widget = OverviewGridTestApi(grid).pine_widget();
+    ASSERT_TRUE(pine_widget);
+
+    const PineContentsView* contents_view =
+        views::AsViewClass<PineContentsView>(pine_widget->GetContentsView());
+    ASSERT_TRUE(contents_view);
+    ASSERT_TRUE(contents_view->container_view_for_testing());
+  }
+
+  const PineItemsOverflowView* GetOverflowView() const {
+    return views::AsViewClass<PineContentsView>(
+               OverviewGridTestApi(Shell::GetPrimaryRootWindow())
+                   .pine_widget()
+                   ->GetContentsView())
+        ->container_view_for_testing()
+        ->overflow_view_for_testing();
+  }
+
+  // Used for testing overview. Returns a vector with `n` chrome browser app
+  // ids.
+  std::unique_ptr<PineContentsData> MakeTestAppIds(int n) {
+    auto data = std::make_unique<PineContentsData>();
+    for (int i = 0; i < n; ++i) {
+      data->apps_infos.emplace_back(app_constants::kChromeAppId);
+    }
+
+    return data;
+  }
+
  private:
   base::test::ScopedFeatureList scoped_feature_list_{features::kForestFeature};
 };
@@ -50,4 +97,88 @@
             overview_session->enter_exit_overview_type());
 }
 
+TEST_F(PineTest, NoOverflow) {
+  auto data = std::make_unique<PineContentsData>();
+  data->last_session_crashed = false;
+
+  // Start a Pine session with restore data for one window.
+  StartPineOverviewSession(MakeTestAppIds(1));
+  EXPECT_FALSE(GetOverflowView());
+}
+
+TEST_F(PineTest, TwoWindowOverflow) {
+  auto data = std::make_unique<PineContentsData>();
+  data->last_session_crashed = false;
+
+  // Start a Pine session with restore data for two overflow windows.
+  StartPineOverviewSession(MakeTestAppIds(pine::kOverflowMinThreshold + 2));
+
+  const PineItemsOverflowView* overflow_view = GetOverflowView();
+  ASSERT_TRUE(overflow_view);
+  EXPECT_EQ(2u, overflow_view->image_view_map_for_testing().size());
+
+  // The top row should have two elements, and the bottom row should have zero
+  // elements, in order to form a 2x1 layout.
+  EXPECT_EQ(2u, overflow_view->top_row_view_for_testing()->children().size());
+  EXPECT_EQ(0u,
+            overflow_view->bottom_row_view_for_testing()->children().size());
+}
+
+TEST_F(PineTest, ThreeWindowOverflow) {
+  auto data = std::make_unique<PineContentsData>();
+  data->last_session_crashed = false;
+
+  // Start a Pine session with restore data for three overflow windows.
+  StartPineOverviewSession(MakeTestAppIds(pine::kOverflowMinThreshold + 3));
+
+  const PineItemsOverflowView* overflow_view = GetOverflowView();
+  ASSERT_TRUE(overflow_view);
+  EXPECT_EQ(3u, overflow_view->image_view_map_for_testing().size());
+
+  // The top row should have one element, and the bottom row should have two
+  // elements, in order to form a triangular layout.
+  EXPECT_EQ(1u, overflow_view->top_row_view_for_testing()->children().size());
+  EXPECT_EQ(2u,
+            overflow_view->bottom_row_view_for_testing()->children().size());
+}
+
+TEST_F(PineTest, FourWindowOverflow) {
+  auto data = std::make_unique<PineContentsData>();
+  data->last_session_crashed = false;
+
+  // Start a Pine session with restore data for four overflow windows.
+  StartPineOverviewSession(MakeTestAppIds(pine::kOverflowMinThreshold + 4));
+
+  const PineItemsOverflowView* overflow_view = GetOverflowView();
+  ASSERT_TRUE(overflow_view);
+  EXPECT_EQ(4u, overflow_view->image_view_map_for_testing().size());
+
+  // The top and bottom rows should have two elements each, in order to form a
+  // 2x2 layout.
+  EXPECT_EQ(2u, overflow_view->top_row_view_for_testing()->children().size());
+  EXPECT_EQ(2u,
+            overflow_view->bottom_row_view_for_testing()->children().size());
+}
+
+TEST_F(PineTest, FivePlusWindowOverflow) {
+  auto data = std::make_unique<PineContentsData>();
+  data->last_session_crashed = false;
+
+  // Start a Pine session with restore data for five overflow windows.
+  StartPineOverviewSession(MakeTestAppIds(pine::kOverflowMinThreshold + 5));
+
+  const PineItemsOverflowView* overflow_view = GetOverflowView();
+  ASSERT_TRUE(overflow_view);
+
+  // The image view map should only have three elements as the fourth slot is
+  // saved for a count of the remaining windows.
+  EXPECT_EQ(3u, overflow_view->image_view_map_for_testing().size());
+
+  // The top row should have two elements, and the bottom row should have zero
+  // elements, in order to form a 2x2 layout.
+  EXPECT_EQ(2u, overflow_view->top_row_view_for_testing()->children().size());
+  EXPECT_EQ(2u,
+            overflow_view->bottom_row_view_for_testing()->children().size());
+}
+
 }  // namespace ash
diff --git a/build/config/mac/mac_sdk.gni b/build/config/mac/mac_sdk.gni
index cc4e1e2..7025bdf 100644
--- a/build/config/mac/mac_sdk.gni
+++ b/build/config/mac/mac_sdk.gni
@@ -10,9 +10,7 @@
 import("//build/toolchain/siso.gni")
 import("//build/toolchain/toolchain.gni")
 
-assert(
-    current_os == "mac" || current_toolchain == default_toolchain ||
-    (current_os == "ios" && current_toolchain == "${default_toolchain}_blink"))
+assert(current_os == "mac" || current_toolchain == default_toolchain)
 
 declare_args() {
   # The following two variables control the minimum supported version for
diff --git a/chrome/VERSION b/chrome/VERSION
index 620568d8..bf17e07 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=124
 MINOR=0
-BUILD=6331
+BUILD=6333
 PATCH=0
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceDelegate.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceDelegate.java
index e735d5a..c3c4d8a 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceDelegate.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceDelegate.java
@@ -18,8 +18,6 @@
 import org.chromium.base.supplier.OneshotSupplierImpl;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.back_press.BackPressManager;
-import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
-import org.chromium.chrome.browser.compositor.layouts.Layout;
 import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost;
 import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost;
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
@@ -63,37 +61,6 @@
     }
 
     /**
-     * Create the {@link TabSwitcherAndStartSurfaceLayout}.
-     * @param context The current Android's context.
-     * @param updateHost The parent {@link LayoutUpdateHost}.
-     * @param renderHost The parent {@link LayoutRenderHost}.
-     * @param browserControlsStateProvider The {@link BrowserControlsStateProvider} of the top
-     *         controls.
-     * @param startSurface The {@link StartSurface} the layout should own.
-     * @param tabSwitcherScrimAnchor {@link ViewGroup} used by tab switcher layout to show scrim
-     *         when overview is visible.
-     * @param scrimCoordinator {@link ScrimCoordinator} to show/hide scrim.
-     * @return The {@link TabSwitcherAndStartSurfaceLayout}.
-     */
-    public static Layout createTabSwitcherAndStartSurfaceLayout(
-            Context context,
-            LayoutUpdateHost updateHost,
-            LayoutRenderHost renderHost,
-            BrowserControlsStateProvider browserControlsStateProvider,
-            StartSurface startSurface,
-            ViewGroup tabSwitcherScrimAnchor,
-            ScrimCoordinator scrimCoordinator) {
-        return new TabSwitcherAndStartSurfaceLayout(
-                context,
-                updateHost,
-                renderHost,
-                browserControlsStateProvider,
-                startSurface,
-                tabSwitcherScrimAnchor,
-                scrimCoordinator);
-    }
-
-    /**
      * Create the {@link StartSurfaceCoordinator}
      *
      * @param activity The {@link Activity} creates this {@link StartSurface}.
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceHomeLayout.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceHomeLayout.java
index aa1ffbb3..bf11faf 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceHomeLayout.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceHomeLayout.java
@@ -164,10 +164,6 @@
         mBackgroundTabAnimation.start();
     }
 
-    public StartSurface getStartSurfaceForTesting() {
-        return mStartSurface;
-    }
-
     @Override
     public int getLayoutType() {
         return LayoutType.START_SURFACE;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
index 41cd26d..e19a5b1 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -73,6 +73,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
 import org.chromium.chrome.browser.tasks.pseudotab.PseudoTab;
+import org.chromium.chrome.browser.tasks.tab_groups.TabGroupColorUtils;
 import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter;
 import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilterObserver;
 import org.chromium.chrome.browser.tasks.tab_groups.TabGroupTitleUtils;
@@ -1976,7 +1977,20 @@
             List<Tab> relatedTabList = getRelatedTabsForId(pseudoTab.getId());
             if (mMode != TabListMode.LIST) {
                 // For tab group card in grid tab switcher, the favicon is set to be null.
-                mModel.get(modelIndex).model.set(TabProperties.FAVICON_FETCHER, null);
+                // With tab group colors, set the the favicon fetcher to a circle of color.
+                TabFaviconFetcher faviconFetcher = null;
+                if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) {
+                    TabGroupModelFilter filter =
+                            (TabGroupModelFilter) mCurrentTabModelFilterSupplier.get();
+                    int color =
+                            TabGroupColorUtils.getOrCreateTabGroupColor(
+                                    pseudoTab.getRootId(), filter);
+                    faviconFetcher =
+                            mTabListFaviconProvider.getFaviconFromTabGroupColorFetcher(
+                                    color, filter.getTabModel().isIncognito());
+                }
+
+                mModel.get(modelIndex).model.set(TabProperties.FAVICON_FETCHER, faviconFetcher);
                 return;
             }
 
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherAndStartSurfaceLayoutTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherAndStartSurfaceLayoutTest.java
index 4194268..66423c4 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherAndStartSurfaceLayoutTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherAndStartSurfaceLayoutTest.java
@@ -376,6 +376,30 @@
     @Test
     @MediumTest
     @Feature({"RenderTest"})
+    @EnableFeatures(ChromeFeatureList.TAB_GROUP_PARITY_ANDROID)
+    @CommandLineFlags.Add({BASE_PARAMS})
+    public void testRenderGrid_1TabGroup_ColorIcon() throws IOException {
+        final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+        createTabs(cta, false, 2);
+        enterTabSwitcher(cta);
+        verifyTabSwitcherCardCount(cta, 2);
+        // Create a tab group.
+        mergeAllNormalTabsToAGroup(cta);
+        verifyTabSwitcherCardCount(cta, 1);
+        // Hardcode TabGroupColorId.GREY as the tab group color for render testing purposes.
+        Tab tab = cta.getTabModelSelector().getCurrentTab();
+        TabGroupColorUtils.storeTabGroupColor(tab.getRootId(), 0);
+        // Leave and re enter GTS to refetch the favicon.
+        leaveTabSwitcher(cta);
+        enterTabSwitcher(cta);
+        mRenderTestRule.render(
+                cta.findViewById(R.id.tab_list_recycler_view),
+                "1_tab_group_GTS_card_item_color_icon");
+    }
+
+    @Test
+    @MediumTest
+    @Feature({"RenderTest"})
     @DisableFeatures(ChromeFeatureList.TAB_TO_GTS_ANIMATION)
     @CommandLineFlags.Add({BASE_PARAMS})
     @DisableIf.Build(
@@ -1662,6 +1686,21 @@
 
     @Test
     @MediumTest
+    @EnableFeatures({ChromeFeatureList.TAB_GROUP_PARITY_ANDROID})
+    public void testTabGroupColorInTabSwitcher() {
+        final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+        createTabs(cta, false, 2);
+        enterTabSwitcher(cta);
+        verifyTabSwitcherCardCount(cta, 2);
+        // Create a tab group.
+        mergeAllNormalTabsToAGroup(cta);
+        // Verify the color icon exists.
+        onView(allOf(withId(R.id.tab_favicon), withParent(withId(R.id.card_view))))
+                .check(matches(isDisplayed()));
+    }
+
+    @Test
+    @MediumTest
     public void testLongPressTab_entryInTabSwitcher_verifyNoSelectionOccurs() {
         TabUiFeatureUtilities.setTabListEditorLongPressEntryEnabledForTesting(true);
 
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
index 2072fa2..680457ab 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
@@ -195,6 +195,7 @@
     private static final String TAB7_TITLE = "Tab7";
     private static final String NEW_TITLE = "New title";
     private static final String CUSTOMIZED_DIALOG_TITLE1 = "Cool Tabs";
+    private static final String TAB_GROUP_COLORS_FILE_NAME = "tab_group_colors";
     private static final String TAB_GROUP_TITLES_FILE_NAME = "tab_group_titles";
     private static final GURL TAB1_URL = JUnitTestGURLs.URL_1;
     private static final GURL TAB2_URL = JUnitTestGURLs.URL_2;
@@ -204,6 +205,7 @@
     private static final GURL TAB6_URL = JUnitTestGURLs.RED_3;
     private static final GURL TAB7_URL = JUnitTestGURLs.URL_1;
     private static final String NEW_URL = JUnitTestGURLs.EXAMPLE_URL.getSpec();
+    private static final int COLOR_2 = 1;
     private static final int TAB1_ID = 456;
     private static final int TAB2_ID = 789;
     private static final int TAB3_ID = 123;
@@ -382,6 +384,9 @@
         doReturn(mTabFaviconFetcher)
                 .when(mTabListFaviconProvider)
                 .getComposedFaviconImageFetcher(any(), anyBoolean());
+        doReturn(mTabFaviconFetcher)
+                .when(mTabListFaviconProvider)
+                .getFaviconFromTabGroupColorFetcher(anyInt(), anyBoolean());
         doReturn(2).when(mTabGroupModelFilter).getCount();
         doReturn(tabs1).when(mTabGroupModelFilter).getRelatedTabList(TAB1_ID);
         doReturn(tabs2).when(mTabGroupModelFilter).getRelatedTabList(TAB2_ID);
@@ -435,6 +440,11 @@
         ProfileManager.resetForTesting();
     }
 
+    private static SharedPreferences getGroupColorSharedPreferences() {
+        return ContextUtils.getApplicationContext()
+                .getSharedPreferences(TAB_GROUP_COLORS_FILE_NAME, Context.MODE_PRIVATE);
+    }
+
     private static SharedPreferences getGroupTitleSharedPreferences() {
         return ContextUtils.getApplicationContext()
                 .getSharedPreferences(TAB_GROUP_TITLES_FILE_NAME, Context.MODE_PRIVATE);
@@ -2802,6 +2812,28 @@
     }
 
     @Test
+    @EnableFeatures(ChromeFeatureList.TAB_GROUP_PARITY_ANDROID)
+    public void testUpdateFaviconFetcherForGroup_gridModeWithColors() {
+        setUpTabListMediator(TabListMediatorType.TAB_SWITCHER, TabListMode.GRID);
+        mModel.get(0).model.set(TabProperties.FAVICON_FETCHER, null);
+
+        when(mTabModel.isIncognito()).thenReturn(false);
+        // Mock that we have a stored color stored with reference to root ID of tab1.
+        getGroupColorSharedPreferences()
+                .edit()
+                .putInt(String.valueOf(mTab1.getRootId()), COLOR_2)
+                .apply();
+
+        // Test a group of three.
+        Tab tab3 = prepareTab(TAB3_ID, TAB3_TITLE, TAB3_URL);
+        List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2, tab3));
+        createTabGroup(tabs, TAB1_ID, TAB_GROUP_ID);
+        mTabObserver.onFaviconUpdated(mTab1, mFaviconBitmap, mFaviconUrl);
+        verify(mTabListFaviconProvider).getFaviconFromTabGroupColorFetcher(COLOR_2, false);
+        assertNotNull(mModel.get(0).model.get(TabProperties.FAVICON_FETCHER));
+    }
+
+    @Test
     public void testUpdateFaviconFetcherForGroup() {
         setUpTabListMediator(TabListMediatorType.TAB_SWITCHER, TabListMode.LIST);
         mModel.get(0).model.set(TabProperties.FAVICON_FETCHER, null);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
index e2863a16..8778a90 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
@@ -32,7 +32,6 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
-import org.chromium.chrome.browser.tasks.ReturnToChromeUtil;
 import org.chromium.chrome.browser.tasks.tab_management.TabManagementDelegate;
 import org.chromium.chrome.browser.tasks.tab_management.TabManagementDelegateProvider;
 import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
@@ -62,27 +61,15 @@
     /** A {@link Layout} that should be used when the user is swiping sideways on the toolbar. */
     protected ToolbarSwipeLayout mToolbarSwipeLayout;
 
-    /**
-     * A {@link Layout} that should be used when the user is in the tab switcher or start surface
-     * when the refactor flag isn't enabled.
-     */
-    protected Layout mOverviewLayout;
-
-    /**
-     * A {@link Layout} that should be used when the user is in the start surface when the refactor
-     * flag is enabled.
-     */
+    /** A {@link Layout} that should be used when the user is in the start surface. */
     protected Layout mStartSurfaceHomeLayout;
 
-    /**
-     * A {@link Layout} that should be used when the user is in the tab switcher when the refactor
-     * flag is enabled.
-     */
+    /** A {@link Layout} that should be used when the user is in the tab switcher. */
     protected Layout mTabSwitcherLayout;
 
     /**
-     * A {@link Layout} that should be used when the user is in the tab switcher when the refactor
-     * flag and hub flags are enabled.
+     * A {@link Layout} that should be used when the user is in the tab switcher when the hub flag
+     * is enabled.
      */
     protected Layout mHubLayout;
 
@@ -133,12 +120,10 @@
      *
      * @param host A {@link LayoutManagerHost} instance.
      * @param contentContainer A {@link ViewGroup} for Android views to be bound to.
-     * @param startSurfaceSupplier Supplier for an interface to talk to the Grid Tab Switcher.
-     *     Creates overviewLayout with this surface if this is has value. If not, {@link
-     *     #showLayout(int, boolean)} will create overviewLayout.
-     * @param tabSwitcherSupplier Supplier for an interface to talk to the Grid Tab Switcher when
-     *     Start surface refactor is enabled. Used to create overviewLayout if it has value,
-     *     otherwise will use the accessibility overview layout.
+     * @param startSurfaceSupplier Supplier for an interface to talk to the Start surface. Creates
+     *     StartSurfaceHomeLayout if it has value.
+     * @param tabSwitcherSupplier Supplier for an interface to talk to the Grid Tab Switcher. Used
+     *     to create TabSwitcherLayout if it has value.
      * @param browserControlsStateProvider The {@link BrowserControlsStateProvider} for top
      *     controls.
      * @param tabContentManagerSupplier Supplier of the {@link TabContentManager} instance.
@@ -174,21 +159,10 @@
         mCreateTabSwitcherOrStartSurfaceCallable = delayedTabSwitcherOrStartSurfaceCallable;
         mHubLayoutDependencyHolder = hubLayoutDependencyHolder;
 
-        Context context = host.getContext();
-        if (ReturnToChromeUtil.isStartSurfaceRefactorEnabled(context)) {
-            if (mStartSurfaceSupplier.hasValue() || mTabSwitcherSupplier.hasValue()) {
-                createLayoutsForStartSurfaceAndTabSwitcher(
-                        mStartSurfaceSupplier.get(),
-                        mTabSwitcherSupplier.get(),
-                        browserControlsStateProvider,
-                        scrimCoordinator,
-                        tabSwitcherScrimAnchor,
-                        hubLayoutDependencyHolder);
-            }
-        } else if (mStartSurfaceSupplier.hasValue()) {
+        if (mStartSurfaceSupplier.hasValue() || mTabSwitcherSupplier.hasValue()) {
             createLayoutsForStartSurfaceAndTabSwitcher(
                     mStartSurfaceSupplier.get(),
-                    /* tabSwitcher= */ null,
+                    mTabSwitcherSupplier.get(),
                     browserControlsStateProvider,
                     scrimCoordinator,
                     tabSwitcherScrimAnchor,
@@ -197,14 +171,12 @@
     }
 
     /**
-     * Creates {@link org.chromium.chrome.features.start_surface.TabSwitcherAndStartSurfaceLayout}
-     * or ({@link org.chromium.chrome.features.start_surface.StartSurfaceHomeLayout} AND {@link
+     * Creates {@link org.chromium.chrome.features.start_surface.StartSurfaceHomeLayout} AND {@link
      * org.chromium.chrome.features.tasks.tab_management.TabSwitcherLayout}).
      *
-     * @param startSurface An interface to talk to the Grid Tab Switcher when Start surface refactor
-     *     is disabled.
-     * @param tabSwitcher An interface to talk to the GridTabSwitcher when Start surface refactor is
-     *     enabled and DeferTabSwitcherLayoutCreation is disabled.
+     * @param startSurface An interface to talk to the Start surface.
+     * @param tabSwitcher An interface to talk to the GridTabSwitcher when
+     *     DeferTabSwitcherLayoutCreation is disabled.
      * @param browserControlsStateProvider The {@link BrowserControlsStateProvider} for top
      *     controls.
      * @param scrimCoordinator scrim coordinator for GTS
@@ -218,37 +190,23 @@
             ScrimCoordinator scrimCoordinator,
             ViewGroup tabSwitcherScrimAnchor,
             HubLayoutDependencyHolder hubLayoutDependencyHolder) {
-        assert mOverviewLayout == null
-                && mTabSwitcherLayout == null
-                && mStartSurfaceHomeLayout == null
-                && mHubLayout == null;
-        boolean isRefactorEnabled =
-                ReturnToChromeUtil.isStartSurfaceRefactorEnabled(mHost.getContext());
+        assert mTabSwitcherLayout == null && mStartSurfaceHomeLayout == null && mHubLayout == null;
 
-        if (isRefactorEnabled) {
-            // TabSwitcherLayout creation is deferred until it is first shown.
-            if (!ChromeFeatureList.sDeferTabSwitcherLayoutCreation.isEnabled()) {
-                if (HubFieldTrial.isHubEnabled()) {
-                    createHubLayout(hubLayoutDependencyHolder);
-                } else {
-                    assert tabSwitcher != null;
-                    createTabSwitcherLayout(
-                            tabSwitcher,
-                            browserControlsStateProvider,
-                            scrimCoordinator,
-                            tabSwitcherScrimAnchor);
-                }
+        // TabSwitcherLayout creation is deferred until it is first shown.
+        if (!ChromeFeatureList.sDeferTabSwitcherLayoutCreation.isEnabled()) {
+            if (HubFieldTrial.isHubEnabled()) {
+                createHubLayout(hubLayoutDependencyHolder);
+            } else {
+                assert tabSwitcher != null;
+                createTabSwitcherLayout(
+                        tabSwitcher,
+                        browserControlsStateProvider,
+                        scrimCoordinator,
+                        tabSwitcherScrimAnchor);
             }
-            if (startSurface != null) {
-                createStartSurfaceHomeLayout(startSurface);
-            }
-        } else {
-            assert startSurface != null;
-            createTabSwitcherAndStartSurfaceLayout(
-                    startSurface,
-                    browserControlsStateProvider,
-                    scrimCoordinator,
-                    tabSwitcherScrimAnchor);
+        }
+        if (startSurface != null) {
+            createStartSurfaceHomeLayout(startSurface);
         }
     }
 
@@ -266,9 +224,6 @@
             ScrimCoordinator scrimCoordinator,
             ViewGroup tabSwitcherScrimAnchor) {
         assert mTabSwitcherLayout == null;
-        boolean isRefactorEnabled =
-                ReturnToChromeUtil.isStartSurfaceRefactorEnabled(mHost.getContext());
-        assert isRefactorEnabled;
 
         Context context = mHost.getContext();
         LayoutRenderHost renderHost = mHost.getLayoutRenderHost();
@@ -334,14 +289,11 @@
 
     /**
      * Creates {@link org.chromium.chrome.features.start_surface.StartSurfaceHomeLayout}.
-     * @param startSurface An interface to talk to the Grid Tab Switcher when Start surface refactor
-     *         is disabled.
+     *
+     * @param startSurface An interface to talk to the Start surface.
      */
     protected void createStartSurfaceHomeLayout(@NonNull StartSurface startSurface) {
         assert mStartSurfaceHomeLayout == null;
-        boolean isRefactorEnabled =
-                ReturnToChromeUtil.isStartSurfaceRefactorEnabled(mHost.getContext());
-        assert isRefactorEnabled;
 
         Context context = mHost.getContext();
         LayoutRenderHost renderHost = mHost.getLayoutRenderHost();
@@ -361,63 +313,6 @@
         }
     }
 
-    /**
-     * Creates {@link org.chromium.chrome.features.start_surface.TabSwitcherAndStartSurfaceLayout}
-     * @param startSurface An interface to talk to the Grid Tab Switcher when Start surface refactor
-     *         is disabled.
-     * @param browserControlsStateProvider The {@link BrowserControlsStateProvider} for top
-     *         controls.
-     * @param scrimCoordinator scrim coordinator for GTS
-     * @param tabSwitcherScrimAnchor scrim anchor view for GTS
-     */
-    protected void createTabSwitcherAndStartSurfaceLayout(
-            @NonNull StartSurface startSurface,
-            BrowserControlsStateProvider browserControlsStateProvider,
-            ScrimCoordinator scrimCoordinator,
-            ViewGroup tabSwitcherScrimAnchor) {
-        assert mOverviewLayout == null;
-        boolean isRefactorEnabled =
-                ReturnToChromeUtil.isStartSurfaceRefactorEnabled(mHost.getContext());
-        assert !isRefactorEnabled;
-
-        Context context = mHost.getContext();
-        LayoutRenderHost renderHost = mHost.getLayoutRenderHost();
-
-        mOverviewLayout =
-                StartSurfaceDelegate.createTabSwitcherAndStartSurfaceLayout(
-                        context,
-                        this,
-                        renderHost,
-                        browserControlsStateProvider,
-                        startSurface,
-                        tabSwitcherScrimAnchor,
-                        scrimCoordinator);
-
-        if (DeviceFormFactor.isNonMultiDisplayContextOnTablet(mHost.getContext())) {
-            mTabSwitcherFocusLayoutStateObserver =
-                    new LayoutStateObserver() {
-                        @Override
-                        public void onFinishedShowing(int layoutType) {
-                            if (layoutType == LayoutType.TAB_SWITCHER) {
-                                startSurface.getGridTabListDelegate().requestFocusOnCurrentTab();
-                            }
-                        }
-                    };
-            addObserver(mTabSwitcherFocusLayoutStateObserver);
-        }
-
-        if (mTabContentManagerSupplier.hasValue()) {
-            mOverviewLayout.setTabContentManager(mTabContentManagerSupplier.get());
-        }
-
-        if (getTabModelSelector() != null) {
-            mOverviewLayout.setTabModelSelector(getTabModelSelector());
-        }
-        if (mFinishNativeInitialization) {
-            mOverviewLayout.onFinishNativeInitialization();
-        }
-    }
-
     /** Returns a list of virtual views representing compositor rendered views. */
     @Override
     public void getVirtualViews(List<VirtualView> views) {
@@ -467,11 +362,6 @@
         TabContentManager content = mTabContentManagerSupplier.get();
         mToolbarSwipeLayout.setTabModelSelector(selector);
         mToolbarSwipeLayout.setTabContentManager(content);
-        if (mOverviewLayout != null) {
-            mOverviewLayout.setTabModelSelector(selector);
-            mOverviewLayout.setTabContentManager(content);
-            mOverviewLayout.onFinishNativeInitialization();
-        }
         if (mTabSwitcherLayout != null) {
             mTabSwitcherLayout.setTabModelSelector(selector);
             mTabSwitcherLayout.setTabContentManager(content);
@@ -493,7 +383,6 @@
     @Override
     public void showLayout(int layoutType, boolean animate) {
         if (layoutType == LayoutType.TAB_SWITCHER
-                && mOverviewLayout == null
                 && mTabSwitcherLayout == null
                 && mHubLayout == null) {
             initTabSwitcher();
@@ -502,22 +391,17 @@
     }
 
     /**
-     * For lazy initialization of {@link mTabSwitcherLayout} or {@link mOverviewLayout}.
-     * This always happens the first time the tab switcher is shown on tablets or if Start Surface
-     * refactor is enabled for phones.
+     * For lazy initialization of {@link mTabSwitcherLayout} This always happens the first time the
+     * tab switcher is shown on tablets and phones.
      */
     private void initTabSwitcher() {
-        boolean isRefactorEnabled =
-                ReturnToChromeUtil.isStartSurfaceRefactorEnabled(mHost.getContext());
-
         // Implicitly guarded by sDeferTabSwitcherLayoutCreation as mTabSwitcherSupplier will
         // have a value already if the feature is disabled.
-        if (mStartSurfaceSupplier.hasValue()
-                && (!isRefactorEnabled || mTabSwitcherSupplier.hasValue())) {
+        if (mStartSurfaceSupplier.hasValue() && mTabSwitcherSupplier.hasValue()) {
             return;
         }
 
-        if (isRefactorEnabled && HubFieldTrial.isHubEnabled()) {
+        if (HubFieldTrial.isHubEnabled()) {
             if (mHubLayout == null) {
                 createHubLayout(mHubLayoutDependencyHolder);
             }
@@ -528,7 +412,6 @@
         try {
             final ViewGroup containerView = mCreateTabSwitcherOrStartSurfaceCallable.call();
 
-            if (isRefactorEnabled) {
                 final TabSwitcher tabSwitcher = mTabSwitcherSupplier.get();
                 assert tabSwitcher != null;
                 createTabSwitcherLayout(
@@ -536,15 +419,6 @@
                         mHost.getBrowserControlsManager(),
                         mScrimCoordinator,
                         containerView);
-            } else {
-                final StartSurface startSurface = mStartSurfaceSupplier.get();
-                assert startSurface != null;
-                createTabSwitcherAndStartSurfaceLayout(
-                        startSurface,
-                        mHost.getBrowserControlsManager(),
-                        mScrimCoordinator,
-                        containerView);
-            }
 
             if (DeviceFormFactor.isNonMultiDisplayContextOnTablet(mHost.getContext())) {
                 mThemeColorObserver = new ThemeColorObserverImpl(containerView);
@@ -559,9 +433,6 @@
     @Override
     public void setTabModelSelector(TabModelSelector selector) {
         super.setTabModelSelector(selector);
-        if (mOverviewLayout != null) {
-            mOverviewLayout.setTabModelSelector(selector);
-        }
         if (mTabSwitcherLayout != null) {
             mTabSwitcherLayout.setTabModelSelector(selector);
         }
@@ -592,10 +463,6 @@
             mTabSwitcherFocusLayoutStateObserver = null;
         }
 
-        if (mOverviewLayout != null) {
-            mOverviewLayout.destroy();
-            mOverviewLayout = null;
-        }
         if (mTabSwitcherLayout != null) {
             mTabSwitcherLayout.destroy();
             mTabSwitcherLayout = null;
@@ -620,7 +487,7 @@
 
     @Override
     protected Layout getLayoutForType(@LayoutType int layoutType) {
-        Layout layout;
+        Layout layout = null;
         if (layoutType == LayoutType.TOOLBAR_SWIPE) {
             layout = mToolbarSwipeLayout;
         } else if (layoutType == LayoutType.TAB_SWITCHER) {
@@ -628,8 +495,6 @@
                 layout = mHubLayout;
             } else if (mTabSwitcherLayout != null) {
                 layout = mTabSwitcherLayout;
-            } else {
-                layout = mOverviewLayout;
             }
         } else if (layoutType == LayoutType.START_SURFACE) {
             layout = mStartSurfaceHomeLayout;
@@ -669,12 +534,6 @@
         super.onTabsAllClosing(incognito);
     }
 
-    /** Returns the overview layout {@link Layout} managed by this class. */
-    @VisibleForTesting
-    public Layout getOverviewLayout() {
-        return mOverviewLayout;
-    }
-
     /** Initializes TabSwitcherLayout without needing to open the Tab Switcher. */
     public void initTabSwitcherLayoutForTesting() {
         initTabSwitcher();
@@ -682,7 +541,7 @@
 
     /**
      * Returns the grid tab switcher layout {@link Layout} managed by this class. This should be
-     * non-null when the Start surface refactor is enabled if init has finished.
+     * non-null if init has finished.
      */
     public Layout getTabSwitcherLayoutForTesting() {
         if (mTabSwitcherLayout != null) return mTabSwitcherLayout;
@@ -835,14 +694,11 @@
 
         /** Returns whether or not we are ready to show the GTS layout. */
         private boolean isTabSwitcherReady() {
-            // On Tablets, or with Start Surface Refactor, attempting to show the GTS while it's
-            // null will trigger its creation.
-            return mOverviewLayout != null
-                    || mTabSwitcherLayout != null
+            // Attempting to show the GTS while it's null will trigger its creation.
+            return mTabSwitcherLayout != null
                     || mHubLayout != null
                     || DeviceFormFactor.isNonMultiDisplayContextOnTablet(mHost.getContext())
-                    || (ReturnToChromeUtil.isStartSurfaceRefactorEnabled(mHost.getContext())
-                            && ChromeFeatureList.sDeferTabSwitcherLayoutCreation.isEnabled());
+                    || ChromeFeatureList.sDeferTabSwitcherLayoutCreation.isEnabled();
         }
     }
 
@@ -870,9 +726,6 @@
         assert mTabContentManager == null;
         mTabContentManager = tabContentManager;
         mTabContentManager.addThumbnailChangeListener(mThumbnailChangeListener);
-        if (mOverviewLayout != null) {
-            mOverviewLayout.setTabContentManager(mTabContentManager);
-        }
         if (mTabSwitcherLayout != null) {
             mTabSwitcherLayout.setTabContentManager(mTabContentManager);
         }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
index f2b44a4..0f852eee 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
@@ -9,9 +9,6 @@
 import static androidx.test.espresso.matcher.ViewMatchers.assertThat;
 
 import static org.hamcrest.Matchers.is;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_LOW_END_DEVICE;
@@ -36,11 +33,8 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.mockito.stubbing.Answer;
 
 import org.chromium.base.Log;
 import org.chromium.base.MathUtils;
@@ -76,13 +70,11 @@
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
-import org.chromium.chrome.browser.tasks.ReturnToChromeUtil;
 import org.chromium.chrome.browser.tasks.tab_management.TabListCoordinator;
 import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
 import org.chromium.chrome.browser.theme.TopUiThemeColorProvider;
 import org.chromium.chrome.browser.util.ChromeAccessibilityUtil;
 import org.chromium.chrome.features.start_surface.StartSurface;
-import org.chromium.chrome.features.start_surface.StartSurface.TabSwitcherViewObserver;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.R;
@@ -117,18 +109,9 @@
     @Mock private TabSwitcher.Controller mTabSwitcherController;
     @Mock private BrowserControlsStateProvider mBrowserControlsStateProvider;
 
-    @Captor private ArgumentCaptor<TabSwitcherViewObserver> mTabSwitcherViewObserverArgumentCaptor;
-
-    @Captor
-    private ArgumentCaptor<TabSwitcher.TabSwitcherViewObserver>
-            mRefactorTabSwitcherViewObserverArgumentCaptor;
-
-    private long mLastDownTime;
-
     private TabModelSelector mTabModelSelector;
     private Supplier<StartSurface> mStartSurfaceSupplier;
     private OneshotSupplierImpl<TabSwitcher> mTabSwitcherSupplier;
-    private boolean mIsStartSurfaceRefactorEnabled;
     private LayoutManagerChrome mManager;
     private LayoutManagerChromePhone mManagerPhone;
 
@@ -209,13 +192,9 @@
 
         mDpToPx = context.getResources().getDisplayMetrics().density;
 
-        if (mIsStartSurfaceRefactorEnabled) {
             when(mTabSwitcher.getController()).thenReturn(mTabSwitcherController);
             when(mTabSwitcher.getTabListDelegate()).thenReturn(mTabListDelegate);
             when(mTabSwitcher.getTabGridDialogVisibilitySupplier()).thenReturn(() -> false);
-        } else {
-            when(mStartSurface.getGridTabListDelegate()).thenReturn(mTabListDelegate);
-        }
         when(mStartSurface.getTabGridDialogVisibilitySupplier()).thenReturn(() -> false);
 
         mTabModelSelector =
@@ -263,8 +242,6 @@
                         },
                         mHubLayoutDependencyHolder);
 
-        setUpLayouts();
-
         tabContentManagerSupplier.set(tabContentManager);
         mManager = mManagerPhone;
         CompositorAnimationHandler.setTestingMode(true);
@@ -272,35 +249,6 @@
         initializeMotionEvent();
     }
 
-    private void setUpLayouts() {
-        if (!mIsStartSurfaceRefactorEnabled) {
-            verify(mStartSurface)
-                    .addTabSwitcherViewObserver(mTabSwitcherViewObserverArgumentCaptor.capture());
-            doAnswer(
-                            (Answer<Void>)
-                                    invocation -> {
-                                        mTabSwitcherViewObserverArgumentCaptor
-                                                .getValue()
-                                                .finishedShowing();
-                                        simulateTime(mManager, 1000);
-                                        return null;
-                                    })
-                    .when(mStartSurface)
-                    .showOverview(anyBoolean());
-
-            doAnswer(
-                            (Answer<Void>)
-                                    invocation -> {
-                                        mTabSwitcherViewObserverArgumentCaptor
-                                                .getValue()
-                                                .finishedHiding();
-                                        return null;
-                                    })
-                    .when(mStartSurface)
-                    .hideTabSwitcherView(anyBoolean());
-        }
-    }
-
     @Test
     @SmallTest
     @Feature({"Android-TabSwitcher"})
@@ -724,13 +672,6 @@
                     ChromeBrowserInitializer.getInstance().handleSynchronousStartup();
                 });
 
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> {
-                    mIsStartSurfaceRefactorEnabled =
-                            ReturnToChromeUtil.isStartSurfaceRefactorEnabled(
-                                    ApplicationProvider.getApplicationContext());
-                });
-
         mStartSurfaceSupplier = () -> mStartSurface;
     }
 
@@ -747,22 +688,13 @@
                     Layout activeLayout = getActiveLayout();
                     Assert.assertEquals(LayoutType.TAB_SWITCHER, activeLayout.getLayoutType());
                     int tabListMode;
-                    if (mIsStartSurfaceRefactorEnabled) {
-                        tabListMode =
-                                mActivityTestRule
-                                        .getActivity()
-                                        .getTabSwitcherSupplierForTesting()
-                                        .get()
-                                        .getTabListDelegate()
-                                        .getListModeForTesting();
-                    } else {
-                        tabListMode =
-                                mActivityTestRule
-                                        .getActivity()
-                                        .getStartSurface()
-                                        .getGridTabListDelegate()
-                                        .getListModeForTesting();
-                    }
+                    tabListMode =
+                            mActivityTestRule
+                                    .getActivity()
+                                    .getTabSwitcherSupplierForTesting()
+                                    .get()
+                                    .getTabListDelegate()
+                                    .getListModeForTesting();
                     Assert.assertEquals(expectedTabListMode, tabListMode);
                 });
     }
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 2edfce6..66d55c0 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -4642,10 +4642,6 @@
     {"crostini-reset-lxd-db", flag_descriptions::kCrostiniResetLxdDbName,
      flag_descriptions::kCrostiniResetLxdDbDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(ash::features::kCrostiniResetLxdDb)},
-    {"terminal-alternative-emulator",
-     flag_descriptions::kTerminalAlternativeEmulatorName,
-     flag_descriptions::kTerminalAlternativeEmulatorDescription, kOsCrOS,
-     FEATURE_VALUE_TYPE(ash::features::kTerminalAlternativeEmulator)},
     {"terminal-dev", flag_descriptions::kTerminalDevName,
      flag_descriptions::kTerminalDevDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(ash::features::kTerminalDev)},
diff --git a/chrome/browser/apps/link_capturing/apps_intent_picker_delegate.h b/chrome/browser/apps/link_capturing/apps_intent_picker_delegate.h
index 5954242..ac9c42a5 100644
--- a/chrome/browser/apps/link_capturing/apps_intent_picker_delegate.h
+++ b/chrome/browser/apps/link_capturing/apps_intent_picker_delegate.h
@@ -41,7 +41,8 @@
   virtual void RecordIntentPickerIconEvent(
       apps::IntentPickerIconEvent event) = 0;
   virtual bool ShouldLaunchAppDirectly(const GURL& url,
-                                       const std::string& app_name) = 0;
+                                       const std::string& app_name,
+                                       PickerEntryType entry_type) = 0;
   virtual void RecordOutputMetrics(PickerEntryType entry_type,
                                    IntentPickerCloseReason close_reason,
                                    bool should_persist,
diff --git a/chrome/browser/apps/link_capturing/chromeos_apps_intent_picker_delegate.cc b/chrome/browser/apps/link_capturing/chromeos_apps_intent_picker_delegate.cc
index 8ff0dd5f..f118b0ea 100644
--- a/chrome/browser/apps/link_capturing/chromeos_apps_intent_picker_delegate.cc
+++ b/chrome/browser/apps/link_capturing/chromeos_apps_intent_picker_delegate.cc
@@ -149,7 +149,8 @@
 
 bool ChromeOsAppsIntentPickerDelegate::ShouldLaunchAppDirectly(
     const GURL& url,
-    const std::string& app_name) {
+    const std::string& app_name,
+    PickerEntryType) {
   // If there is only a single available app, immediately launch it if
   // ShouldShowLinkCapturingUX() is enabled and the app is preferred for this
   // link.
diff --git a/chrome/browser/apps/link_capturing/chromeos_apps_intent_picker_delegate.h b/chrome/browser/apps/link_capturing/chromeos_apps_intent_picker_delegate.h
index 045dd9b3..88ad247 100644
--- a/chrome/browser/apps/link_capturing/chromeos_apps_intent_picker_delegate.h
+++ b/chrome/browser/apps/link_capturing/chromeos_apps_intent_picker_delegate.h
@@ -42,7 +42,8 @@
                          IconLoadedCallback icon_loaded_callback) override;
   void RecordIntentPickerIconEvent(apps::IntentPickerIconEvent event) override;
   bool ShouldLaunchAppDirectly(const GURL& url,
-                               const std::string& app_name) override;
+                               const std::string& app_name,
+                               PickerEntryType) override;
   void RecordOutputMetrics(PickerEntryType entry_type,
                            IntentPickerCloseReason close_reason,
                            bool should_persist,
diff --git a/chrome/browser/apps/link_capturing/mac_intent_picker_helpers.mm b/chrome/browser/apps/link_capturing/mac_intent_picker_helpers.mm
index d6f9de79..a78b1c8 100644
--- a/chrome/browser/apps/link_capturing/mac_intent_picker_helpers.mm
+++ b/chrome/browser/apps/link_capturing/mac_intent_picker_helpers.mm
@@ -29,6 +29,16 @@
   return *value;
 }
 
+NSImage* CreateRedIconForTesting() {
+  return [NSImage imageWithSize:NSMakeSize(16, 16)
+                        flipped:NO
+                 drawingHandler:^(NSRect rect) {
+                   [NSColor.redColor set];
+                   NSRectFill(rect);
+                   return YES;
+                 }];
+}
+
 IntentPickerAppInfo AppInfoForAppUrl(NSURL* app_url) {
   NSString* app_name = nil;
   if (![app_url getResourceValue:&app_name
@@ -37,6 +47,7 @@
     // This shouldn't happen but just in case.
     app_name = app_url.lastPathComponent;
   }
+
   NSImage* app_icon = nil;
   if (![app_url getResourceValue:&app_icon
                           forKey:NSURLEffectiveIconKey
@@ -44,12 +55,15 @@
     // This shouldn't happen but just in case.
     app_icon = [NSImage imageNamed:NSImageNameApplicationIcon];
   }
+  if (UseFakeAppForTesting()) {            // IN-TEST
+    app_icon = CreateRedIconForTesting();  // IN-TEST
+  }
+
   app_icon.size = NSMakeSize(16, 16);
 
-  return IntentPickerAppInfo{PickerEntryType::kMacOs,
-                             ui::ImageModel::FromImage(gfx::Image(app_icon)),
-                             base::SysNSStringToUTF8([app_url path]),
-                             base::SysNSStringToUTF8(app_name)};
+  return IntentPickerAppInfo{
+      PickerEntryType::kMacOs, ui::ImageModel::FromImage(gfx::Image(app_icon)),
+      base::SysNSStringToUTF8(app_url.path), base::SysNSStringToUTF8(app_name)};
 }
 
 }  // namespace
diff --git a/chrome/browser/apps/link_capturing/web_apps_intent_picker_delegate.cc b/chrome/browser/apps/link_capturing/web_apps_intent_picker_delegate.cc
index d5445b1a..986f09d 100644
--- a/chrome/browser/apps/link_capturing/web_apps_intent_picker_delegate.cc
+++ b/chrome/browser/apps/link_capturing/web_apps_intent_picker_delegate.cc
@@ -34,21 +34,6 @@
 
 namespace apps {
 
-namespace {
-
-#if BUILDFLAG(IS_MAC)
-std::vector<apps::IntentPickerAppInfo> CombinePossibleMacAppWithOtherApps(
-    std::vector<apps::IntentPickerAppInfo> apps,
-    std::optional<apps::IntentPickerAppInfo> mac_app) {
-  if (mac_app) {
-    apps.emplace_back(std::move(mac_app.value()));
-  }
-  return apps;
-}
-#endif  // BUILDFLAG(IS_MAC)
-
-}  // namespace
-
 WebAppsIntentPickerDelegate::WebAppsIntentPickerDelegate(Profile* profile)
     : profile_(*profile),
       provider_(*web_app::WebAppProvider::GetForWebApps(profile)) {}
@@ -75,8 +60,10 @@
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE, {base::TaskPriority::USER_BLOCKING, base::MayBlock()},
       base::BindOnce(&FindMacAppForUrl, url),
-      base::BindOnce(&CombinePossibleMacAppWithOtherApps, std::move(apps))
-          .Then(std::move(apps_callback)));
+      base::BindOnce(
+          &WebAppsIntentPickerDelegate::CacheMacAppInfoAndPostFinalCallback,
+          weak_ptr_factory.GetWeakPtr(), std::move(apps_callback),
+          std::move(apps)));
 #else
   base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
       FROM_HERE, base::BindOnce(std::move(apps_callback), std::move(apps)));
@@ -93,36 +80,54 @@
     const std::string& app_id,
     int size_in_dep,
     IconLoadedCallback icon_loaded_callback) {
-  web_app::WebAppIconManager& icon_manager = provider_->icon_manager();
-  // First, iterate over all icons with the given order of purposes, and verify
-  // if there exists an icon that can be loaded. The order of purposes helps
-  // ensure we first look for ANY and MASKABLE icons before going for
-  // MONOCHROME.
-  std::vector<web_app::IconPurpose> ordered_purpose = {
-      web_app::IconPurpose::MASKABLE, web_app::IconPurpose::ANY,
-      web_app::IconPurpose::MONOCHROME};
-  auto size_and_purpose =
-      icon_manager.FindIconMatchBigger(app_id, ordered_purpose, size_in_dep);
-  if (!size_and_purpose.has_value()) {
-    std::move(icon_loaded_callback).Run(ui::ImageModel());
-    return;
+  CHECK(entry_type == PickerEntryType::kWeb ||
+        entry_type == PickerEntryType::kMacOs);
+
+  if (entry_type == PickerEntryType::kWeb) {
+    web_app::WebAppIconManager& icon_manager = provider_->icon_manager();
+    // First, iterate over all icons with the given order of purposes, and
+    // verify if there exists an icon that can be loaded. The order of purposes
+    // helps ensure we first look for ANY and MASKABLE icons before going for
+    // MONOCHROME.
+    std::vector<web_app::IconPurpose> ordered_purpose = {
+        web_app::IconPurpose::MASKABLE, web_app::IconPurpose::ANY,
+        web_app::IconPurpose::MONOCHROME};
+    auto size_and_purpose =
+        icon_manager.FindIconMatchBigger(app_id, ordered_purpose, size_in_dep);
+    if (!size_and_purpose.has_value()) {
+      std::move(icon_loaded_callback).Run(ui::ImageModel());
+      return;
+    }
+
+    web_app::IconPurpose purpose_to_get = size_and_purpose.value().purpose;
+    auto transform_bitmaps_to_icon_metadata = base::BindOnce(
+        [](std::map<web_app::SquareSizePx, SkBitmap> icons) -> ui::ImageModel {
+          bool is_valid_icon = !icons.empty();
+          if (!is_valid_icon) {
+            return ui::ImageModel();
+          }
+
+          CHECK_EQ(icons.size(), 1u);
+          return ui::ImageModel::FromImageSkia(
+              gfx::ImageSkia::CreateFrom1xBitmap(icons.begin()->second));
+        });
+    icon_manager.ReadIconAndResize(app_id, purpose_to_get, size_in_dep,
+                                   std::move(transform_bitmaps_to_icon_metadata)
+                                       .Then(std::move(icon_loaded_callback)));
+  } else if (entry_type == apps::PickerEntryType::kMacOs) {
+#if BUILDFLAG(IS_MAC)
+    // Read from the cached app information if an app with universal links were
+    // found.
+    ui::ImageModel mac_app_icon;
+    if (mac_app_info_.has_value()) {
+      CHECK_EQ(mac_app_info_->launch_name, app_id);
+      mac_app_icon = mac_app_info_->icon_model;
+    }
+    std::move(icon_loaded_callback).Run(mac_app_icon);
+#else
+    NOTREACHED();
+#endif  // BUILDFLAG(IS_MAC)
   }
-
-  web_app::IconPurpose purpose_to_get = size_and_purpose.value().purpose;
-  auto transform_bitmaps_to_icon_metadata = base::BindOnce(
-      [](std::map<web_app::SquareSizePx, SkBitmap> icons) -> ui::ImageModel {
-        bool is_valid_icon = !icons.empty();
-        if (!is_valid_icon) {
-          return ui::ImageModel();
-        }
-
-        CHECK_EQ(icons.size(), 1u);
-        return ui::ImageModel::FromImageSkia(
-            gfx::ImageSkia::CreateFrom1xBitmap(icons.begin()->second));
-      });
-  icon_manager.ReadIconAndResize(app_id, purpose_to_get, size_in_dep,
-                                 std::move(transform_bitmaps_to_icon_metadata)
-                                     .Then(std::move(icon_loaded_callback)));
 }
 
 void WebAppsIntentPickerDelegate::RecordIntentPickerIconEvent(
@@ -136,12 +141,23 @@
 
 bool WebAppsIntentPickerDelegate::ShouldLaunchAppDirectly(
     const GURL& url,
-    const std::string& app_id) {
-  // Launch app directly only if |url| is in the scope of |app_id|.
-  // TODO(b/294079334): Use `IsUrlInAppExtendedScope` to support scope
-  // extensions for user link capturing on desktop platforms.
-  return features::ShouldShowLinkCapturingUX() &&
-         provider_->registrar_unsafe().IsUrlInAppScope(url, app_id);
+    const std::string& app_id,
+    PickerEntryType entry_type) {
+  CHECK(entry_type == PickerEntryType::kWeb ||
+        entry_type == PickerEntryType::kMacOs);
+  if (!features::ShouldShowLinkCapturingUX()) {
+    return false;
+  }
+  if (entry_type == PickerEntryType::kWeb) {
+    // Launch app directly only if |url| is in the scope of |app_id|.
+    // TODO(b/294079334): Use `IsUrlInAppExtendedScope` to support scope
+    // extensions for user link capturing on desktop platforms.
+    return provider_->registrar_unsafe().IsUrlInAppScope(url, app_id);
+  }
+
+  // This is only reached on MacOS if there is one app available and the picker
+  // entry type is kMacOS, so it's fine to launch directly.
+  return true;
 }
 
 void WebAppsIntentPickerDelegate::RecordOutputMetrics(
@@ -207,4 +223,18 @@
   }
 }
 
+#if BUILDFLAG(IS_MAC)
+void WebAppsIntentPickerDelegate::CacheMacAppInfoAndPostFinalCallback(
+    IntentPickerAppsCallback apps_callback,
+    std::vector<IntentPickerAppInfo> apps,
+    MacAppInfo mac_app_info) {
+  mac_app_info_ = mac_app_info;
+  if (mac_app_info_.has_value()) {
+    apps.emplace_back(mac_app_info_.value());
+  }
+  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(apps_callback), std::move(apps)));
+}
+#endif  // BUILDFLAG(IS_MAC)
+
 }  // namespace apps
diff --git a/chrome/browser/apps/link_capturing/web_apps_intent_picker_delegate.h b/chrome/browser/apps/link_capturing/web_apps_intent_picker_delegate.h
index e45a48e..cd01cc12 100644
--- a/chrome/browser/apps/link_capturing/web_apps_intent_picker_delegate.h
+++ b/chrome/browser/apps/link_capturing/web_apps_intent_picker_delegate.h
@@ -27,6 +27,10 @@
 
 namespace apps {
 
+#if BUILDFLAG(IS_MAC)
+using MacAppInfo = std::optional<IntentPickerAppInfo>;
+#endif  // BUILDFLAG(IS_MAC)
+
 class WebAppsIntentPickerDelegate : public AppsIntentPickerDelegate {
  public:
   explicit WebAppsIntentPickerDelegate(Profile* profile);
@@ -46,7 +50,8 @@
                          IconLoadedCallback icon_loaded_callback) override;
   void RecordIntentPickerIconEvent(apps::IntentPickerIconEvent event) override;
   bool ShouldLaunchAppDirectly(const GURL& url,
-                               const std::string& app_id) override;
+                               const std::string& app_id,
+                               PickerEntryType entry_type) override;
   void RecordOutputMetrics(PickerEntryType entry_type,
                            IntentPickerCloseReason close_reason,
                            bool should_persist,
@@ -59,8 +64,20 @@
                  PickerEntryType entry_type) override;
 
  private:
+#if BUILDFLAG(IS_MAC)
+  // If any app with universal links are found, cache that for reuse later (like
+  // getting icons) instead of going through the universal links API again.
+  void CacheMacAppInfoAndPostFinalCallback(
+      IntentPickerAppsCallback apps_callback,
+      std::vector<IntentPickerAppInfo> apps,
+      MacAppInfo mac_app_info);
+#endif  // BUILDFLAG(IS_MAC)
+
   raw_ref<Profile> profile_;
   raw_ref<web_app::WebAppProvider> provider_;
+#if BUILDFLAG(IS_MAC)
+  MacAppInfo mac_app_info_;
+#endif  // BUILDFLAG(IS_MAC)
   base::WeakPtrFactory<WebAppsIntentPickerDelegate> weak_ptr_factory{this};
 };
 
diff --git a/chrome/browser/ash/account_manager/account_manager_ui_impl.cc b/chrome/browser/ash/account_manager/account_manager_ui_impl.cc
index 5e03446..8e6ffdd4 100644
--- a/chrome/browser/ash/account_manager/account_manager_ui_impl.cc
+++ b/chrome/browser/ash/account_manager/account_manager_ui_impl.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ash/account_manager/account_manager_ui_impl.h"
 
+#include "ash/constants/ash_features.h"
 #include "ash/webui/settings/public/constants/routes.mojom.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -35,7 +36,9 @@
 void AccountManagerUIImpl::ShowManageAccountsSettings() {
   chrome::SettingsWindowManager::GetInstance()->ShowOSSettings(
       ProfileManager::GetActiveUserProfile(),
-      chromeos::settings::mojom::kMyAccountsSubpagePath);
+      ash::features::IsOsSettingsRevampWayfindingEnabled()
+          ? chromeos::settings::mojom::kPeopleSectionPath
+          : chromeos::settings::mojom::kMyAccountsSubpagePath);
 }
 
 }  // namespace ash
diff --git a/chrome/browser/ash/login/signin/signin_error_notifier.cc b/chrome/browser/ash/login/signin/signin_error_notifier.cc
index b6e065d..a3c05ca 100644
--- a/chrome/browser/ash/login/signin/signin_error_notifier.cc
+++ b/chrome/browser/ash/login/signin/signin_error_notifier.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <string>
 
+#include "ash/constants/ash_features.h"
 #include "ash/constants/notifier_catalogs.h"
 #include "ash/public/cpp/notification_utils.h"
 #include "ash/webui/settings/public/constants/routes.mojom.h"
@@ -366,7 +367,9 @@
 void SigninErrorNotifier::HandleSecondaryAccountReauthNotificationClick(
     std::optional<int> button_index) {
   chrome::SettingsWindowManager::GetInstance()->ShowOSSettings(
-      profile_, chromeos::settings::mojom::kMyAccountsSubpagePath);
+      profile_, ash::features::IsOsSettingsRevampWayfindingEnabled()
+                    ? chromeos::settings::mojom::kPeopleSectionPath
+                    : chromeos::settings::mojom::kMyAccountsSubpagePath);
 }
 
 }  // namespace ash
diff --git a/chrome/browser/ash/login/users/chrome_user_manager_impl.cc b/chrome/browser/ash/login/users/chrome_user_manager_impl.cc
index dce52db..276c2b1 100644
--- a/chrome/browser/ash/login/users/chrome_user_manager_impl.cc
+++ b/chrome/browser/ash/login/users/chrome_user_manager_impl.cc
@@ -66,7 +66,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/ui/ash/wallpaper_controller_client_impl.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_switches.h"
@@ -731,10 +730,6 @@
           *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
               IDR_LOGIN_DEFAULT_USER)),
       user_manager::User::USER_IMAGE_INVALID, false);
-
-  // Initializes wallpaper after active_user_ is set.
-  WallpaperControllerClientImpl::Get()->ShowUserWallpaper(
-      user_manager::GuestAccountId());
 }
 
 void ChromeUserManagerImpl::RegularUserLoggedIn(
@@ -745,8 +740,6 @@
 
   MaybeStartBluetoothLogging(account_id);
 
-  WallpaperControllerClientImpl::Get()->ShowUserWallpaper(account_id);
-
   // Make sure that new data is persisted to Local State.
   GetLocalState()->CommitPendingWrite();
 }
@@ -756,7 +749,6 @@
     const user_manager::UserType user_type) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   UserManagerBase::RegularUserLoggedInAsEphemeral(account_id, user_type);
-  WallpaperControllerClientImpl::Get()->ShowUserWallpaper(account_id);
 }
 
 bool ChromeUserManagerImpl::IsEphemeralAccountIdByPolicy(
@@ -774,13 +766,6 @@
     user_manager::User* user) {
   SetIsCurrentUserNew(true);
   active_user_ = user;
-
-  // For public account, it's possible that the user-policy controlled wallpaper
-  // was fetched/cleared at the login screen (while for a regular user it was
-  // always fetched/cleared inside a user session), in the case the user-policy
-  // controlled wallpaper was fetched/cleared but not updated in the login
-  // screen, we need to update the wallpaper after the public user logged in.
-  WallpaperControllerClientImpl::Get()->ShowUserWallpaper(user->GetAccountId());
 }
 
 void ChromeUserManagerImpl::KioskAppLoggedIn(user_manager::User* user) {
@@ -794,7 +779,6 @@
       user_manager::User::USER_IMAGE_INVALID, false);
 
   const AccountId& kiosk_app_account_id = user->GetAccountId();
-  WallpaperControllerClientImpl::Get()->ShowUserWallpaper(kiosk_app_account_id);
 
   // TODO(bartfab): Add KioskAppUsers to the users_ list and keep metadata like
   // the kiosk_app_id in these objects, removing the need to re-parse the
diff --git a/chrome/browser/ash/login/users/user_manager_unittest.cc b/chrome/browser/ash/login/users/user_manager_unittest.cc
index 0086d78..3e6b4f420 100644
--- a/chrome/browser/ash/login/users/user_manager_unittest.cc
+++ b/chrome/browser/ash/login/users/user_manager_unittest.cc
@@ -160,11 +160,6 @@
     ResetUserManager();
 
     ConciergeClient::InitializeFake(/*fake_cicerone_client=*/nullptr);
-
-    wallpaper_controller_client_ = std::make_unique<
-        WallpaperControllerClientImpl>(
-        std::make_unique<wallpaper_handlers::TestWallpaperFetcherDelegate>());
-    wallpaper_controller_client_->InitForTesting(&test_wallpaper_controller_);
   }
 
   void TearDown() override {
@@ -201,10 +196,17 @@
   void ResetUserManager() {
     // Initialize the UserManager singleton to a fresh ChromeUserManagerImpl
     // instance.
+    // WallpaperControllerClient needs to be recreated, too, because
+    // it subscribes UserManager singleton.
+    wallpaper_controller_client_.reset();
     user_image_manager_registry_.reset();
     user_manager_.Reset(ChromeUserManagerImpl::CreateChromeUserManager());
     user_image_manager_registry_ =
         std::make_unique<ash::UserImageManagerRegistry>(user_manager_.Get());
+    wallpaper_controller_client_ = std::make_unique<
+        WallpaperControllerClientImpl>(
+        std::make_unique<wallpaper_handlers::TestWallpaperFetcherDelegate>());
+    wallpaper_controller_client_->InitForTesting(&test_wallpaper_controller_);
 
     // ChromeUserManagerImpl ctor posts a task to reload policies.
     // Also ensure that all existing ongoing user manager tasks are completed.
diff --git a/chrome/browser/browser_process_platform_part_chromeos_browsertest.cc b/chrome/browser/browser_process_platform_part_chromeos_browsertest.cc
index 9f8cf009a..8b9ac43 100644
--- a/chrome/browser/browser_process_platform_part_chromeos_browsertest.cc
+++ b/chrome/browser/browser_process_platform_part_chromeos_browsertest.cc
@@ -104,7 +104,8 @@
   SessionStartupPref::SetStartupPref(profile, startup_pref);
 
   // Open a new window.
-  chrome::NewEmptyWindow(profile, /*should_trigger_session_restore=*/true);
+  ui_test_utils::OpenNewEmptyWindowAndWaitUntilSetAsLastActive(
+      profile, /*should_trigger_session_restore=*/true);
 
   // Startup URLs should not have been applied to the browser window.
   ASSERT_EQ(1u, chrome::GetBrowserCount(profile));
@@ -152,7 +153,7 @@
   SessionStartupPref::SetStartupPref(profile, startup_pref);
 
   // Request a new browser window.
-  chrome::NewEmptyWindow(profile);
+  ui_test_utils::OpenNewEmptyWindowAndWaitUntilSetAsLastActive(profile);
 
   ASSERT_EQ(1u, chrome::GetBrowserCount(profile));
 
@@ -172,7 +173,8 @@
 
   // If there are existing open browsers opening a new browser should not
   // trigger a restore or open another window with startup URLs.
-  chrome::NewEmptyWindow(profile, /*should_trigger_session_restore=*/true);
+  ui_test_utils::OpenNewEmptyWindowAndWaitUntilSetAsLastActive(
+      profile, /*should_trigger_session_restore=*/true);
   ASSERT_EQ(2u, chrome::GetBrowserCount(profile));
   auto* new_browser = chrome::FindLastActiveWithProfile(profile);
   EXPECT_NO_FATAL_FAILURE(WaitForLoadStopForBrowser(new_browser));
@@ -258,11 +260,9 @@
 
   // If there are existing open browsers opening a new browser should not
   // trigger a restore or open another window with last URLs.
-  ui_test_utils::BrowserChangeObserver restored_browser_observer(
-      nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded);
-  chrome::NewEmptyWindow(profile, /*should_trigger_session_restore=*/true);
-  auto* new_browser = restored_browser_observer.Wait();
-  ui_test_utils::WaitForBrowserSetLastActive(new_browser);
+  auto* new_browser =
+      ui_test_utils::OpenNewEmptyWindowAndWaitUntilSetAsLastActive(
+          profile, /*should_trigger_session_restore=*/true);
   ASSERT_EQ(3u, chrome::GetBrowserCount(profile));
   EXPECT_EQ(new_browser, chrome::FindLastActiveWithProfile(profile));
   EXPECT_NO_FATAL_FAILURE(WaitForLoadStopForBrowser(new_browser));
@@ -373,10 +373,7 @@
 
     // If there are existing open browsers opening a new browser should not
     // trigger a restore or open another window with startup URLs.
-    ui_test_utils::BrowserChangeObserver new_browser_observer(
-        nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded);
-    chrome::NewEmptyWindow(profile_urls);
-    ui_test_utils::WaitForBrowserSetLastActive(new_browser_observer.Wait());
+    ui_test_utils::OpenNewEmptyWindowAndWaitUntilSetAsLastActive(profile_urls);
     ASSERT_EQ(2u, chrome::GetBrowserCount(profile_urls));
     auto* last_active_browser = chrome::FindLastActiveWithProfile(profile_urls);
     EXPECT_NO_FATAL_FAILURE(WaitForLoadStopForBrowser(last_active_browser));
@@ -432,10 +429,8 @@
 
     // If there are existing open browsers opening a new browser should not
     // trigger a restore or open another window with last URLs.
-    ui_test_utils::BrowserChangeObserver new_browser_observer(
-        nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded);
-    chrome::NewEmptyWindow(profile_last_and_urls);
-    ui_test_utils::WaitForBrowserSetLastActive(new_browser_observer.Wait());
+    ui_test_utils::OpenNewEmptyWindowAndWaitUntilSetAsLastActive(
+        profile_last_and_urls);
     ASSERT_EQ(3u, chrome::GetBrowserCount(profile_last_and_urls));
     auto* last_active_browser =
         chrome::FindLastActiveWithProfile(profile_last_and_urls);
diff --git a/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api.cc b/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api.cc
index e2e756b..5d919707 100644
--- a/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api.cc
+++ b/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api.cc
@@ -8,6 +8,7 @@
 
 #include "base/memory/weak_ptr.h"
 #include "base/numerics/safe_conversions.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/pdf/pdf_pref_names.h"
 #include "chrome/browser/pdf/pdf_viewer_stream_manager.h"
@@ -30,6 +31,8 @@
 namespace SetPdfPluginAttributes =
     api::pdf_viewer_private::SetPdfPluginAttributes;
 
+namespace SetPdfDocumentTitle = api::pdf_viewer_private::SetPdfDocumentTitle;
+
 // Check if the current URL is allowed based on a list of allowlisted domains.
 bool IsUrlAllowedToEmbedLocalFiles(
     const GURL& current_url,
@@ -135,6 +138,31 @@
   return RespondNow(WithArguments(value));
 }
 
+PdfViewerPrivateSetPdfDocumentTitleFunction::
+    PdfViewerPrivateSetPdfDocumentTitleFunction() = default;
+
+PdfViewerPrivateSetPdfDocumentTitleFunction::
+    ~PdfViewerPrivateSetPdfDocumentTitleFunction() = default;
+
+// This function is only called for full-page PDFs.
+ExtensionFunction::ResponseAction
+PdfViewerPrivateSetPdfDocumentTitleFunction::Run() {
+  content::WebContents* web_contents = GetSenderWebContents();
+  if (!web_contents) {
+    return RespondNow(Error("Could not find a valid web contents."));
+  }
+
+  std::optional<SetPdfDocumentTitle::Params> params =
+      SetPdfDocumentTitle::Params::Create(args());
+  EXTENSION_FUNCTION_VALIDATE(params);
+
+  web_contents->UpdateTitleForEntry(
+      web_contents->GetController().GetLastCommittedEntry(),
+      base::UTF8ToUTF16(params->title));
+
+  return RespondNow(NoArguments());
+}
+
 PdfViewerPrivateSetPdfOcrPrefFunction::PdfViewerPrivateSetPdfOcrPrefFunction() =
     default;
 
diff --git a/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api.h b/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api.h
index e6d2694a0..b31a929 100644
--- a/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api.h
+++ b/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api.h
@@ -64,6 +64,24 @@
   ResponseAction Run() override;
 };
 
+class PdfViewerPrivateSetPdfDocumentTitleFunction : public ExtensionFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("pdfViewerPrivate.setPdfDocumentTitle",
+                             PDFVIEWERPRIVATE_SETPDFDOCUMENTTITLE)
+
+  PdfViewerPrivateSetPdfDocumentTitleFunction();
+  PdfViewerPrivateSetPdfDocumentTitleFunction(
+      const PdfViewerPrivateSetPdfDocumentTitleFunction&) = delete;
+  PdfViewerPrivateSetPdfDocumentTitleFunction& operator=(
+      const PdfViewerPrivateSetPdfDocumentTitleFunction&) = delete;
+
+ protected:
+  ~PdfViewerPrivateSetPdfDocumentTitleFunction() override;
+
+  // Override from ExtensionFunction:
+  ResponseAction Run() override;
+};
+
 class PdfViewerPrivateSetPdfOcrPrefFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("pdfViewerPrivate.setPdfOcrPref",
diff --git a/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api_unittest.cc b/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api_unittest.cc
index 36f43e00..870e855 100644
--- a/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api_unittest.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/pdf/pdf_test_util.h"
 #include "chrome/browser/pdf/pdf_viewer_stream_manager.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "content/public/browser/navigation_entry.h"
 #include "content/public/test/navigation_simulator.h"
 #include "extensions/browser/api_test_utils.h"
 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
@@ -138,6 +139,23 @@
   EXPECT_THAT(*result_dict, base::test::IsJson(kExpectedStreamInfo));
 }
 
+// Succeed in setting tab title.
+TEST_F(PdfViewerPrivateApiUnitTest, SetPdfDocumentTitle) {
+  auto function =
+      base::MakeRefCounted<PdfViewerPrivateSetPdfDocumentTitleFunction>();
+  function->SetRenderFrameHost(extension_host());
+
+  ASSERT_TRUE(api_test_utils::RunFunction(function.get(),
+                                          "[\"PDF title test\"]", profile()));
+
+  const std::u16string kExpectedTitle = u"PDF title test";
+  EXPECT_EQ(kExpectedTitle, web_contents()
+                                ->GetController()
+                                .GetLastCommittedEntry()
+                                ->GetTitleForDisplay());
+  EXPECT_EQ(kExpectedTitle, web_contents()->GetTitle());
+}
+
 // Getting the stream info should fail if there isn't an embedder host.
 TEST_F(PdfViewerPrivateApiUnitTest, SetPdfPluginAttributesNoEmbedderHost) {
   auto function =
diff --git a/chrome/browser/extensions/api/terminal/terminal_private_api.cc b/chrome/browser/extensions/api/terminal/terminal_private_api.cc
index 466e82df..9797db0 100644
--- a/chrome/browser/extensions/api/terminal/terminal_private_api.cc
+++ b/chrome/browser/extensions/api/terminal/terminal_private_api.cc
@@ -753,9 +753,6 @@
 
 ExtensionFunction::ResponseAction TerminalPrivateGetOSInfoFunction::Run() {
   base::Value::Dict info;
-  info.Set("alternative_emulator",
-           base::FeatureList::IsEnabled(
-               ash::features::kTerminalAlternativeEmulator));
   info.Set("tast", extensions::ExtensionRegistry::Get(browser_context())
                        ->enabled_extensions()
                        .Contains(extension_misc::kGuestModeTestExtensionId));
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 4f275c66..b5587362 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -7790,13 +7790,8 @@
     "expiry_milestone": 135
   },
   {
-    "name": "terminal-alternative-emulator",
-    "owners": [ "lxj@chromium.org", "joelhockey@chromium.org", "//chrome/browser/ash/guest_os/OWNERS" ],
-    "expiry_milestone": 122
-  },
-  {
     "name": "terminal-dev",
-    "owners": [ "joelhockey@chromium.org", "lxj@google.com", "//chrome/browser/ash/guest_os/OWNERS" ],
+    "owners": [ "joelhockey@chromium.org", "//chrome/browser/ash/guest_os/OWNERS" ],
     // This flag is used by CrOS Terminal developers for testing SSH on devices
     // with valid machine certs and should not be removed.  Only works in dev
     // and canary channels.
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index cbb0132..c30cdba 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -7147,11 +7147,6 @@
     "Customize keyboard keys "
     "page.";
 
-const char kTerminalAlternativeEmulatorName[] = "Terminal alternative emulator";
-const char kTerminalAlternativeEmulatorDescription[] =
-    "Enable the alternative emulator for the Terminal app. You will also get "
-    "an option in Terminal settings to change the default emulator.";
-
 const char kTerminalDevName[] = "Terminal dev";
 const char kTerminalDevDescription[] =
     "Enables Terminal System App to load from Downloads for developer testing. "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index bdeb74c3..6f89dd1 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -4120,9 +4120,6 @@
 extern const char kSupportF11AndF12ShortcutsName[];
 extern const char kSupportF11AndF12ShortcutsDescription[];
 
-extern const char kTerminalAlternativeEmulatorName[];
-extern const char kTerminalAlternativeEmulatorDescription[];
-
 extern const char kTerminalDevName[];
 extern const char kTerminalDevDescription[];
 
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index 33e3b86..58a0e4c 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -223,53 +223,49 @@
             guest_view->GetGuestMainFrame());
 }
 
-// This test verifies that when a PDF is loaded, that (i) the embedder
+// For GuestView PDF, this test verifies that when a PDF is loaded, the embedder
 // WebContents' html consists of a single <embed> tag with appropriate
-// properties, and (ii) that the guest WebContents finishes loading and
-// has the correct URL for the PDF extension.
+// properties. It also verifies that the guest WebContents finishes loading. For
+// OOPIF PDF, this test verifies that extension frame finished loading. For
+// both, the WebContents and the extension frame should have the correct URL for
+// the PDF extension.
 // TODO(wjmaclean): Are there any attributes we can/should test with respect to
 // the extension's loaded html?
-IN_PROC_BROWSER_TEST_P(PDFExtensionTest, PdfExtensionLoadedInGuest) {
-  // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF.
-  if (UseOopif()) {
-    GTEST_SKIP();
-  }
-
-  // Load test HTML, and verify the text area has focus.
+IN_PROC_BROWSER_TEST_P(PDFExtensionTest, PdfExtensionLoaded) {
+  // Load test PDF.
   const GURL main_url(embedded_test_server()->GetURL("/pdf/test.pdf"));
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
-  auto* primary_main_frame = GetActiveWebContents()->GetPrimaryMainFrame();
-
-  // Verify the pdf has loaded.
-  auto* guest_view = GetGuestViewManager()->WaitForSingleGuestViewCreated();
-  ASSERT_TRUE(guest_view);
-  EXPECT_NE(primary_main_frame, guest_view->GetGuestMainFrame());
-  TestMimeHandlerViewGuest::WaitForGuestLoadStartThenStop(guest_view);
+  content::RenderFrameHost* extension_host = LoadPdfGetExtensionHost(main_url);
+  ASSERT_TRUE(extension_host);
+  auto* web_contents = GetActiveWebContents();
+  auto* primary_main_frame = web_contents->GetPrimaryMainFrame();
 
   // Verify we loaded the extension.
   const GURL extension_url(
       "chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/index.html");
-  EXPECT_EQ(extension_url,
-            guest_view->GetGuestMainFrame()->GetLastCommittedURL());
+  EXPECT_EQ(extension_url, extension_host->GetLastCommittedURL());
   EXPECT_EQ(main_url, primary_main_frame->GetLastCommittedURL());
 
-  // Make sure the embedder has the correct html boilerplate.
-  EXPECT_EQ(
-      1, content::EvalJs(primary_main_frame, "document.body.children.length;")
-             .ExtractInt());
-  EXPECT_EQ("EMBED", content::EvalJs(primary_main_frame,
-                                     "document.body.firstChild.tagName;")
-                         .ExtractString());
-  EXPECT_EQ("application/pdf", content::EvalJs(primary_main_frame,
-                                               "document.body.firstChild.type;")
-                                   .ExtractString());
-  EXPECT_EQ("about:blank",
-            content::EvalJs(primary_main_frame, "document.body.firstChild.src;")
-                .ExtractString());
-  EXPECT_TRUE(
-      content::EvalJs(primary_main_frame,
-                      "document.body.firstChild.hasAttribute('internalid');")
-          .ExtractBool());
+  // Make sure the embedder has the correct html boilerplate. GuestView PDF
+  // only, as OOPIF PDF hides the html using shadow DOM.
+  if (!UseOopif()) {
+    EXPECT_EQ(
+        1, content::EvalJs(primary_main_frame, "document.body.children.length;")
+               .ExtractInt());
+    EXPECT_EQ("EMBED", content::EvalJs(primary_main_frame,
+                                       "document.body.firstChild.tagName;")
+                           .ExtractString());
+    EXPECT_EQ(
+        "application/pdf",
+        content::EvalJs(primary_main_frame, "document.body.firstChild.type;")
+            .ExtractString());
+    EXPECT_EQ("about:blank", content::EvalJs(primary_main_frame,
+                                             "document.body.firstChild.src;")
+                                 .ExtractString());
+    EXPECT_TRUE(
+        content::EvalJs(primary_main_frame,
+                        "document.body.firstChild.hasAttribute('internalid');")
+            .ExtractBool());
+  }
 }
 
 // Helper class to allow pausing the asynchronous attachment of an inner
@@ -1017,11 +1013,6 @@
 
 // This test ensures that titles are set properly for PDFs without /Title.
 IN_PROC_BROWSER_TEST_P(PDFExtensionTest, TabTitleWithNoTitle) {
-  // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF.
-  if (UseOopif()) {
-    GTEST_SKIP();
-  }
-
   ASSERT_TRUE(LoadPdf(embedded_test_server()->GetURL("/pdf/test.pdf")));
 
   const std::u16string kExpectedTitle = u"test.pdf";
@@ -1034,11 +1025,6 @@
 
 // This test ensures that titles are set properly for PDFs with /Title.
 IN_PROC_BROWSER_TEST_P(PDFExtensionTest, TabTitleWithTitle) {
-  // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF.
-  if (UseOopif()) {
-    GTEST_SKIP();
-  }
-
   ASSERT_TRUE(LoadPdf(embedded_test_server()->GetURL("/pdf/test-title.pdf")));
 
   const std::u16string kExpectedTitle = u"PDF title test";
@@ -1072,11 +1058,6 @@
 // This test ensures that tab titles are set properly for embedded PDFs.
 // PDF /Title should be ignored for embedded PDFs.
 IN_PROC_BROWSER_TEST_P(PDFExtensionTest, TabTitleWithEmbeddedPdf) {
-  // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF.
-  if (UseOopif()) {
-    GTEST_SKIP();
-  }
-
   // Load page with embedded PDF and make sure it succeeds.
   ASSERT_TRUE(LoadPdfInFirstChild(
       embedded_test_server()->GetURL("/pdf/pdf_embed.html")));
diff --git a/chrome/browser/preloading/preview/COMMON_METADATA b/chrome/browser/preloading/preview/COMMON_METADATA
deleted file mode 100644
index d9e17ee..0000000
--- a/chrome/browser/preloading/preview/COMMON_METADATA
+++ /dev/null
@@ -1 +0,0 @@
-team_email: "loading-dev@chromium.org"
diff --git a/chrome/browser/preloading/preview/DIR_METADATA b/chrome/browser/preloading/preview/DIR_METADATA
deleted file mode 100644
index ae58a56..0000000
--- a/chrome/browser/preloading/preview/DIR_METADATA
+++ /dev/null
@@ -1 +0,0 @@
-mixins: "//chrome/browser/preloading/preview/COMMON_METADATA"
diff --git a/chrome/browser/preloading/preview/preview_tab.cc b/chrome/browser/preloading/preview/preview_tab.cc
index 9e73154..7c498c72 100644
--- a/chrome/browser/preloading/preview/preview_tab.cc
+++ b/chrome/browser/preloading/preview/preview_tab.cc
@@ -68,10 +68,8 @@
       return;
     }
 
-    // This doesn't triggered for long press trigger.
-    //
-    // TODO(b:320386573): Cancel preview when focus lost.
-    if (!is_event_for_preview_window && event->type() == ui::ET_MOUSE_PRESSED) {
+    if (!is_event_for_preview_window &&
+        event->type() == ui::ET_MOUSE_RELEASED) {
       event->SetHandled();
       preview_manager_->Cancel(content::PreviewCancelReason::Build(
           content::PreviewFinalStatus::kCancelledByWindowClose));
diff --git a/chrome/browser/resources/accessibility/chromevox_helper/BUILD.gn b/chrome/browser/resources/accessibility/chromevox_helper/BUILD.gn
index 77aa512..e75001d 100644
--- a/chrome/browser/resources/accessibility/chromevox_helper/BUILD.gn
+++ b/chrome/browser/resources/accessibility/chromevox_helper/BUILD.gn
@@ -20,6 +20,7 @@
   ]
   out_dir = tsc_output_dir
   definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/runtime.d.ts",
     "//tools/typescript/definitions/scripting.d.ts",
     "//tools/typescript/definitions/storage.d.ts",
diff --git a/chrome/browser/resources/ash/settings/os_settings.gni b/chrome/browser/resources/ash/settings/os_settings.gni
index 9af11b0..dbc6bbc 100644
--- a/chrome/browser/resources/ash/settings/os_settings.gni
+++ b/chrome/browser/resources/ash/settings/os_settings.gni
@@ -5,6 +5,7 @@
 ts_definition_files = [
   "//tools/typescript/definitions/bluetooth.d.ts",
   "//tools/typescript/definitions/bluetooth_private.d.ts",
+  "//tools/typescript/definitions/chrome_event.d.ts",
   "//tools/typescript/definitions/chrome_send.d.ts",
   "//tools/typescript/definitions/input_method_private.d.ts",
   "//tools/typescript/definitions/language_settings_private.d.ts",
diff --git a/chrome/browser/resources/bookmarks/BUILD.gn b/chrome/browser/resources/bookmarks/BUILD.gn
index b0e0a78..562af135 100644
--- a/chrome/browser/resources/bookmarks/BUILD.gn
+++ b/chrome/browser/resources/bookmarks/BUILD.gn
@@ -61,7 +61,6 @@
 
   ts_deps = [
     "//third_party/polymer/v3_0:library",
-    "//tools/typescript/definitions:library",
     "//ui/webui/resources/cr_components/managed_footnote:build_ts",
     "//ui/webui/resources/cr_elements:build_ts",
     "//ui/webui/resources/js:build_ts",
diff --git a/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn
index cba7797..d5343c9 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn
+++ b/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn
@@ -89,6 +89,7 @@
   "../definitions/storage_mv2.d.ts",
   "../definitions/tabs.d.ts",
   "../definitions/tts.d.ts",
+  "//tools/typescript/definitions/chrome_event.d.ts",
   "//tools/typescript/definitions/windows.d.ts",
 ]
 
@@ -98,8 +99,6 @@
   composite = true
   in_files = ts_modules + js_sources
 
-  deps = [ "//tools/typescript/definitions:library" ]
-
   tsconfig_base = "../tsconfig.base.json"
 }
 
diff --git a/chrome/browser/resources/chromeos/add_supervision/BUILD.gn b/chrome/browser/resources/chromeos/add_supervision/BUILD.gn
index b9eb131..56bd7e4 100644
--- a/chrome/browser/resources/chromeos/add_supervision/BUILD.gn
+++ b/chrome/browser/resources/chromeos/add_supervision/BUILD.gn
@@ -23,6 +23,7 @@
   ts_definitions = [
     "//tools/typescript/definitions/webview_tag.d.ts",
     "//tools/typescript/definitions/web_request.d.ts",
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/context_menus.d.ts",
     "//tools/typescript/definitions/tabs.d.ts",
     "//tools/typescript/definitions/extension_types.d.ts",
diff --git a/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn b/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn
index 1e831be..bc5adcde 100644
--- a/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn
+++ b/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn
@@ -16,13 +16,14 @@
   ts_definitions = [
     "//tools/typescript/definitions/bluetooth.d.ts",
     "//tools/typescript/definitions/bluetooth_private.d.ts",
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/chrome_send.d.ts",
   ]
 
   ts_deps = [
     "//ash/webui/common/resources:build_ts",
+    "//ash/webui/common/resources/cr_elements:build_ts",
     "//third_party/polymer/v3_0:library",
     "//ui/webui/resources/cr_components/color_change_listener:build_ts",
-    "//ash/webui/common/resources/cr_elements:build_ts",
   ]
 }
diff --git a/chrome/browser/resources/chromeos/edu_coexistence/BUILD.gn b/chrome/browser/resources/chromeos/edu_coexistence/BUILD.gn
index 91d7306..fd9ee60 100644
--- a/chrome/browser/resources/chromeos/edu_coexistence/BUILD.gn
+++ b/chrome/browser/resources/chromeos/edu_coexistence/BUILD.gn
@@ -29,6 +29,7 @@
     "//tools/typescript/definitions/webview_tag.d.ts",
     "//tools/typescript/definitions/web_request.d.ts",
     "//tools/typescript/definitions/extension_types.d.ts",
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/context_menus.d.ts",
     "//tools/typescript/definitions/tabs.d.ts",
     "//tools/typescript/definitions/chrome_send.d.ts",
diff --git a/chrome/browser/resources/chromeos/login/BUILD.gn b/chrome/browser/resources/chromeos/login/BUILD.gn
index 491f5d21..71da95b4 100644
--- a/chrome/browser/resources/chromeos/login/BUILD.gn
+++ b/chrome/browser/resources/chromeos/login/BUILD.gn
@@ -225,6 +225,7 @@
     "//chrome/browser/resources/chromeos/accessibility/definitions/tts.d.ts",
     "//chrome/browser/resources/gaia_auth_host/saml_password_attributes.d.ts",
     "//chrome/browser/resources/gaia_auth_host/authenticator.d.ts",
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/chrome_send.d.ts",
     "//tools/typescript/definitions/context_menus.d.ts",
     "//tools/typescript/definitions/extension_types.d.ts",
diff --git a/chrome/browser/resources/chromeos/network_ui/BUILD.gn b/chrome/browser/resources/chromeos/network_ui/BUILD.gn
index 6a70abf7..9cfc9b4 100644
--- a/chrome/browser/resources/chromeos/network_ui/BUILD.gn
+++ b/chrome/browser/resources/chromeos/network_ui/BUILD.gn
@@ -20,6 +20,7 @@
 
   ts_definitions = [
     "//chrome/browser/resources/chromeos/network_ui/third_party/uPlot.iife.min.d.ts",
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/chrome_send.d.ts",
     "//tools/typescript/definitions/networking_private.d.ts",
     "//tools/typescript/definitions/runtime.d.ts",
diff --git a/chrome/browser/resources/chromeos/parent_access/BUILD.gn b/chrome/browser/resources/chromeos/parent_access/BUILD.gn
index 199b6358..dfa28818 100644
--- a/chrome/browser/resources/chromeos/parent_access/BUILD.gn
+++ b/chrome/browser/resources/chromeos/parent_access/BUILD.gn
@@ -48,6 +48,7 @@
   ts_definitions = [
     "//tools/typescript/definitions/webview_tag.d.ts",
     "//tools/typescript/definitions/web_request.d.ts",
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/context_menus.d.ts",
     "//tools/typescript/definitions/tabs.d.ts",
     "//tools/typescript/definitions/extension_types.d.ts",
diff --git a/chrome/browser/resources/extensions/BUILD.gn b/chrome/browser/resources/extensions/BUILD.gn
index 7d41f38..745d46ea 100644
--- a/chrome/browser/resources/extensions/BUILD.gn
+++ b/chrome/browser/resources/extensions/BUILD.gn
@@ -95,7 +95,6 @@
 
   ts_deps = [
     "//third_party/polymer/v3_0:library",
-    "//tools/typescript/definitions:library",
     "//ui/webui/resources/cr_components/managed_footnote:build_ts",
     "//ui/webui/resources/cr_elements:build_ts",
     "//ui/webui/resources/js:build_ts",
diff --git a/chrome/browser/resources/pdf/pdf_viewer.ts b/chrome/browser/resources/pdf/pdf_viewer.ts
index 903be62..a89b1aa 100644
--- a/chrome/browser/resources/pdf/pdf_viewer.ts
+++ b/chrome/browser/resources/pdf/pdf_viewer.ts
@@ -44,6 +44,7 @@
 import {getTemplate} from './pdf_viewer.html.js';
 import type {KeyEventData} from './pdf_viewer_base.js';
 import {PdfViewerBaseElement} from './pdf_viewer_base.js';
+import {PdfViewerPrivateProxyImpl} from './pdf_viewer_private_proxy.js';
 import type {DestinationMessageData, DocumentDimensionsMessageData} from './pdf_viewer_utils.js';
 import {hasCtrlModifier, hasCtrlModifierOnly, shouldIgnoreKeyEvents} from './pdf_viewer_utils.js';
 
@@ -899,7 +900,18 @@
   private setDocumentMetadata_(metadata: DocumentMetadata) {
     this.documentMetadata_ = metadata;
     this.title_ = this.documentMetadata_.title || this.fileName_;
-    document.title = this.title_;
+
+    // Tab title is updated only when document.title is called in a
+    // top-level document (`main_frame` of `WebContents`). For OOPIF PDF viewer,
+    // the current document is the child of a top-level document, hence using a
+    // private API to set the tab title.
+    // NOTE: Title should only be set for full-page PDFs.
+    if (this.pdfOopifEnabled && !this.embedded_) {
+      PdfViewerPrivateProxyImpl.getInstance().setPdfDocumentTitle(this.title_);
+    } else {
+      document.title = this.title_;
+    }
+
     this.canSerializeDocument_ = this.documentMetadata_.canSerializeDocument;
   }
 
diff --git a/chrome/browser/resources/pdf/pdf_viewer_private_proxy.ts b/chrome/browser/resources/pdf/pdf_viewer_private_proxy.ts
index d1f929f..f0b4f29 100644
--- a/chrome/browser/resources/pdf/pdf_viewer_private_proxy.ts
+++ b/chrome/browser/resources/pdf/pdf_viewer_private_proxy.ts
@@ -10,6 +10,7 @@
 // `chrome/browser/resources/pdf/navigator.ts`.
 interface PdfViewerPrivateProxy {
   isPdfOcrAlwaysActive(): Promise<boolean>;
+  setPdfDocumentTitle(title: string): void;
   setPdfOcrPref(value: boolean): Promise<boolean>;
   addPdfOcrPrefChangedListener(listener: PdfOcrPrefCallback): void;
   removePdfOcrPrefChangedListener(listener: PdfOcrPrefCallback): void;
@@ -22,6 +23,10 @@
     });
   }
 
+  setPdfDocumentTitle(title: string): void {
+    chrome.pdfViewerPrivate.setPdfDocumentTitle(title);
+  }
+
   setPdfOcrPref(value: boolean): Promise<boolean> {
     return new Promise(resolve => {
       chrome.pdfViewerPrivate.setPdfOcrPref(value, result => resolve(result));
diff --git a/chrome/browser/resources/print_preview/BUILD.gn b/chrome/browser/resources/print_preview/BUILD.gn
index 2e4a32e..faf7f64 100644
--- a/chrome/browser/resources/print_preview/BUILD.gn
+++ b/chrome/browser/resources/print_preview/BUILD.gn
@@ -115,6 +115,7 @@
 
   ts_composite = true
   ts_definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/chrome_send.d.ts",
     "//tools/typescript/definitions/mime_handler_private.d.ts",
     "//tools/typescript/definitions/pending.d.ts",
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn
index e301fde..60f3c67 100644
--- a/chrome/browser/resources/settings/BUILD.gn
+++ b/chrome/browser/resources/settings/BUILD.gn
@@ -125,6 +125,7 @@
     "privacy_page/anti_abuse_page.ts",
     "privacy_page/collapse_radio_button.ts",
     "privacy_page/cookies_page.ts",
+    "privacy_page/fingerprint_progress_arc.ts",
     "privacy_page/do_not_track_toggle.ts",
     "privacy_page/personalization_options.ts",
     "privacy_page/privacy_guide/privacy_guide_completion_fragment.ts",
@@ -363,6 +364,7 @@
 
   icons_html_files = [
     "icons.html",
+    "privacy_page/fingerprint_icons.html",
     "privacy_sandbox/privacy_sandbox_icons.html",
     "site_settings/all_sites_icons.html",
   ]
@@ -388,6 +390,7 @@
   ts_composite = true
   ts_definitions = [
     "//tools/typescript/definitions/autofill_private.d.ts",
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/chrome_send.d.ts",
     "//tools/typescript/definitions/language_settings_private.d.ts",
     "//tools/typescript/definitions/management.d.ts",
diff --git a/chrome/browser/resources/settings/lazy_load.ts b/chrome/browser/resources/settings/lazy_load.ts
index 2cba5e4..760552910 100644
--- a/chrome/browser/resources/settings/lazy_load.ts
+++ b/chrome/browser/resources/settings/lazy_load.ts
@@ -181,6 +181,7 @@
 export {SettingsCollapseRadioButtonElement} from './privacy_page/collapse_radio_button.js';
 export {SettingsCookiesPageElement} from './privacy_page/cookies_page.js';
 export {SettingsDoNotTrackToggleElement} from './privacy_page/do_not_track_toggle.js';
+export {FINGERPRINT_CHECK_DARK_URL, FINGERPRINT_CHECK_LIGHT_URL, FINGERPRINT_SCANNED_ICON_DARK, FINGERPRINT_SCANNED_ICON_LIGHT, FingerprintProgressArcElement, PROGRESS_CIRCLE_BACKGROUND_COLOR_DARK, PROGRESS_CIRCLE_BACKGROUND_COLOR_LIGHT, PROGRESS_CIRCLE_FILL_COLOR_DARK, PROGRESS_CIRCLE_FILL_COLOR_LIGHT} from './privacy_page/fingerprint_progress_arc.js';
 export {SettingsPersonalizationOptionsElement} from './privacy_page/personalization_options.js';
 export {PrivacyGuideStep} from './privacy_page/privacy_guide/constants.js';
 export {PrivacyGuideCompletionFragmentElement} from './privacy_page/privacy_guide/privacy_guide_completion_fragment.js';
diff --git a/chrome/browser/resources/settings/privacy_page/OWNERS b/chrome/browser/resources/settings/privacy_page/OWNERS
index c393996..8decff1f 100644
--- a/chrome/browser/resources/settings/privacy_page/OWNERS
+++ b/chrome/browser/resources/settings/privacy_page/OWNERS
@@ -3,3 +3,5 @@
 sideyilmaz@chromium.org
 
 per-file cookies_page*=fmacintosh@google.com
+per-file fingerprint*=nsatragno@chromium.org
+per-file fingerprint*=ckincaid@chromium.org
diff --git a/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_icons.html b/chrome/browser/resources/settings/privacy_page/fingerprint_icons.html
similarity index 98%
rename from ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_icons.html
rename to chrome/browser/resources/settings/privacy_page/fingerprint_icons.html
index db8f98b..e9d17f9 100644
--- a/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_icons.html
+++ b/chrome/browser/resources/settings/privacy_page/fingerprint_icons.html
@@ -1,4 +1,4 @@
-<iron-iconset-svg name="cr-fingerprint-icon" size="32">
+<iron-iconset-svg name="fingerprint-icon" size="32">
   <svg>
     <defs>
       <g id="fingerprint-scanned-dark" viewBox="0 0 93 104">
diff --git a/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.html b/chrome/browser/resources/settings/privacy_page/fingerprint_progress_arc.html
similarity index 100%
rename from ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.html
rename to chrome/browser/resources/settings/privacy_page/fingerprint_progress_arc.html
diff --git a/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.ts b/chrome/browser/resources/settings/privacy_page/fingerprint_progress_arc.ts
similarity index 94%
rename from ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.ts
rename to chrome/browser/resources/settings/privacy_page/fingerprint_progress_arc.ts
index 2ec9f96..9cc9701 100644
--- a/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.ts
+++ b/chrome/browser/resources/settings/privacy_page/fingerprint_progress_arc.ts
@@ -4,30 +4,29 @@
 
 import '//resources/polymer/v3_0/iron-icon/iron-icon.js';
 import '//resources/polymer/v3_0/iron-media-query/iron-media-query.js';
-import './cr_fingerprint_icons.html.js';
-import '../cr_lottie/cr_lottie.js';
+import './fingerprint_icons.html.js';
+import '//resources/cr_elements/cr_lottie/cr_lottie.js';
 
+import type {CrLottieElement} from '//resources/cr_elements/cr_lottie/cr_lottie.js';
 import {assert} from '//resources/js/assert.js';
 import type {IronIconElement} from '//resources/polymer/v3_0/iron-icon/iron-icon.js';
 import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import type {CrLottieElement} from '../cr_lottie/cr_lottie.js';
-
-import {getTemplate} from './cr_fingerprint_progress_arc.html.js';
+import {getTemplate} from './fingerprint_progress_arc.html.js';
 
 /**
  * The dark-mode fingerprint icon displayed temporarily each time a user scans
  * their fingerprint and persistently once the enrollment process is complete.
  */
 export const FINGERPRINT_SCANNED_ICON_DARK: string =
-    'cr-fingerprint-icon:fingerprint-scanned-dark';
+    'fingerprint-icon:fingerprint-scanned-dark';
 
 /**
  * The light-mode fingerprint icon displayed temporarily each time a user scans
  * their fingerprint and persistently once the enrollment process is complete.
  */
 export const FINGERPRINT_SCANNED_ICON_LIGHT: string =
-    'cr-fingerprint-icon:fingerprint-scanned-light';
+    'fingerprint-icon:fingerprint-scanned-light';
 
 export const FINGERPRINT_CHECK_DARK_URL: string =
     'chrome://theme/IDR_FINGERPRINT_COMPLETE_CHECK_DARK';
@@ -104,7 +103,7 @@
 const PROGRESS_CIRCLE_STROKE_WIDTH: number = 4;
 
 
-export interface CrFingerprintProgressArcElement {
+export interface FingerprintProgressArcElement {
   $: {
     canvas: HTMLCanvasElement,
     fingerprintScanned: IronIconElement,
@@ -112,9 +111,9 @@
   };
 }
 
-export class CrFingerprintProgressArcElement extends PolymerElement {
+export class FingerprintProgressArcElement extends PolymerElement {
   static get is() {
-    return 'cr-fingerprint-progress-arc';
+    return 'fingerprint-progress-arc';
   }
 
   static get template() {
@@ -258,8 +257,7 @@
       this.drawProgressCircle_(nextPercentToDraw);
       if (!this.progressAnimationIntervalId_) {
         this.dispatchEvent(new CustomEvent(
-            'cr-fingerprint-progress-arc-drawn',
-            {bubbles: true, composed: true}));
+            'fingerprint-progress-arc-drawn', {bubbles: true, composed: true}));
       }
       nextPercentToDraw += step;
     };
@@ -459,9 +457,9 @@
 
 declare global {
   interface HTMLElementTagNameMap {
-    'cr-fingerprint-progress-arc': CrFingerprintProgressArcElement;
+    'fingerprint-progress-arc': FingerprintProgressArcElement;
   }
 }
 
 customElements.define(
-    CrFingerprintProgressArcElement.is, CrFingerprintProgressArcElement);
+    FingerprintProgressArcElement.is, FingerprintProgressArcElement);
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.html b/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.html
index edd9705..ff58194 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.html
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.html
@@ -84,10 +84,10 @@
                 <template>
                   <div class="list-item" first$="[[!index]]">
                     <iron-icon id="darkIcon"
-                        icon="cr-fingerprint-icon:fingerprint-scanned-dark">
+                        icon="fingerprint-icon:fingerprint-scanned-dark">
                     </iron-icon>
                     <iron-icon id="lightIcon"
-                        icon="cr-fingerprint-icon:fingerprint-scanned-light">
+                        icon="fingerprint-icon:fingerprint-scanned-light">
                     </iron-icon>
                     <div class="name" aria-label="[[item.name]]">
                       [[item.name]]
@@ -105,8 +105,8 @@
 
           <div id="enroll">
             <p>[[progressArcLabel_]]</p>
-            <cr-fingerprint-progress-arc id="arc" autoplay>
-            </cr-fingerprint-progress-arc>
+            <fingerprint-progress-arc id="arc" autoplay>
+            </fingerprint-progress-arc>
           </div>
 
           <div id="chooseName">
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.ts b/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.ts
index b7b9d1b..c0d5b70 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.ts
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.ts
@@ -11,7 +11,6 @@
 import 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
 import 'chrome://resources/cr_elements/cr_input/cr_input.js';
-import 'chrome://resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.js';
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
@@ -20,11 +19,11 @@
 import '../settings_shared.css.js';
 import '../site_favicon.js';
 import '../i18n_setup.js';
+import './fingerprint_progress_arc.js';
 
 import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
 import type {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import type {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
-import type {CrFingerprintProgressArcElement} from 'chrome://resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.js';
 import type {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.js';
 import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
 import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
@@ -32,6 +31,7 @@
 import type {IronListElement} from 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import type {FingerprintProgressArcElement} from './fingerprint_progress_arc.js';
 import {getTemplate} from './security_keys_bio_enroll_dialog.html.js';
 import type {Enrollment, EnrollmentResponse, SampleResponse, SecurityKeysBioEnrollProxy} from './security_keys_browser_proxy.js';
 import {Ctap2Status, SampleStatus, SecurityKeysBioEnrollProxyImpl} from './security_keys_browser_proxy.js';
@@ -49,7 +49,7 @@
 export interface SettingsSecurityKeysBioEnrollDialogElement {
   $: {
     addButton: HTMLElement,
-    arc: CrFingerprintProgressArcElement,
+    arc: FingerprintProgressArcElement,
     cancelButton: CrButtonElement,
     confirmButton: CrButtonElement,
     dialog: CrDialogElement,
diff --git a/chrome/browser/resources/settings_shared/BUILD.gn b/chrome/browser/resources/settings_shared/BUILD.gn
index 9dca3fc..e7f6731 100644
--- a/chrome/browser/resources/settings_shared/BUILD.gn
+++ b/chrome/browser/resources/settings_shared/BUILD.gn
@@ -30,6 +30,7 @@
 
   ts_composite = true
   ts_definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/chrome_send.d.ts",
     "//tools/typescript/definitions/metrics_private.d.ts",
     "//tools/typescript/definitions/settings_private.d.ts",
diff --git a/chrome/browser/resources/side_panel/bookmarks/BUILD.gn b/chrome/browser/resources/side_panel/bookmarks/BUILD.gn
index 5e29c81..66b8153 100644
--- a/chrome/browser/resources/side_panel/bookmarks/BUILD.gn
+++ b/chrome/browser/resources/side_panel/bookmarks/BUILD.gn
@@ -41,6 +41,7 @@
 
   ts_composite = true
   ts_definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/bookmark_manager_private.d.ts",
     "//tools/typescript/definitions/bookmarks.d.ts",
     "//tools/typescript/definitions/metrics_private.d.ts",
@@ -49,7 +50,6 @@
   ts_deps = [
     "../shared:build_ts",
     "//third_party/polymer/v3_0:library",
-    "//tools/typescript/definitions:library",
     "//ui/webui/resources/cr_components/color_change_listener:build_ts",
     "//ui/webui/resources/cr_components/commerce:build_ts",
     "//ui/webui/resources/cr_components/page_image_service:build_ts",
diff --git a/chrome/browser/resources/side_panel/customize_chrome/appearance.ts b/chrome/browser/resources/side_panel/customize_chrome/appearance.ts
index 7f1f875..241ee46 100644
--- a/chrome/browser/resources/side_panel/customize_chrome/appearance.ts
+++ b/chrome/browser/resources/side_panel/customize_chrome/appearance.ts
@@ -126,6 +126,11 @@
         value: () => loadTimeData.getBoolean('wallpaperSearchButtonEnabled'),
         reflectToAttribute: true,
       },
+
+      wallpaperSearchEnabled_: {
+        type: Boolean,
+        value: () => loadTimeData.getBoolean('wallpaperSearchEnabled'),
+      },
     };
   }
 
@@ -145,6 +150,8 @@
   private showManagedDialog_: boolean;
   private wallpaperSearchButtonEnabled_:
     boolean;
+  private wallpaperSearchEnabled_:
+    boolean;
 
   private setThemeListenerId_: number|null = null;
 
@@ -272,7 +279,11 @@
   }
 
   private onSearchedImageButtonClick_() {
-    this.dispatchEvent(new CustomEvent('wallpaper-search-click'));
+    if (this.wallpaperSearchEnabled_) {
+      this.dispatchEvent(new CustomEvent('wallpaper-search-click'));
+    } else {
+      this.dispatchEvent(new Event('edit-theme-click'));
+    }
   }
 
   private onSetClassicChromeClicked_() {
diff --git a/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc b/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc
index 73aaadc6..9b92c24a 100644
--- a/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc
+++ b/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc
@@ -931,8 +931,14 @@
   ASSERT_FALSE(switches::IsExplicitBrowserSigninUIOnDesktopEnabled(
       switches::ExplicitBrowserSigninPhase::kExperimental));
 
-  signin::MakePrimaryAccountAvailable(identity_manager(), email_,
-                                      signin::ConsentLevel::kSignin);
+  signin::AccountAvailabilityOptionsBuilder builder;
+  AccountInfo account_info = signin::MakeAccountAvailable(
+      identity_manager(),
+      builder
+          .AsPrimary(signin::ConsentLevel::kSignin)
+          // `ACCESS_POINT_UNKNOWN` is not explicit signin.
+          .WithAccessPoint(signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN)
+          .Build(email_));
 
   EXPECT_TRUE(IsChromeSignedIn());
   EXPECT_FALSE(browser()->profile()->GetPrefs()->GetBoolean(
diff --git a/chrome/browser/signin/signin_manager_unittest.cc b/chrome/browser/signin/signin_manager_unittest.cc
index 368781c2..6ceeef84 100644
--- a/chrome/browser/signin/signin_manager_unittest.cc
+++ b/chrome/browser/signin/signin_manager_unittest.cc
@@ -159,10 +159,13 @@
       const std::string& email,
       signin_metrics::AccessPoint access_point =
           signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN) {
-    AccountInfo account = identity_test_env_.MakeAccountAvailable(email);
-    EXPECT_FALSE(account.IsEmpty());
-    account.access_point = access_point;
-    identity_test_env_.UpdateAccountInfoForAccount(account);
+    AccountAvailabilityOptionsBuilder builder =
+        identity_test_env()
+            ->CreateAccountAvailabilityOptionsBuilder()
+            .WithAccessPoint(access_point);
+
+    AccountInfo account =
+        identity_test_env_.MakeAccountAvailable(builder.Build(email));
     signin::CookieParamsForTest cookie_params = {account.email, account.gaia};
     identity_test_env_.SetCookieAccounts({cookie_params});
     EXPECT_TRUE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin));
@@ -529,10 +532,14 @@
 
 TEST_P(SigninManagerTest, UnconsentedPrimaryAccountUpdatedOnHandleDestroyed) {
   base::HistogramTester histogram_tester;
+  AccountAvailabilityOptionsBuilder builder =
+      identity_test_env()
+          ->CreateAccountAvailabilityOptionsBuilder()
+          .WithAccessPoint(signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN);
   AccountInfo first_account =
-      identity_test_env()->MakeAccountAvailable(kTestEmail);
+      identity_test_env()->MakeAccountAvailable(builder.Build(kTestEmail));
   AccountInfo second_account =
-      identity_test_env()->MakeAccountAvailable(kTestEmail2);
+      identity_test_env()->MakeAccountAvailable(builder.Build(kTestEmail2));
   identity_test_env()->SetCookieAccounts(
       {{first_account.email, first_account.gaia},
        {second_account.email, second_account.gaia}});
@@ -648,11 +655,6 @@
   AccountInfo account =
       MakeAccountAvailableWithCookies(kTestEmail, access_point);
   ExpectUnconsentedPrimaryAccountSetEvent(account);
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  // Lacros always records `ACCESS_POINT_DESKTOP_SIGNIN_MANAGER`.
-  access_point =
-      signin_metrics::AccessPoint::ACCESS_POINT_DESKTOP_SIGNIN_MANAGER;
-#endif
   histogram_tester.ExpectUniqueSample("Signin.SignIn.Completed", access_point,
                                       1);
   histogram_tester.ExpectUniqueSample("Signin.SigninManager.SigninAccessPoint",
diff --git a/chrome/browser/sync/test/integration/password_manager_sync_test.cc b/chrome/browser/sync/test/integration/password_manager_sync_test.cc
index fe1dcf0..5f25eca 100644
--- a/chrome/browser/sync/test/integration/password_manager_sync_test.cc
+++ b/chrome/browser/sync/test/integration/password_manager_sync_test.cc
@@ -161,8 +161,12 @@
     // page load. This is important because if a password is autofilled, then
     // all Javascript changes to it are discarded, and thus any tests that cover
     // updating a password become flaky.
-    feature_list_.InitAndEnableFeature(
-        password_manager::features::kFillOnAccountSelect);
+    feature_list_.InitWithFeatures(
+        /*enabled_features=*/{password_manager::features::kFillOnAccountSelect,
+                              switches::kUnoDesktop,
+                              password_manager::features::
+                                  kButterOnDesktopFollowup},
+        /*disabled_features=*/{});
   }
 
   ~PasswordManagerSyncTest() override = default;
@@ -233,22 +237,31 @@
 
   // Also stores the AccountInfo for the signed-in account in
   // |signed_in_account_| as a side effect.
-  void SignIn(const std::string& email = kTestUserEmail) {
+  // Implicit browser signin, disables passwords account storage by default.
+  void SignIn(const std::string& email = kTestUserEmail,
+              bool explicit_signin = true) {
     ASSERT_TRUE(signed_in_account_.IsEmpty());
     // Setup Sync for an unconsented account (i.e. in transport mode).
-    signed_in_account_ = secondary_account_helper::SignInUnconsentedAccount(
-        GetProfile(0), &test_url_loader_factory_, email);
+    signed_in_account_ =
+        explicit_signin
+            ? secondary_account_helper::SignInUnconsentedAccount(
+                  GetProfile(0), &test_url_loader_factory_, email)
+            : secondary_account_helper::ImplicitSignInUnconsentedAccount(
+                  GetProfile(0), &test_url_loader_factory_, email);
     ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
     ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
   }
 
-  void SetupSyncTransportWithPasswordAccountStorage() {
-    SignIn();
+  void SetupSyncTransportWithPasswordAccountStorage(
+      bool explicit_signin = true) {
+    SignIn(kTestUserEmail, explicit_signin);
 
-    // Let the user opt in to the account-scoped password storage, and wait for
-    // it to become active.
-    password_manager::features_util::OptInToAccountStorage(
-        GetProfile(0)->GetPrefs(), GetSyncService(0));
+    if (!explicit_signin) {
+      // Let the user opt in to the account-scoped password storage, and wait
+      // for it to become active.
+      password_manager::features_util::OptInToAccountStorage(
+          GetProfile(0)->GetPrefs(), GetSyncService(0));
+    }
     PasswordSyncActiveChecker(GetSyncService(0)).Wait();
     ASSERT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::PASSWORDS));
   }
@@ -411,6 +424,15 @@
   AccountInfo signed_in_account_;
 };
 
+class PasswordManagerSyncExplicitParamTest
+    : public PasswordManagerSyncTest,
+      public testing::WithParamInterface<bool /*explicit_signin*/> {
+ public:
+  PasswordManagerSyncExplicitParamTest() = default;
+
+  bool is_explicit_signin() const { return GetParam(); }
+};
+
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
 #if !BUILDFLAG(IS_CHROMEOS_LACROS)
 IN_PROC_BROWSER_TEST_F(PasswordManagerSyncTest, ChooseDestinationStore) {
@@ -898,9 +920,11 @@
 #endif  // !BUILDFLAG(IS_CHROMEOS_LACROS)
 
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
+
+// TODO(b/327118794): Delete this test once implicit signin no longer exists.
 IN_PROC_BROWSER_TEST_F(PasswordManagerSyncTest, OptInSurvivesSignout) {
   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
-  SignIn();
+  SignIn(kTestUserEmail, /*explicit_signin=*/false);
   ASSERT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::PASSWORDS));
 
   password_manager::features_util::OptInToAccountStorage(
@@ -911,10 +935,26 @@
   PasswordSyncInactiveChecker(GetSyncService(0)).Wait();
 
   // The opt-in should be remembered.
-  SignIn();
+  SignIn(kTestUserEmail, /*explicit_signin=*/false);
   PasswordSyncActiveChecker(GetSyncService(0)).Wait();
 }
 
+IN_PROC_BROWSER_TEST_F(PasswordManagerSyncTest, OptOutSurvivesSignout) {
+  ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
+  SignIn(kTestUserEmail);
+  ASSERT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::PASSWORDS));
+
+  password_manager::features_util::OptOutOfAccountStorage(
+      GetProfile(0)->GetPrefs(), GetSyncService(0));
+  PasswordSyncInactiveChecker(GetSyncService(0)).Wait();
+
+  SignOut();
+
+  // The opt-out should be remembered.
+  SignIn(kTestUserEmail);
+  PasswordSyncInactiveChecker(GetSyncService(0)).Wait();
+}
+
 IN_PROC_BROWSER_TEST_F(PasswordManagerSyncTest, OptInOutHistograms) {
   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
   {
@@ -1021,15 +1061,15 @@
 }
 
 IN_PROC_BROWSER_TEST_F(PasswordManagerSyncTest,
-                       KeepAccountStorageSettingsOnlyForUsers) {
+                       KeepOptInAccountStorageSettingsOnlyForUsers) {
   ASSERT_TRUE(SetupClients());
-  SignIn("first@gmail.com");
+  SignIn("first@gmail.com", /*explicit_signin=*/false);
   password_manager::features_util::OptInToAccountStorage(
       GetProfile(0)->GetPrefs(), GetSyncService(0));
   auto first_gaia_id_hash =
       signin::GaiaIdHash::FromGaiaId(GetSyncService(0)->GetAccountInfo().gaia);
   SignOut();
-  SignIn("second@gmail.com");
+  SignIn("second@gmail.com", /*explicit_signin=*/false);
   password_manager::features_util::OptInToAccountStorage(
       GetProfile(0)->GetPrefs(), GetSyncService(0));
   SignOut();
@@ -1037,24 +1077,51 @@
   GetSyncService(0)->GetUserSettings()->KeepAccountSettingsPrefsOnlyForUsers(
       {first_gaia_id_hash});
 
-  SignIn("first@gmail.com");
+  SignIn("first@gmail.com", /*explicit_signin=*/false);
   EXPECT_TRUE(password_manager::features_util::IsOptedInForAccountStorage(
       GetProfile(0)->GetPrefs(), GetSyncService(0)));
   SignOut();
-  SignIn("second@gmail.com");
+  SignIn("second@gmail.com", /*explicit_signin=*/false);
   EXPECT_FALSE(password_manager::features_util::IsOptedInForAccountStorage(
       GetProfile(0)->GetPrefs(), GetSyncService(0)));
 }
-#endif  // BUILDFLAG(ENABLE_DICE_SUPPORT)
 
 IN_PROC_BROWSER_TEST_F(PasswordManagerSyncTest,
+                       KeepOptOutAccountStorageSettingsOnlyForUsers) {
+  ASSERT_TRUE(SetupClients());
+  SignIn("first@gmail.com");
+  password_manager::features_util::OptOutOfAccountStorage(
+      GetProfile(0)->GetPrefs(), GetSyncService(0));
+  auto first_gaia_id_hash =
+      signin::GaiaIdHash::FromGaiaId(GetSyncService(0)->GetAccountInfo().gaia);
+  SignOut();
+  SignIn("second@gmail.com");
+  password_manager::features_util::OptOutOfAccountStorage(
+      GetProfile(0)->GetPrefs(), GetSyncService(0));
+  SignOut();
+
+  GetSyncService(0)->GetUserSettings()->KeepAccountSettingsPrefsOnlyForUsers(
+      {first_gaia_id_hash});
+
+  SignIn("first@gmail.com");
+  EXPECT_FALSE(password_manager::features_util::IsOptedInForAccountStorage(
+      GetProfile(0)->GetPrefs(), GetSyncService(0)));
+  SignOut();
+  SignIn("second@gmail.com");
+  EXPECT_TRUE(password_manager::features_util::IsOptedInForAccountStorage(
+      GetProfile(0)->GetPrefs(), GetSyncService(0)));
+}
+
+#endif  // BUILDFLAG(ENABLE_DICE_SUPPORT)
+
+IN_PROC_BROWSER_TEST_P(PasswordManagerSyncExplicitParamTest,
                        PasswordDeletionsPropagateToServer) {
   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
 
   // Add credential to server.
   AddCredentialToFakeServer(CreateTestPasswordForm("user", "pass"));
 
-  SetupSyncTransportWithPasswordAccountStorage();
+  SetupSyncTransportWithPasswordAccountStorage(is_explicit_signin());
   password_manager::PasswordStoreInterface* account_store =
       passwords_helper::GetAccountPasswordStoreInterface(0);
 
@@ -1081,11 +1148,21 @@
   EXPECT_EQ(fake_server_->GetSyncEntitiesByModelType(syncer::PASSWORDS).size(),
             0u);
 
-  // The opt-in should be gone as well.
-  EXPECT_FALSE(password_manager::features_util::IsOptedInForAccountStorage(
-      GetProfile(0)->GetPrefs(), GetSyncService(0)));
+  // The opt-in persists only if the signin was explicit.
+  EXPECT_EQ(password_manager::features_util::IsOptedInForAccountStorage(
+                GetProfile(0)->GetPrefs(), GetSyncService(0)),
+            is_explicit_signin());
 }
 
+INSTANTIATE_TEST_SUITE_P(
+    /* no prefix */,
+    PasswordManagerSyncExplicitParamTest,
+    ::testing::Bool(),
+    [](const testing::TestParamInfo<bool>& info) {
+      return info.param ? "Explicit" : "Implicit";
+    });
+
+// TODO(b/327118794): Delete this test once implicit signin no longer exists.
 IN_PROC_BROWSER_TEST_F(PasswordManagerSyncTest,
                        PRE_ClearAccountStoreOnStartup) {
   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
@@ -1094,7 +1171,7 @@
   AddCredentialToFakeServer(
       CreateTestPasswordForm("accountuser", "accountpass"));
 
-  SetupSyncTransportWithPasswordAccountStorage();
+  SetupSyncTransportWithPasswordAccountStorage(/*explicit_signin=*/false);
 
   // Also add a credential to the profile store.
   AddLocalCredential("localuser", "localpass");
@@ -1105,6 +1182,7 @@
               ElementsAre(MatchesLogin("accountuser", "accountpass")));
 }
 
+// TODO(b/327118794): Delete this test once implicit signin no longer exists.
 IN_PROC_BROWSER_TEST_F(PasswordManagerSyncTest, ClearAccountStoreOnStartup) {
   // Before setting up the client (aka profile), manually remove the opt-in pref
   // from the profile's prefs file. This simulates the case where the user
diff --git a/chrome/browser/sync/test/integration/secondary_account_helper.cc b/chrome/browser/sync/test/integration/secondary_account_helper.cc
index 7347d450..4b2837f6 100644
--- a/chrome/browser/sync/test/integration/secondary_account_helper.cc
+++ b/chrome/browser/sync/test/integration/secondary_account_helper.cc
@@ -116,6 +116,28 @@
   return account_info;
 }
 
+AccountInfo ImplicitSignInUnconsentedAccount(
+    Profile* profile,
+    network::TestURLLoaderFactory* test_url_loader_factory,
+    const std::string& email) {
+  signin::IdentityManager* identity_manager =
+      IdentityManagerFactory::GetForProfile(profile);
+  signin::AccountAvailabilityOptionsBuilder builder;
+  AccountInfo account_info = signin::MakeAccountAvailable(
+      identity_manager,
+      builder
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
+          .AsPrimary(signin::ConsentLevel::kSignin)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
+        // `ACCESS_POINT_WEB_SIGNIN` is not explicit signin.
+          .WithAccessPoint(signin_metrics::AccessPoint::ACCESS_POINT_WEB_SIGNIN)
+          .Build(email));
+  SetCookieForGaiaId(account_info.gaia, account_info.email,
+                     /*signed_out=*/false, identity_manager,
+                     test_url_loader_factory);
+  return account_info;
+}
+
 void SignOutAccount(Profile* profile,
                     network::TestURLLoaderFactory* test_url_loader_factory,
                     const CoreAccountId& account_id) {
diff --git a/chrome/browser/sync/test/integration/secondary_account_helper.h b/chrome/browser/sync/test/integration/secondary_account_helper.h
index 2663cd5..5f853a90 100644
--- a/chrome/browser/sync/test/integration/secondary_account_helper.h
+++ b/chrome/browser/sync/test/integration/secondary_account_helper.h
@@ -48,6 +48,16 @@
     network::TestURLLoaderFactory* test_url_loader_factory,
     const std::string& email);
 
+// Sets an account as primary with `signin::ConsentLevel::kSignin`. There is no
+// consent for Sync. The account is available with both a refresh token and
+// cookie. The signin is not considered explicit (it happened through Dice
+// automatic signin), and account storage for passwords and addresses is not
+// opted-in.
+AccountInfo ImplicitSignInUnconsentedAccount(
+    Profile* profile,
+    network::TestURLLoaderFactory* test_url_loader_factory,
+    const std::string& email);
+
 // Clears signin cookies and removes the refresh token for the given account.
 void SignOutAccount(Profile* profile,
                     network::TestURLLoaderFactory* test_url_loader_factory,
diff --git a/chrome/browser/sync/test/integration/single_client_incoming_password_sharing_invitation_test.cc b/chrome/browser/sync/test/integration/single_client_incoming_password_sharing_invitation_test.cc
index d56b93d4..8b0a563 100644
--- a/chrome/browser/sync/test/integration/single_client_incoming_password_sharing_invitation_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_incoming_password_sharing_invitation_test.cc
@@ -25,6 +25,7 @@
 #include "components/password_manager/core/browser/features/password_manager_features_util.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
+#include "components/signin/public/base/signin_switches.h"
 #include "components/sync/base/features.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/engine/nigori/cross_user_sharing_public_key.h"
@@ -182,6 +183,16 @@
     if (!GetClient(0)->AwaitSyncTransportActive()) {
       return false;
     }
+
+#if !BUILDFLAG(IS_ANDROID)
+    // Explicitly opt out of account storage when signin is explicit.
+    if (switches::IsExplicitBrowserSigninUIOnDesktopEnabled(
+            switches::ExplicitBrowserSigninPhase::kExperimental)) {
+      password_manager::features_util::OptOutOfAccountStorage(
+          GetProfile(0)->GetPrefs(), GetSyncService(0));
+    }
+#endif
+
     return true;
   }
 
diff --git a/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc b/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc
index 7aa29553..cbfc4a3 100644
--- a/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc
@@ -2244,24 +2244,52 @@
 
 // ChromeOS doesn't have unconsented primary accounts.
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
-IN_PROC_BROWSER_TEST_F(SingleClientNigoriWithWebApiTest,
+
+class SingleClientNigoriWithWebApiExplicitParamTest
+    : public SingleClientNigoriWithWebApiTest,
+      public testing::WithParamInterface<bool /*explicit_signin*/> {
+ public:
+  SingleClientNigoriWithWebApiExplicitParamTest() = default;
+
+  bool is_explicit_signin() const { return GetParam(); }
+
+  void SignInMaybeExplicit() {
+    if (is_explicit_signin()) {
+      secondary_account_helper::SignInUnconsentedAccount(
+          GetProfile(0), &test_url_loader_factory_,
+          SyncTest::kDefaultUserEmail);
+    } else {
+      secondary_account_helper::ImplicitSignInUnconsentedAccount(
+          GetProfile(0), &test_url_loader_factory_,
+          SyncTest::kDefaultUserEmail);
+    }
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_{switches::kUnoDesktop};
+};
+
+IN_PROC_BROWSER_TEST_P(SingleClientNigoriWithWebApiExplicitParamTest,
                        ShouldAcceptEncryptionKeysFromTheWebInTransportMode) {
   // Mimic the account using a trusted vault passphrase.
   SetNigoriInFakeServer(BuildTrustedVaultNigoriSpecifics({kTestEncryptionKey}),
                         GetFakeServer());
 
   ASSERT_TRUE(SetupClients());
-  secondary_account_helper::SignInUnconsentedAccount(
-      GetProfile(0), &test_url_loader_factory_, SyncTest::kDefaultUserEmail);
+
+  SignInMaybeExplicit();
   ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
   ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
 
-  // Chrome isn't trying to sync passwords, because the user hasn't opted in to
-  // passwords account storage. So the error shouldn't be surfaced yet.
-  ASSERT_FALSE(GetAvatarSyncErrorType(GetProfile(0)).has_value());
+  if (!is_explicit_signin()) {
+    // If signin is implicit, Chrome isn't trying to sync passwords, because the
+    // user hasn't opted in to passwords account storage. So the error shouldn't
+    // be surfaced yet.
+    ASSERT_FALSE(GetAvatarSyncErrorType(GetProfile(0)).has_value());
 
-  password_manager::features_util::OptInToAccountStorage(
-      GetProfile(0)->GetPrefs(), GetSyncService(0));
+    password_manager::features_util::OptInToAccountStorage(
+        GetProfile(0)->GetPrefs(), GetSyncService(0));
+  }
 
   // The error is now shown, because PASSWORDS is trying to sync. The data
   // type isn't active yet though due to the missing encryption keys.
@@ -2293,8 +2321,8 @@
   EXPECT_FALSE(GetAvatarSyncErrorType(GetProfile(0)).has_value());
 }
 
-IN_PROC_BROWSER_TEST_F(
-    SingleClientNigoriWithWebApiTest,
+IN_PROC_BROWSER_TEST_P(
+    SingleClientNigoriWithWebApiExplicitParamTest,
     ShouldReportDegradedTrustedVaultRecoverabilityInTransportMode) {
   base::HistogramTester histogram_tester;
 
@@ -2314,17 +2342,18 @@
       GetSecurityDomainsServer()->GetAllTrustedVaultKeys(),
       /*last_key_version=*/GetSecurityDomainsServer()->GetCurrentEpoch());
 
-  secondary_account_helper::SignInUnconsentedAccount(
-      GetProfile(0), &test_url_loader_factory_, SyncTest::kDefaultUserEmail);
+  SignInMaybeExplicit();
   ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
   ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
 
-  // Chrome isn't trying to sync passwords, because the user hasn't opted in to
-  // passwords account storage. So the error shouldn't be surfaced yet.
-  ASSERT_FALSE(GetAvatarSyncErrorType(GetProfile(0)).has_value());
+  if (!is_explicit_signin()) {
+    // Chrome isn't trying to sync passwords, because the user hasn't opted in
+    // to passwords account storage. So the error shouldn't be surfaced yet.
+    ASSERT_FALSE(GetAvatarSyncErrorType(GetProfile(0)).has_value());
 
-  password_manager::features_util::OptInToAccountStorage(
-      GetProfile(0)->GetPrefs(), GetSyncService(0));
+    password_manager::features_util::OptInToAccountStorage(
+        GetProfile(0)->GetPrefs(), GetSyncService(0));
+  }
 
   ASSERT_TRUE(TrustedVaultRecoverabilityDegradedStateChecker(GetSyncService(0),
                                                              /*degraded=*/true)
@@ -2353,6 +2382,14 @@
       "Sync.TrustedVaultRecoverabilityDegradedOnStartup",
       /*sample=*/true, /*expected_bucket_count=*/1);
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    /* no prefix */,
+    SingleClientNigoriWithWebApiExplicitParamTest,
+    ::testing::Bool(),
+    [](const testing::TestParamInfo<bool>& info) {
+      return info.param ? "Explicit" : "Implicit";
+    });
 #endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 }  // namespace
diff --git a/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc b/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc
index 79cdff8..efc8ebfe 100644
--- a/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc
@@ -516,6 +516,7 @@
 }
 
 // Regression test for crbug.com/1076378.
+// TODO(b/327118794): Delete this test once implicit signin no longer exists.
 IN_PROC_BROWSER_TEST_F(SingleClientPasswordsWithAccountStorageSyncTest,
                        EnablesPasswordSyncOnOptingInToSync) {
   AddTestPasswordToFakeServer();
@@ -523,13 +524,14 @@
   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
 
   // Setup Sync for an unconsented account (i.e. in transport mode).
-  AccountInfo account_info = secondary_account_helper::SignInUnconsentedAccount(
-      GetProfile(0), &test_url_loader_factory_, "user@email.com");
+  AccountInfo account_info =
+      secondary_account_helper::ImplicitSignInUnconsentedAccount(
+          GetProfile(0), &test_url_loader_factory_, "user@email.com");
   ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
   ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
 
-  // The user is not opted in to the account-scoped password storage, so the
-  // passwords data type should *not* be active.
+  // If signin is implicit, the user is not opted in to the account-scoped
+  // password storage, so the passwords data type should *not* be active.
   ASSERT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::PASSWORDS));
 
   // Turn on Sync-the-feature.
diff --git a/chrome/browser/sync/test/integration/single_client_webauthn_credentials_sync_test.cc b/chrome/browser/sync/test/integration/single_client_webauthn_credentials_sync_test.cc
index e81da018..3d08215 100644
--- a/chrome/browser/sync/test/integration/single_client_webauthn_credentials_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_webauthn_credentials_sync_test.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/sync/test/integration/webauthn_credentials_helper.h"
 #include "chrome/browser/ui/browser.h"
 #include "components/password_manager/core/browser/features/password_manager_features_util.h"
+#include "components/signin/public/base/signin_switches.h"
 #include "components/sync/base/client_tag_hash.h"
 #include "components/sync/base/features.h"
 #include "components/sync/base/model_type.h"
@@ -856,26 +857,47 @@
 
 // The unconsented primary account isn't supported on ChromeOS.
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
+
+class SingleClientWebAuthnCredentialsSyncTestExplicitParamTest
+    : public SingleClientWebAuthnCredentialsSyncTest,
+      public testing::WithParamInterface<bool /*explicit_signin*/> {
+ public:
+  SingleClientWebAuthnCredentialsSyncTestExplicitParamTest() = default;
+
+  bool is_explicit_signin() const { return GetParam(); }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_{
+      switches::kExplicitBrowserSigninUIOnDesktop};
+};
+
 // Tests that passkeys sync on transport mode only if the user has consented to
 // showing credentials from their Google account.
-IN_PROC_BROWSER_TEST_F(SingleClientWebAuthnCredentialsSyncTest,
+IN_PROC_BROWSER_TEST_P(SingleClientWebAuthnCredentialsSyncTestExplicitParamTest,
                        TransportModeConsent) {
   const std::string sync_id = InjectPasskeyToFakeServer(NewPasskey());
   ASSERT_TRUE(SetupClients());
 
-  AccountInfo account_info = secondary_account_helper::SignInUnconsentedAccount(
-      GetProfile(0), &test_url_loader_factory_, "user@email.com");
+  const char kTestEmail[] = "user@email.com";
+  AccountInfo account_info =
+      is_explicit_signin()
+          ? secondary_account_helper::SignInUnconsentedAccount(
+                GetProfile(0), &test_url_loader_factory_, kTestEmail)
+          : secondary_account_helper::ImplicitSignInUnconsentedAccount(
+                GetProfile(0), &test_url_loader_factory_, kTestEmail);
   ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
   ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
 
-  // Passkeys should not be syncing.
-  EXPECT_FALSE(
-      GetSyncService(0)->GetActiveDataTypes().Has(syncer::WEBAUTHN_CREDENTIAL));
+  if (!is_explicit_signin()) {
+    // Passkeys should be syncing only if the signin is explicit.
+    EXPECT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has(
+        syncer::WEBAUTHN_CREDENTIAL));
 
-  // Let the user opt in to transport mode and wait for passkeys to start
-  // syncing.
-  password_manager::features_util::OptInToAccountStorage(
-      GetProfile(0)->GetPrefs(), GetSyncService(0));
+    // Let the user opt in to transport mode and wait for passkeys to start
+    // syncing.
+    password_manager::features_util::OptInToAccountStorage(
+        GetProfile(0)->GetPrefs(), GetSyncService(0));
+  }
   PasskeySyncActiveChecker(GetSyncService(0)).Wait();
   EXPECT_TRUE(
       LocalPasskeysMatchChecker(kSingleProfile,
@@ -887,6 +909,14 @@
       GetProfile(0)->GetPrefs(), GetSyncService(0));
   EXPECT_TRUE(LocalPasskeysMatchChecker(kSingleProfile, IsEmpty()).Wait());
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    /* no prefix */,
+    SingleClientWebAuthnCredentialsSyncTestExplicitParamTest,
+    ::testing::Bool(),
+    [](const testing::TestParamInfo<bool>& info) {
+      return info.param ? "Explicit" : "Implicit";
+    });
 #endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 }  // namespace
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc
index 3277c9b..ebf6fe20d 100644
--- a/chrome/browser/sync/test/integration/sync_test.cc
+++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -65,6 +65,7 @@
 #include "components/os_crypt/sync/os_crypt_mocker.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/signin/public/base/consent_level.h"
+#include "components/signin/public/base/signin_switches.h"
 #include "components/sync/base/command_line_switches.h"
 #include "components/sync/base/features.h"
 #include "components/sync/base/model_type.h"
@@ -1143,9 +1144,21 @@
           syncer::kSyncEnableWalletOfferInTransportMode)) {
     allowed_types.Put(syncer::AUTOFILL_WALLET_OFFER);
   }
-  if (base::FeatureList::IsEnabled(
-          syncer::kEnablePasswordsAccountStorageForNonSyncingUsers)) {
+
+  bool allow_passwords = base::FeatureList::IsEnabled(
+      syncer::kEnablePasswordsAccountStorageForNonSyncingUsers);
+#if !BUILDFLAG(IS_ANDROID)
+  // This is an approximation because passwords are only enabled if the signin
+  // is explicit (they are not enabled for users who signed in through Dice).
+  allow_passwords &= switches::IsExplicitBrowserSigninUIOnDesktopEnabled(
+      switches::ExplicitBrowserSigninPhase::kExperimental);
+#endif
+
+  if (allow_passwords) {
     allowed_types.Put(syncer::PASSWORDS);
+    allowed_types.Put(syncer::WEBAUTHN_CREDENTIAL);
+    allowed_types.Put(syncer::INCOMING_PASSWORD_SHARING_INVITATION);
+    allowed_types.Put(syncer::OUTGOING_PASSWORD_SHARING_INVITATION);
   }
   if (base::FeatureList::IsEnabled(syncer::kEnablePreferencesAccountStorage) &&
       base::FeatureList::IsEnabled(
diff --git a/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc b/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc
index 5269029..4f76769 100644
--- a/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc
@@ -21,6 +21,7 @@
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_store/password_store_interface.h"
 #include "components/password_manager/core/common/password_manager_features.h"
+#include "components/signin/public/base/signin_switches.h"
 #include "components/sync/engine/cycle/entity_change_metric_recording.h"
 #include "components/sync/test/fake_server_http_post_provider.h"
 #include "content/public/test/browser_test.h"
@@ -91,14 +92,15 @@
   for (int i = 0; i < num_clients(); i++) {
     ASSERT_TRUE(GetClient(i)->SignInPrimaryAccount());
     ASSERT_TRUE(GetClient(i)->AwaitSyncTransportActive());
-    // The user hasn't opted in, so PASSWORDS is not active yet.
-    ASSERT_FALSE(GetSyncService(i)->GetActiveDataTypes().Has(
-        syncer::ModelType::PASSWORDS));
     ASSERT_FALSE(GetSyncService(i)->IsSyncFeatureEnabled());
 
-    // Opt in. PASSWORDS should become active.
-    password_manager::features_util::OptInToAccountStorage(
-        GetProfile(i)->GetPrefs(), GetSyncService(i));
+    // The PASSWORDS are active only if the signin was explicit.
+    if (!switches::IsExplicitBrowserSigninUIOnDesktopEnabled(
+            switches::ExplicitBrowserSigninPhase::kExperimental)) {
+      // Opt in. PASSWORDS should become active.
+      password_manager::features_util::OptInToAccountStorage(
+          GetProfile(i)->GetPrefs(), GetSyncService(i));
+    }
     PasswordSyncActiveChecker(GetSyncService(i)).Wait();
   }
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 34209257..b87562a2 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -6164,6 +6164,8 @@
       "views/webauthn/authenticator_client_pin_entry_sheet_view.h",
       "views/webauthn/authenticator_client_pin_entry_view.cc",
       "views/webauthn/authenticator_client_pin_entry_view.h",
+      "views/webauthn/authenticator_gpm_arbitrary_pin_sheet_view.cc",
+      "views/webauthn/authenticator_gpm_arbitrary_pin_sheet_view.h",
       "views/webauthn/authenticator_gpm_pin_sheet_view.cc",
       "views/webauthn/authenticator_gpm_pin_sheet_view.h",
       "views/webauthn/authenticator_gpm_pin_view.cc",
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc b/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc
index 0b5d2de..1f5d3bf 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc
+++ b/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc
@@ -16,6 +16,7 @@
 #include "ash/webui/personalization_app/personalization_app_url_constants.h"
 #include "ash/webui/personalization_app/proto/backdrop_wallpaper.pb.h"
 #include "ash/webui/system_apps/public/system_web_app_type.h"
+#include "base/check_is_test.h"
 #include "base/command_line.h"
 #include "base/functional/bind.h"
 #include "base/hash/hash.h"
@@ -183,6 +184,12 @@
   // SessionManager might not exist in unit tests.
   if (session_manager)
     session_observation_.Observe(session_manager);
+
+  if (user_manager::UserManager::IsInitialized()) {
+    user_manager_observation_.Observe(user_manager::UserManager::Get());
+  } else {
+    CHECK_IS_TEST();
+  }
 }
 
 WallpaperControllerClientImpl::~WallpaperControllerClientImpl() {
@@ -360,6 +367,16 @@
   ObserveVolumeManagerForAccountId(account_id);
 }
 
+void WallpaperControllerClientImpl::OnUserLoggedIn(
+    const user_manager::User& user) {
+  // For public account, it's possible that the user-policy controlled wallpaper
+  // was fetched/cleared at the login screen (while for a regular user it was
+  // always fetched/cleared inside a user session), in the case the user-policy
+  // controlled wallpaper was fetched/cleared but not updated in the login
+  // screen, we need to update the wallpaper after the public user logged in.
+  ShowUserWallpaper(user.GetAccountId());
+}
+
 void WallpaperControllerClientImpl::DeviceWallpaperImageFilePathChanged() {
   wallpaper_controller_->SetDevicePolicyWallpaperPath(
       GetDeviceWallpaperImageFilePath());
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client_impl.h b/chrome/browser/ui/ash/wallpaper_controller_client_impl.h
index 4cfe14168..fce452cf 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client_impl.h
+++ b/chrome/browser/ui/ash/wallpaper_controller_client_impl.h
@@ -37,7 +37,8 @@
 class WallpaperControllerClientImpl
     : public ash::WallpaperControllerClient,
       public file_manager::VolumeManagerObserver,
-      public session_manager::SessionManagerObserver {
+      public session_manager::SessionManagerObserver,
+      public user_manager::UserManager::Observer {
  public:
   explicit WallpaperControllerClientImpl(
       std::unique_ptr<wallpaper_handlers::WallpaperFetcherDelegate>
@@ -94,6 +95,9 @@
   // session_manager::SessionManagerObserver implementation.
   void OnUserProfileLoaded(const AccountId& account_id) override;
 
+  // user_manager::UserManager::Observer:
+  void OnUserLoggedIn(const user_manager::User& user) override;
+
   // Wrappers around the ash::WallpaperController interface.
   void SetPolicyWallpaper(const AccountId& account_id,
                           std::unique_ptr<std::string> data);
@@ -181,6 +185,10 @@
                           session_manager::SessionManagerObserver>
       session_observation_{this};
 
+  base::ScopedObservation<user_manager::UserManager,
+                          user_manager::UserManager::Observer>
+      user_manager_observation_{this};
+
   base::WeakPtrFactory<WallpaperControllerClientImpl> weak_factory_{this};
 };
 
diff --git a/chrome/browser/ui/browser_commands_browsertest.cc b/chrome/browser/ui/browser_commands_browsertest.cc
index f074bdc..90f3887 100644
--- a/chrome/browser/ui/browser_commands_browsertest.cc
+++ b/chrome/browser/ui/browser_commands_browsertest.cc
@@ -240,10 +240,8 @@
   };
 
   // Create another window, and add tabs.
-  ui_test_utils::BrowserChangeObserver second_browser_observer(
-      nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded);
-  chrome::NewEmptyWindow(browser()->profile());
-  ui_test_utils::WaitForBrowserSetLastActive(second_browser_observer.Wait());
+  ui_test_utils::OpenNewEmptyWindowAndWaitUntilSetAsLastActive(
+      browser()->profile());
   Browser* second_window = BrowserList::GetInstance()->GetLastActive();
   AddTabs(browser(), 2);
   AddTabs(second_window, 1);
diff --git a/chrome/browser/ui/intent_picker_tab_helper.cc b/chrome/browser/ui/intent_picker_tab_helper.cc
index 28ff491..6b92f8d 100644
--- a/chrome/browser/ui/intent_picker_tab_helper.cc
+++ b/chrome/browser/ui/intent_picker_tab_helper.cc
@@ -344,7 +344,7 @@
       apps::IntentPickerIconEvent::kIconClicked);
 
   if (apps.size() == 1 && intent_picker_delegate_->ShouldLaunchAppDirectly(
-                              url, apps[0].launch_name)) {
+                              url, apps[0].launch_name, apps[0].type)) {
     // TODO(b/305075981): Move IntentChipDisplayPrefs to
     // c/b/apps/link_capturing.
     if (apps::features::ShouldShowLinkCapturingUX()) {
diff --git a/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc b/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc
index 4bfe9d4..12cff59 100644
--- a/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc
+++ b/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc
@@ -343,10 +343,8 @@
                        DismissalCausePromptBrowserSwitched) {
   JavaScriptDialogDismissalCauseTester tester(this);
   tester.PopupDialog(content::JAVASCRIPT_DIALOG_TYPE_PROMPT);
-  ui_test_utils::BrowserChangeObserver new_browser_observer(
-      nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded);
-  chrome::NewEmptyWindow(browser()->profile());
-  ui_test_utils::WaitForBrowserSetLastActive(new_browser_observer.Wait());
+  ui_test_utils::OpenNewEmptyWindowAndWaitUntilSetAsLastActive(
+      browser()->profile());
   EXPECT_EQ(DismissalCause::kBrowserSwitched, tester.GetLastDismissalCause());
 }
 
diff --git a/chrome/browser/ui/views/default_link_capturing_interactive_uitest.cc b/chrome/browser/ui/views/default_link_capturing_interactive_uitest.cc
index b4f5752c..ff480a0 100644
--- a/chrome/browser/ui/views/default_link_capturing_interactive_uitest.cc
+++ b/chrome/browser/ui/views/default_link_capturing_interactive_uitest.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/ui/web_applications/app_browser_controller.h"
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
 #include "chrome/browser/ui/web_applications/test/web_app_navigation_browsertest.h"
+#include "chrome/browser/web_applications/test/web_app_icon_test_utils.h"
 #include "chrome/browser/web_applications/web_app_pref_guardrails.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_ui_manager.h"
@@ -161,14 +162,13 @@
 
 #if BUILDFLAG(IS_MAC)
 using IntentPickerInteractiveUiTest = DefaultLinkCapturingInteractiveUiTest;
-// Test that if there is a Universal Link for a site, it shows the picker icon
-// and lists the app as an option in the bubble.
+// Test that if there is a Universal Link for a site, it shows the picker
+// with the app icon.
 IN_PROC_BROWSER_TEST_F(IntentPickerInteractiveUiTest,
-                       ShowUniversalLinkInIntentPicker) {
+                       ShowUniversalLinkAppInIntentChip) {
   const GURL url1(embedded_test_server()->GetURL("/title1.html"));
   const GURL url2(embedded_test_server()->GetURL("/title2.html"));
 
-  const char* kFinderAppName = "Finder";
   const char* kFinderAppPath = "/System/Library/CoreServices/Finder.app";
 
   // Start with a page with no corresponding native app.
@@ -184,24 +184,18 @@
   apps::OverrideMacAppForUrlForTesting(true, kFinderAppPath);
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url2));
 
-  // Verify intent picker chip shows up, click on it, and wait for the bubble to
-  // be populated
-  EXPECT_TRUE(web_app::ClickIntentPickerAndWaitForBubble(browser()));
-  EXPECT_TRUE(web_app::intent_picker_bubble()->GetVisible());
+  // Verify app icon shows up in the intent picker.
+  EXPECT_TRUE(web_app::AwaitIntentPickerTabHelperIconUpdateComplete(
+      browser()->tab_strip_model()->GetActiveWebContents()));
+  IntentChipButton* intent_picker_icon =
+      web_app::GetIntentPickerIcon(browser());
+  ASSERT_NE(intent_picker_icon, nullptr);
 
-  EXPECT_EQ(1U, GetItemContainerSize(web_app::intent_picker_bubble()));
-  auto& app_info =
-      web_app::intent_picker_bubble()->app_info_for_testing();  // IN-TEST
-  ASSERT_EQ(1U, app_info.size());
-  EXPECT_EQ(kFinderAppPath, app_info[0].launch_name);
-  EXPECT_EQ(kFinderAppName, app_info[0].display_name);
+  ui::ImageModel app_icon = intent_picker_icon->GetAppIconForTesting();
 
-  // Navigate to the first page while simulating no native app.
-  apps::OverrideMacAppForUrlForTesting(true, "");
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url1));
-
-  // Verify that the icon was hidden.
-  ASSERT_FALSE(web_app::GetIntentPickerIcon(browser())->GetVisible());
+  SkColor final_color = app_icon.GetImage().AsBitmap().getColor(8, 8);
+  EXPECT_TRUE(
+      web_app::AreColorsEqual(SK_ColorRED, final_color, /*threshold=*/50));
 }
 #endif  // BUILDFLAG(IS_MAC)
 
diff --git a/chrome/browser/ui/views/location_bar/intent_chip_button.cc b/chrome/browser/ui/views/location_bar/intent_chip_button.cc
index 77062ac..4ef2195 100644
--- a/chrome/browser/ui/views/location_bar/intent_chip_button.cc
+++ b/chrome/browser/ui/views/location_bar/intent_chip_button.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/views/location_bar/intent_chip_button.h"
 
 #include "base/check.h"
+#include "base/check_is_test.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
 #include "build/build_config.h"
@@ -73,6 +74,11 @@
   }
 }
 
+ui::ImageModel IntentChipButton::GetAppIconForTesting() const {
+  CHECK_IS_TEST();
+  return GetAppIcon();
+}
+
 bool IntentChipButton::GetShowChip() const {
   if (delegate_->ShouldHidePageActionIcons())
     return false;
diff --git a/chrome/browser/ui/views/location_bar/intent_chip_button.h b/chrome/browser/ui/views/location_bar/intent_chip_button.h
index 012d502..11972f2 100644
--- a/chrome/browser/ui/views/location_bar/intent_chip_button.h
+++ b/chrome/browser/ui/views/location_bar/intent_chip_button.h
@@ -27,6 +27,7 @@
   ~IntentChipButton() override;
 
   void Update();
+  ui::ImageModel GetAppIconForTesting() const;
 
  private:
   bool GetShowChip() const;
diff --git a/chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog.cc b/chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog.cc
index 87d42d9..96ac14b 100644
--- a/chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog.cc
@@ -7,6 +7,7 @@
 #include <string>
 #include <vector>
 
+#include "base/feature_list.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_forward.h"
 #include "base/memory/raw_ref.h"
@@ -17,11 +18,13 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
+#include "chrome/browser/ui/views/web_apps/web_app_icon_name_and_origin_view.h"
 #include "chrome/browser/ui/views/web_apps/web_app_info_image_source.h"
 #include "chrome/browser/ui/views/web_apps/web_app_install_dialog_delegate.h"
 #include "chrome/browser/ui/web_applications/web_app_dialogs.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/constrained_window/constrained_window_views.h"
 #include "components/prefs/pref_service.h"
@@ -351,49 +354,81 @@
                             gfx::Size(kIconSize, kIconSize));
 
   auto title = install_info->title;
+  GURL start_url = install_info->start_url;
   std::u16string start_url_host_formatted_for_display =
       url_formatter::FormatUrlForDisplayOmitSchemePathAndTrivialSubdomains(
-          install_info->start_url);
+          start_url);
+
   const std::u16string description = gfx::TruncateString(
       install_info->description, webapps::kMaximumDescriptionLength,
       gfx::CHARACTER_BREAK);
   auto manifest_id = install_info->manifest_id;
 
-  auto delegate = std::make_unique<web_app::WebAppInstallDialogDelegate>(
+  auto delegate = std::make_unique<WebAppInstallDialogDelegate>(
       web_contents, std::move(install_info), std::move(install_tracker),
       std::move(callback), std::move(iph_state), prefs, tracker,
       InstallDialogType::kDetailed);
   auto delegate_weak_ptr = delegate->AsWeakPtr();
-  auto dialog_model =
-      ui::DialogModel::Builder(std::move(delegate))
-          .SetInternalName("WebAppDetailedInstallDialog")
-          .SetIcon(ui::ImageModel::FromImageSkia(icon_image))
-          .SetTitle(title)
-          .SetSubtitle(start_url_host_formatted_for_display)
-          .AddParagraph(
-              ui::DialogModelLabel(description).set_is_secondary(),
-              l10n_util::GetStringUTF16(
-                  IDS_WEB_APP_DETAILED_INSTALL_DIALOG_DESCRIPTION_TITLE))
-          .AddOkButton(
-              base::BindOnce(&web_app::WebAppInstallDialogDelegate::OnAccept,
-                             delegate_weak_ptr),
-              ui::DialogModel::Button::Params().SetLabel(
-                  l10n_util::GetStringUTF16(IDS_INSTALL)))
-          .AddCancelButton(
-              base::BindOnce(&web_app::WebAppInstallDialogDelegate::OnCancel,
-                             delegate_weak_ptr))
-          .SetCloseActionCallback(
-              base::BindOnce(&web_app::WebAppInstallDialogDelegate::OnClose,
-                             delegate_weak_ptr))
-          .AddCustomField(
-              std::make_unique<views::BubbleDialogModelHost::CustomView>(
-                  std::make_unique<ImageCarouselView>(screenshots),
-                  views::BubbleDialogModelHost::FieldType::kControl))
-          .SetDialogDestroyingCallback(
-              base::BindOnce(&web_app::WebAppInstallDialogDelegate::OnClose,
-                             delegate_weak_ptr))
-          .OverrideDefaultButton(ui::DialogButton::DIALOG_BUTTON_CANCEL)
-          .Build();
+
+  std::unique_ptr<ui::DialogModel> dialog_model;
+  if (base::FeatureList::IsEnabled(features::kWebAppUniversalInstall)) {
+    dialog_model =
+        ui::DialogModel::Builder(std::move(delegate))
+            .SetInternalName("WebAppDetailedInstallDialog")
+            .SetTitle(l10n_util::GetStringUTF16(IDS_INSTALL_PWA_DIALOG_TITLE))
+            .AddCustomField(
+                std::make_unique<views::BubbleDialogModelHost::CustomView>(
+                    WebAppIconNameAndOriginView::Create(icon_image, title,
+                                                        start_url),
+                    views::BubbleDialogModelHost::FieldType::kControl))
+            .AddParagraph(
+                ui::DialogModelLabel(description).set_is_secondary(),
+                l10n_util::GetStringUTF16(
+                    IDS_WEB_APP_DETAILED_INSTALL_DIALOG_DESCRIPTION_TITLE))
+            .AddOkButton(base::BindOnce(&WebAppInstallDialogDelegate::OnAccept,
+                                        delegate_weak_ptr),
+                         ui::DialogModel::Button::Params().SetLabel(
+                             l10n_util::GetStringUTF16(IDS_INSTALL)))
+            .AddCancelButton(base::BindOnce(
+                &WebAppInstallDialogDelegate::OnCancel, delegate_weak_ptr))
+            .SetCloseActionCallback(base::BindOnce(
+                &WebAppInstallDialogDelegate::OnClose, delegate_weak_ptr))
+            .AddCustomField(
+                std::make_unique<views::BubbleDialogModelHost::CustomView>(
+                    std::make_unique<ImageCarouselView>(screenshots),
+                    views::BubbleDialogModelHost::FieldType::kControl))
+            .SetDialogDestroyingCallback(base::BindOnce(
+                &WebAppInstallDialogDelegate::OnClose, delegate_weak_ptr))
+            .OverrideDefaultButton(ui::DialogButton::DIALOG_BUTTON_CANCEL)
+            .Build();
+  } else {
+    dialog_model =
+        ui::DialogModel::Builder(std::move(delegate))
+            .SetInternalName("WebAppDetailedInstallDialog")
+            .SetIcon(ui::ImageModel::FromImageSkia(icon_image))
+            .SetTitle(title)
+            .SetSubtitle(start_url_host_formatted_for_display)
+            .AddParagraph(
+                ui::DialogModelLabel(description).set_is_secondary(),
+                l10n_util::GetStringUTF16(
+                    IDS_WEB_APP_DETAILED_INSTALL_DIALOG_DESCRIPTION_TITLE))
+            .AddOkButton(base::BindOnce(&WebAppInstallDialogDelegate::OnAccept,
+                                        delegate_weak_ptr),
+                         ui::DialogModel::Button::Params().SetLabel(
+                             l10n_util::GetStringUTF16(IDS_INSTALL)))
+            .AddCancelButton(base::BindOnce(
+                &WebAppInstallDialogDelegate::OnCancel, delegate_weak_ptr))
+            .SetCloseActionCallback(base::BindOnce(
+                &WebAppInstallDialogDelegate::OnClose, delegate_weak_ptr))
+            .AddCustomField(
+                std::make_unique<views::BubbleDialogModelHost::CustomView>(
+                    std::make_unique<ImageCarouselView>(screenshots),
+                    views::BubbleDialogModelHost::FieldType::kControl))
+            .SetDialogDestroyingCallback(base::BindOnce(
+                &WebAppInstallDialogDelegate::OnClose, delegate_weak_ptr))
+            .OverrideDefaultButton(ui::DialogButton::DIALOG_BUTTON_CANCEL)
+            .Build();
+  }
 
   auto dialog = views::BubbleDialogModelHost::CreateModal(
       std::move(dialog_model), ui::MODAL_TYPE_CHILD);
diff --git a/chrome/browser/ui/views/webauthn/authenticator_gpm_arbitrary_pin_sheet_view.cc b/chrome/browser/ui/views/webauthn/authenticator_gpm_arbitrary_pin_sheet_view.cc
new file mode 100644
index 0000000..afdfdc2
--- /dev/null
+++ b/chrome/browser/ui/views/webauthn/authenticator_gpm_arbitrary_pin_sheet_view.cc
@@ -0,0 +1,43 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/webauthn/authenticator_gpm_arbitrary_pin_sheet_view.h"
+
+#include "chrome/browser/ui/views/webauthn/authenticator_client_pin_entry_view.h"
+
+AuthenticatorGPMArbitraryPinSheetView::AuthenticatorGPMArbitraryPinSheetView(
+    std::unique_ptr<AuthenticatorGPMArbitraryPinSheetModel> sheet_model)
+    : AuthenticatorRequestSheetView(std::move(sheet_model)) {}
+
+AuthenticatorGPMArbitraryPinSheetView::
+    ~AuthenticatorGPMArbitraryPinSheetView() = default;
+
+AuthenticatorGPMArbitraryPinSheetModel*
+AuthenticatorGPMArbitraryPinSheetView::gpm_arbitrary_pin_sheet_model() {
+  return static_cast<AuthenticatorGPMArbitraryPinSheetModel*>(model());
+}
+
+std::pair<std::unique_ptr<views::View>,
+          AuthenticatorGPMArbitraryPinSheetView::AutoFocus>
+AuthenticatorGPMArbitraryPinSheetView::BuildStepSpecificContent() {
+  // TODO(rgod): Use different view when mocks are ready or re-use and possibly
+  // rename client pin.
+  return std::make_pair(
+      std::make_unique<AuthenticatorClientPinEntryView>(
+          this, /*show_confirmation_text_field=*/gpm_arbitrary_pin_sheet_model()
+                        ->mode() ==
+                    AuthenticatorGPMArbitraryPinSheetModel::Mode::kPinCreate),
+      AutoFocus::kYes);
+}
+
+void AuthenticatorGPMArbitraryPinSheetView::OnPincodeChanged(
+    std::u16string pin_code) {
+  gpm_arbitrary_pin_sheet_model()->SetPin(std::move(pin_code));
+}
+
+void AuthenticatorGPMArbitraryPinSheetView::OnConfirmationChanged(
+    std::u16string pin_confirmation) {
+  gpm_arbitrary_pin_sheet_model()->SetPinConfirmation(
+      std::move(pin_confirmation));
+}
diff --git a/chrome/browser/ui/views/webauthn/authenticator_gpm_arbitrary_pin_sheet_view.h b/chrome/browser/ui/views/webauthn/authenticator_gpm_arbitrary_pin_sheet_view.h
new file mode 100644
index 0000000..7624553
--- /dev/null
+++ b/chrome/browser/ui/views/webauthn/authenticator_gpm_arbitrary_pin_sheet_view.h
@@ -0,0 +1,40 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_WEBAUTHN_AUTHENTICATOR_GPM_ARBITRARY_PIN_SHEET_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_WEBAUTHN_AUTHENTICATOR_GPM_ARBITRARY_PIN_SHEET_VIEW_H_
+
+#include "chrome/browser/ui/views/webauthn/authenticator_client_pin_entry_view.h"
+#include "chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.h"
+#include "chrome/browser/ui/webauthn/sheet_models.h"
+
+// Represents a sheet in the Web Authentication request dialog that allows the
+// user to enter an arbitrary (alphanumeric) GPM pin code used in passkeys flow.
+class AuthenticatorGPMArbitraryPinSheetView
+    : public AuthenticatorRequestSheetView,
+      public AuthenticatorClientPinEntryView::Delegate {
+ public:
+  explicit AuthenticatorGPMArbitraryPinSheetView(
+      std::unique_ptr<AuthenticatorGPMArbitraryPinSheetModel> sheet_model);
+
+  AuthenticatorGPMArbitraryPinSheetView(
+      const AuthenticatorGPMArbitraryPinSheetView&) = delete;
+  AuthenticatorGPMArbitraryPinSheetView& operator=(
+      const AuthenticatorGPMArbitraryPinSheetView&) = delete;
+
+  ~AuthenticatorGPMArbitraryPinSheetView() override;
+
+ private:
+  AuthenticatorGPMArbitraryPinSheetModel* gpm_arbitrary_pin_sheet_model();
+
+  // AuthenticatorRequestSheetView:
+  std::pair<std::unique_ptr<views::View>, AutoFocus> BuildStepSpecificContent()
+      override;
+
+  // AuthenticatorClientPinEntryView::Delegate:
+  void OnPincodeChanged(std::u16string pin_code) override;
+  void OnConfirmationChanged(std::u16string pin_confirmation) override;
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_WEBAUTHN_AUTHENTICATOR_GPM_ARBITRARY_PIN_SHEET_VIEW_H_
diff --git a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
index 6cda02b..2c4af01 100644
--- a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
+++ b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/ui/autofill/payments/webauthn_dialog_model.h"
 #include "chrome/browser/ui/views/webauthn/authenticator_bio_enrollment_sheet_view.h"
 #include "chrome/browser/ui/views/webauthn/authenticator_client_pin_entry_sheet_view.h"
+#include "chrome/browser/ui/views/webauthn/authenticator_gpm_arbitrary_pin_sheet_view.h"
 #include "chrome/browser/ui/views/webauthn/authenticator_gpm_pin_sheet_view.h"
 #include "chrome/browser/ui/views/webauthn/authenticator_multi_source_picker_sheet_view.h"
 #include "chrome/browser/ui/views/webauthn/authenticator_paask_sheet_view.h"
@@ -347,6 +348,18 @@
               AuthenticatorGPMPinSheetModel::Mode::kPinEntry,
               dialog_model->gpm_pin_error()));
       break;
+    case Step::kGPMCreateArbitraryPin:
+      sheet_view = std::make_unique<AuthenticatorGPMArbitraryPinSheetView>(
+          std::make_unique<AuthenticatorGPMArbitraryPinSheetModel>(
+              dialog_model,
+              AuthenticatorGPMArbitraryPinSheetModel::Mode::kPinCreate));
+      break;
+    case Step::kGPMEnterArbitraryPin:
+      sheet_view = std::make_unique<AuthenticatorGPMArbitraryPinSheetView>(
+          std::make_unique<AuthenticatorGPMArbitraryPinSheetModel>(
+              dialog_model,
+              AuthenticatorGPMArbitraryPinSheetModel::Mode::kPinEntry));
+      break;
     case Step::kNotStarted:
     case Step::kConditionalMediation:
     case Step::kClosed:
diff --git a/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc b/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc
index 1398142..5ad9a89 100644
--- a/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc
+++ b/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc
@@ -712,6 +712,12 @@
     } else if (name == "gpm_enter_pin") {
       model_->SetCurrentStepForTesting(
           AuthenticatorRequestDialogModel::Step::kGPMEnterPin);
+    } else if (name == "gpm_create_arbitrary_pin") {
+      model_->SetCurrentStepForTesting(
+          AuthenticatorRequestDialogModel::Step::kGPMCreateArbitraryPin);
+    } else if (name == "gpm_enter_arbitrary_pin") {
+      model_->SetCurrentStepForTesting(
+          AuthenticatorRequestDialogModel::Step::kGPMEnterArbitraryPin);
     } else {
       NOTREACHED();
     }
@@ -809,6 +815,16 @@
   ShowAndVerifyUi();
 }
 
+IN_PROC_BROWSER_TEST_F(GPMPasskeysAuthenticatorDialogTest,
+                       InvokeUi_gpm_create_arbitrary_pin) {
+  ShowAndVerifyUi();
+}
+
+IN_PROC_BROWSER_TEST_F(GPMPasskeysAuthenticatorDialogTest,
+                       InvokeUi_gpm_enter_arbitrary_pin) {
+  ShowAndVerifyUi();
+}
+
 #if BUILDFLAG(IS_MAC)
 IN_PROC_BROWSER_TEST_F(GPMPasskeysAuthenticatorDialogTest, InvokeUi_touchid) {
   ShowAndVerifyUi();
diff --git a/chrome/browser/ui/webauthn/sheet_models.cc b/chrome/browser/ui/webauthn/sheet_models.cc
index 9631aea..9d86896b 100644
--- a/chrome/browser/ui/webauthn/sheet_models.cc
+++ b/chrome/browser/ui/webauthn/sheet_models.cc
@@ -1654,3 +1654,75 @@
 void AuthenticatorGPMPinSheetModel::OnAccept() {
   dialog_model()->OnGPMPinEntered(pin_);
 }
+
+// AuthenticatorGPMArbitraryPinSheetModel ------------------------------------
+
+AuthenticatorGPMArbitraryPinSheetModel::AuthenticatorGPMArbitraryPinSheetModel(
+    AuthenticatorRequestDialogModel* dialog_model,
+    Mode mode)
+    : AuthenticatorSheetModelBase(dialog_model,
+                                  OtherMechanismButtonVisibility::kHidden),
+      mode_(mode) {
+  // TODO(rgod): Add correct illustration.
+  vector_illustrations_.emplace(kPasskeyHeaderIcon, kPasskeyHeaderDarkIcon);
+}
+
+AuthenticatorGPMArbitraryPinSheetModel::
+    ~AuthenticatorGPMArbitraryPinSheetModel() = default;
+
+void AuthenticatorGPMArbitraryPinSheetModel::SetPin(std::u16string pin) {
+  bool accept_button_enabled = IsAcceptButtonEnabled();
+  pin_ = std::move(pin);
+  if (accept_button_enabled != IsAcceptButtonEnabled()) {
+    dialog_model()->OnButtonsStateChange();
+  }
+}
+
+void AuthenticatorGPMArbitraryPinSheetModel::SetPinConfirmation(
+    std::u16string pin_confirmation) {
+  bool accept_button_enabled = IsAcceptButtonEnabled();
+  pin_confirmation_ = std::move(pin_confirmation);
+  if (accept_button_enabled != IsAcceptButtonEnabled()) {
+    dialog_model()->OnButtonsStateChange();
+  }
+}
+
+std::u16string AuthenticatorGPMArbitraryPinSheetModel::GetStepTitle() const {
+  switch (mode_) {
+    case Mode::kPinCreate:
+      return u"Create a PIN for your Google Password Manager (UNTRANSLATED)";
+    case Mode::kPinEntry:
+      return u"Enter your PIN for your Google Password Manager (UNTRANSLATED)";
+  }
+}
+
+std::u16string AuthenticatorGPMArbitraryPinSheetModel::GetStepDescription()
+    const {
+  switch (mode_) {
+    case Mode::kPinCreate:
+      return u"Your PIN protects your data. You'll need it when you want to "
+             u"start using your passkeys on new devices. (UNTRANSLATED)";
+    case Mode::kPinEntry:
+      return u"Sign in with your passkey to example.com as example@gmail.com "
+             u"(UNTRANSLATED)";
+  }
+}
+
+bool AuthenticatorGPMArbitraryPinSheetModel::IsAcceptButtonVisible() const {
+  return true;
+}
+
+bool AuthenticatorGPMArbitraryPinSheetModel::IsAcceptButtonEnabled() const {
+  return pin_.length() > 0 && pin_confirmation_.length() > 0;
+}
+
+std::u16string AuthenticatorGPMArbitraryPinSheetModel::GetAcceptButtonLabel()
+    const {
+  return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CONTINUE);
+}
+
+void AuthenticatorGPMArbitraryPinSheetModel::OnAccept() {
+  // TODO(rgod): Handle pin mismatch error.
+  // TODO(rgod): Possibly add OnGPMArbitraryPinEntered().
+  dialog_model()->OnGPMPinEntered(pin_);
+}
diff --git a/chrome/browser/ui/webauthn/sheet_models.h b/chrome/browser/ui/webauthn/sheet_models.h
index 1f22f49..418aef16 100644
--- a/chrome/browser/ui/webauthn/sheet_models.h
+++ b/chrome/browser/ui/webauthn/sheet_models.h
@@ -678,11 +678,11 @@
   void OnAccept() override;
 };
 
-// The sheet shown when the user is entering a GPM pin.
+// The sheet shown when the user is entering a digit-only GPM pin.
 class AuthenticatorGPMPinSheetModel : public AuthenticatorSheetModelBase {
  public:
   // Indicates whether the view should accommodate creating a new pin or
-  // entering an exisiting one.
+  // entering an existing one.
   enum class Mode { kPinCreate, kPinEntry };
 
   explicit AuthenticatorGPMPinSheetModel(
@@ -713,4 +713,38 @@
   const AuthenticatorRequestDialogModel::GpmPinError error_;
 };
 
+// The sheet shown when the user is entering an arbitrary (alphanumeric) pin.
+class AuthenticatorGPMArbitraryPinSheetModel
+    : public AuthenticatorSheetModelBase {
+ public:
+  // Indicates whether the view should accommodate creating a new pin or
+  // entering an existing one.
+  enum class Mode { kPinCreate, kPinEntry };
+
+  explicit AuthenticatorGPMArbitraryPinSheetModel(
+      AuthenticatorRequestDialogModel* dialog_model,
+      Mode mode);
+  ~AuthenticatorGPMArbitraryPinSheetModel() override;
+
+  // Sets currently typed pin in the sheet.
+  void SetPin(std::u16string pin);
+  // Sets currently typed pin confirmation in the sheet.
+  void SetPinConfirmation(std::u16string pin_confirmation);
+
+  Mode mode() { return mode_; }
+
+ private:
+  // AuthenticatorSheetModelBase:
+  std::u16string GetStepTitle() const override;
+  std::u16string GetStepDescription() const override;
+  bool IsAcceptButtonEnabled() const override;
+  bool IsAcceptButtonVisible() const override;
+  std::u16string GetAcceptButtonLabel() const override;
+  void OnAccept() override;
+
+  std::u16string pin_;
+  std::u16string pin_confirmation_;
+  const Mode mode_;
+};
+
 #endif  // CHROME_BROWSER_UI_WEBAUTHN_SHEET_MODELS_H_
diff --git a/chrome/browser/ui/webui/signin/turn_sync_on_helper_unittest.cc b/chrome/browser/ui/webui/signin/turn_sync_on_helper_unittest.cc
index c6c6d04d..c1ccd00 100644
--- a/chrome/browser/ui/webui/signin/turn_sync_on_helper_unittest.cc
+++ b/chrome/browser/ui/webui/signin/turn_sync_on_helper_unittest.cc
@@ -1427,12 +1427,13 @@
   CheckDelegateCalls();
   CheckSigninMetrics({
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
-    .sign_in_access_point = signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN,
+      .sign_in_access_point =
+          signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS,
 #else
-    .sign_in_access_point = kAccessPoint,
+      .sign_in_access_point = kAccessPoint,
 #endif
-    .sign_in_recorded = true, .sync_opt_in_started = true
-  });
+      .sign_in_recorded = true,
+      .sync_opt_in_started = true});
 }
 
 // Abort after the enterprise confirmation prompt.
@@ -1513,12 +1514,13 @@
   CheckDelegateCalls();
   CheckSigninMetrics({
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
-    .sign_in_access_point = signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN,
+      .sign_in_access_point =
+          signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS,
 #else
-    .sign_in_access_point = kAccessPoint,
+      .sign_in_access_point = kAccessPoint,
 #endif
-    .sign_in_recorded = true, .sync_opt_in_started = true
-  });
+      .sign_in_recorded = true,
+      .sync_opt_in_started = true});
 }
 
 // Wait for cloud policy to be merged before showing sync confirmation.
@@ -1612,12 +1614,13 @@
   CheckDelegateCalls();
   CheckSigninMetrics({
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
-    .sign_in_access_point = signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN,
+      .sign_in_access_point =
+          signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS,
 #else
-    .sign_in_access_point = kAccessPoint,
+      .sign_in_access_point = kAccessPoint,
 #endif
-    .sign_in_recorded = true, .sync_opt_in_started = true
-  });
+      .sign_in_recorded = true,
+      .sync_opt_in_started = true});
 }
 
 class TurnSyncOnHelperSearchEngineTest : public TurnSyncOnHelperTest {
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.h b/chrome/browser/webauthn/authenticator_request_dialog_model.h
index be14ac81..338bc0f4 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model.h
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model.h
@@ -157,13 +157,22 @@
     kAttestationPermissionRequest,
     kEnterpriseAttestationPermissionRequest,
 
-    kCreatePasskey,
-    kRecoverSecurityDomain,
-    kTrustThisComputer,
-    kGPMCreatePasskey,
+    // GPM Pin (6-digit).
     kGPMCreatePin,
     kGPMEnterPin,
+
+    // GPM Pin (alphanumeric).
+    kGPMCreateArbitraryPin,
+    kGPMEnterArbitraryPin,
+
+    // GPM passkey creation.
     kGPMOnboarding,
+    kGPMCreatePasskey,
+    kCreatePasskey,
+
+    // Device bootstrap to use GPM passkeys.
+    kRecoverSecurityDomain,
+    kTrustThisComputer,
     kWaitingForEnclave,
 
     // User verification prompt for GPM for demo purposes.
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt
index 0917b71..7a4a784 100644
--- a/chrome/build/android-arm32.pgo.txt
+++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@
-chrome-android32-main-1709251103-e8d56921b9676e3c8c28dd83222f6d9af53ff132-3c4dd528ce3d74fc6fbb5168d0d0578f495ae3ac.profdata
+chrome-android32-main-1709276042-021209abe7839a98639a33ff9795ff37325566a3-40412b90c691904ff438f6c25a50616b4c3c957f.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index 748107f8..136e122 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1709207912-0f6aee8ce2f22a1280f3a2637a959b7b735562f2-2d819bfbac4fb4878136cb51604920b8d923177b.profdata
+chrome-android64-main-1709276042-34a46b3b3c4a1875b57514e07d52dab9dd66a052-40412b90c691904ff438f6c25a50616b4c3c957f.profdata
diff --git a/chrome/build/lacros64.pgo.txt b/chrome/build/lacros64.pgo.txt
index e54bab1..35153885 100644
--- a/chrome/build/lacros64.pgo.txt
+++ b/chrome/build/lacros64.pgo.txt
@@ -1 +1 @@
-chrome-chromeos-amd64-generic-main-1709208653-d793c19e822ef633112f16b66fb5561b595f6cb5-2e1af413772c303b20662a475629c53534a7350b.profdata
+chrome-chromeos-amd64-generic-main-1709276042-35315db5cc505753be379587f5cdd664f4bd1270-40412b90c691904ff438f6c25a50616b4c3c957f.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 525d7ee8..19c02c2 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1709207912-3b88c646b0529b1408183526ea717c6629e434bb-2d819bfbac4fb4878136cb51604920b8d923177b.profdata
+chrome-linux-main-1709272542-e669012cc90ec265c2e83e90155129bafa222dd6-e545f27e7821d93e0acbc119c92f648d52c14bcb.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index d93ed7fe..6e2f827 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1709243983-50785a75cb830e0f2240fd1b19b319a71af9aaab-d13c4884812124f4acaa95b49bf2d9031dc14546.profdata
+chrome-mac-arm-main-1709308479-db231f1643e8ed09f840adc2dacdc5662e679748-d8280999ac0aaf51e6c74f9f913a366dd233a967.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 30e459e..bc570ca 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1709229418-705274331d29f367c0fc74527d8e650dde99c159-b0a7a7040e49ebde707133bb7b28d1df2acbe3f5.profdata
+chrome-mac-main-1709276042-42b1ac4d4c7af78a7679e3eafb4db1cc755b8285-40412b90c691904ff438f6c25a50616b4c3c957f.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt
index b89400b..86c359c 100644
--- a/chrome/build/win-arm64.pgo.txt
+++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@
-chrome-win-arm64-main-1709229418-e645b1867e6096f5b77ee9acbd5e6bca83117273-b0a7a7040e49ebde707133bb7b28d1df2acbe3f5.profdata
+chrome-win-arm64-main-1709276042-39d3a7122b2f77822abfa6ffef2785e2538a586d-40412b90c691904ff438f6c25a50616b4c3c957f.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 773e267..3353718 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1709240374-c1fa17f359931ac60670f45b775a845e91cf471b-a24027fc5f6980ae3924b10ebafca851e62c9b14.profdata
+chrome-win32-main-1709276042-ebbf33308ab763c820e92c7783c94200b825c85c-40412b90c691904ff438f6c25a50616b4c3c957f.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 76dc689c..bd0a93e0 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1709240374-555542797fa7ce9ea2319c141916825658cb036a-a24027fc5f6980ae3924b10ebafca851e62c9b14.profdata
+chrome-win64-main-1709276042-af8a560556a7edb2c894d6c83cb62b40d8211894-40412b90c691904ff438f6c25a50616b4c3c957f.profdata
diff --git a/chrome/common/extensions/api/pdf_viewer_private.idl b/chrome/common/extensions/api/pdf_viewer_private.idl
index fac71208..677a600 100644
--- a/chrome/common/extensions/api/pdf_viewer_private.idl
+++ b/chrome/common/extensions/api/pdf_viewer_private.idl
@@ -60,6 +60,11 @@
     static void isPdfOcrAlwaysActive(
         IsPdfOcrAlwaysActiveCallback callback);
 
+    // Sets the current tab title to `title` for a full-page PDF.
+    static void setPdfDocumentTitle(
+        DOMString title,
+        optional VoidCallback callback);
+
     // Sets a pref value for PDF OCR.
     // |value|: The new value of the pref.
     // |callback|: The callback for whether the pref was set or not.
diff --git a/chrome/common/extensions/api/terminal_private.json b/chrome/common/extensions/api/terminal_private.json
index 3ad134c..ffc1f87 100644
--- a/chrome/common/extensions/api/terminal_private.json
+++ b/chrome/common/extensions/api/terminal_private.json
@@ -238,10 +238,6 @@
               "name": "info",
               "type": "object",
               "properties": {
-                "alternative_emulator": {
-                  "description": "True if alternative emulator flag is enabled.",
-                  "type": "boolean"
-                },
                 "tast": {
                   "description": "True if tast extension is installed.",
                   "type": "boolean"
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn
index 9a4608e2..cc1b273c 100644
--- a/chrome/renderer/BUILD.gn
+++ b/chrome/renderer/BUILD.gn
@@ -101,8 +101,6 @@
     "url_loader_throttle_provider_impl.h",
     "v8_unwinder.cc",
     "v8_unwinder.h",
-    "web_link_preview_triggerer_impl.cc",
-    "web_link_preview_triggerer_impl.h",
     "websocket_handshake_throttle_provider_impl.cc",
     "websocket_handshake_throttle_provider_impl.h",
     "worker_content_settings_client.cc",
diff --git a/chrome/renderer/OWNERS b/chrome/renderer/OWNERS
index 4a01ff05..5a76272 100644
--- a/chrome/renderer/OWNERS
+++ b/chrome/renderer/OWNERS
@@ -20,6 +20,3 @@
 per-file chrome_content_renderer_client.cc=*
 per-file chrome_content_renderer_client.h=*
 per-file chrome_content_renderer_client_unittest.cc=*
-
-# Link Preview.
-per-file web_link_preview_triggerer_impl*=file://chrome/browser/preloading/preview/OWNERS
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 5e6f1d9f..f04d94e3a 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -65,7 +65,6 @@
 #include "chrome/renderer/trusted_vault_encryption_keys_extension.h"
 #include "chrome/renderer/url_loader_throttle_provider_impl.h"
 #include "chrome/renderer/v8_unwinder.h"
-#include "chrome/renderer/web_link_preview_triggerer_impl.h"
 #include "chrome/renderer/websocket_handshake_throttle_provider_impl.h"
 #include "chrome/renderer/worker_content_settings_client.h"
 #include "chrome/services/speech/buildflags/buildflags.h"
@@ -1854,8 +1853,3 @@
                   network::mojom::ContentSecurityPolicySource::kHTTP});
 #endif
 }
-
-std::unique_ptr<blink::WebLinkPreviewTriggerer>
-ChromeContentRendererClient::CreateLinkPreviewTriggerer() {
-  return ::CreateWebLinkPreviewTriggerer();
-}
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index 3b7c2fe4..68d8afb 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -210,8 +210,6 @@
   void AppendContentSecurityPolicy(
       const blink::WebURL& url,
       blink::WebVector<blink::WebContentSecurityPolicyHeader>* csp) override;
-  std::unique_ptr<blink::WebLinkPreviewTriggerer> CreateLinkPreviewTriggerer()
-      override;
 
 #if BUILDFLAG(ENABLE_PLUGINS)
   static blink::WebPlugin* CreatePlugin(
diff --git a/chrome/renderer/web_link_preview_triggerer_impl.cc b/chrome/renderer/web_link_preview_triggerer_impl.cc
deleted file mode 100644
index 78d5a9a..0000000
--- a/chrome/renderer/web_link_preview_triggerer_impl.cc
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/renderer/web_link_preview_triggerer_impl.h"
-
-#include "base/functional/bind.h"
-#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/common/input/web_input_event.h"
-#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/public/web/web_document.h"
-#include "third_party/blink/public/web/web_element.h"
-
-namespace {
-
-constexpr base::TimeDelta kHoverThreshold = base::Milliseconds(800);
-constexpr base::TimeDelta kLongPressThreshold = base::Milliseconds(800);
-
-blink::WebURL GetURL(blink::WebElement& anchor_element) {
-  if (anchor_element.IsNull()) {
-    return blink::WebURL();
-  }
-
-  blink::WebString href = anchor_element.GetAttribute("href");
-  if (href.IsNull()) {
-    return blink::WebURL();
-  }
-
-  // TODO(b:325558426): Mimic HTMLAnchorElement::Href and
-  // StripLeadingAndTrailingHTMLSpaces.
-  blink::WebURL url = anchor_element.GetDocument().CompleteURL(href);
-
-  if (!url.IsValid()) {
-    return blink::WebURL();
-  }
-
-  return url;
-}
-
-}  // namespace
-
-std::unique_ptr<blink::WebLinkPreviewTriggerer>
-CreateWebLinkPreviewTriggerer() {
-  if (!base::FeatureList::IsEnabled(blink::features::kLinkPreview)) {
-    return nullptr;
-  }
-
-  switch (blink::features::kLinkPreviewTriggerType.Get()) {
-    // Alt+click is handled by navigation policy.
-    case blink::features::LinkPreviewTriggerType::kAltClick:
-      return nullptr;
-    case blink::features::LinkPreviewTriggerType::kAltHover:
-      return std::make_unique<WebLinkPreviewTriggererAltHover>();
-    case blink::features::LinkPreviewTriggerType::kLongPress:
-      return std::make_unique<WebLinkPreviewTriggererLongPress>();
-  }
-}
-
-WebLinkPreviewTriggererAltHover::WebLinkPreviewTriggererAltHover()
-    : timer_(std::make_unique<base::OneShotTimer>()) {}
-
-WebLinkPreviewTriggererAltHover::~WebLinkPreviewTriggererAltHover() = default;
-
-WebLinkPreviewTriggererAltHover::WebLinkPreviewTriggererAltHover(
-    WebLinkPreviewTriggererAltHover&& other) = default;
-
-WebLinkPreviewTriggererAltHover& WebLinkPreviewTriggererAltHover::operator=(
-    WebLinkPreviewTriggererAltHover&& other) = default;
-
-void WebLinkPreviewTriggererAltHover::MaybeChangedKeyEventModifier(
-    int modifiers) {
-  bool is_alt_on = (modifiers & blink::WebInputEvent::kAltKey) != 0;
-  UpdateState(is_alt_on, anchor_element_);
-}
-
-void WebLinkPreviewTriggererAltHover::DidChangeHoverElement(
-    blink::WebElement element) {
-  blink::WebElement most_inner_anchor_element;
-  for (blink::WebNode curr = element; !curr.IsNull() && curr.IsElementNode();
-       curr = curr.ParentNode()) {
-    blink::WebElement curr_as_element = curr.To<blink::WebElement>();
-    if (curr_as_element.HasHTMLTagName("a")) {
-      most_inner_anchor_element = curr_as_element;
-      break;
-    }
-  }
-
-  UpdateState(is_alt_on_, most_inner_anchor_element);
-}
-
-void WebLinkPreviewTriggererAltHover::UpdateState(
-    bool is_alt_on,
-    blink::WebElement anchor_element) {
-  if (is_alt_on_ == is_alt_on && anchor_element_ == anchor_element) {
-    return;
-  }
-
-  is_alt_on_ = is_alt_on;
-  anchor_element_ = anchor_element;
-
-  if (is_alt_on_ && !GetURL(anchor_element).IsNull()) {
-    timer_->Start(
-        FROM_HERE, kHoverThreshold,
-        base::BindOnce(&WebLinkPreviewTriggererAltHover::InitiatePreview,
-                       // base::Unretained() is safe since `this` owns `timer_`.
-                       base::Unretained(this)));
-  } else {
-    timer_->Stop();
-  }
-}
-
-void WebLinkPreviewTriggererAltHover::InitiatePreview() {
-  blink::WebDocument document = anchor_element_.GetDocument();
-  if (document.IsNull()) {
-    return;
-  }
-
-  blink::WebURL url = GetURL(anchor_element_);
-  if (url.IsNull()) {
-    return;
-  }
-
-  document.InitiatePreview(url);
-}
-
-WebLinkPreviewTriggererLongPress::WebLinkPreviewTriggererLongPress()
-    : timer_(std::make_unique<base::OneShotTimer>()) {}
-
-WebLinkPreviewTriggererLongPress::~WebLinkPreviewTriggererLongPress() = default;
-
-WebLinkPreviewTriggererLongPress::WebLinkPreviewTriggererLongPress(
-    WebLinkPreviewTriggererLongPress&& other) = default;
-
-WebLinkPreviewTriggererLongPress& WebLinkPreviewTriggererLongPress::operator=(
-    WebLinkPreviewTriggererLongPress&& other) = default;
-
-void WebLinkPreviewTriggererLongPress::DidAnchorElementReceiveMouseEvent(
-    blink::WebElement anchor_element,
-    blink::WebMouseEvent mouse_event) {
-  if (mouse_event.GetType() == blink::WebInputEvent::Type::kMouseDown &&
-      mouse_event.button == blink::WebMouseEvent::Button::kLeft &&
-      mouse_event.ClickCount() == 1) {
-    anchor_element_ = anchor_element;
-    timer_->Start(
-        FROM_HERE, kLongPressThreshold,
-        base::BindOnce(&WebLinkPreviewTriggererLongPress::InitiatePreview,
-                       // base::Unretained() is safe since `this` owns `timer_`.
-                       base::Unretained(this)));
-    return;
-  }
-
-  if (mouse_event.GetType() == blink::WebInputEvent::Type::kMouseUp &&
-      mouse_event.button == blink::WebMouseEvent::Button::kLeft) {
-    anchor_element_ = blink::WebElement();
-    timer_->Stop();
-    return;
-  }
-
-  if (mouse_event.GetType() == blink::WebInputEvent::Type::kMouseLeave) {
-    anchor_element_ = blink::WebElement();
-    timer_->Stop();
-    return;
-  }
-}
-
-void WebLinkPreviewTriggererLongPress::InitiatePreview() {
-  blink::WebDocument document = anchor_element_.GetDocument();
-  if (document.IsNull()) {
-    return;
-  }
-
-  blink::WebURL url = GetURL(anchor_element_);
-  if (url.IsNull()) {
-    return;
-  }
-
-  document.InitiatePreview(url);
-}
diff --git a/chrome/renderer/web_link_preview_triggerer_impl.h b/chrome/renderer/web_link_preview_triggerer_impl.h
deleted file mode 100644
index f98fda8..0000000
--- a/chrome/renderer/web_link_preview_triggerer_impl.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_RENDERER_WEB_LINK_PREVIEW_TRIGGERER_IMPL_H_
-#define CHROME_RENDERER_WEB_LINK_PREVIEW_TRIGGERER_IMPL_H_
-
-#include "base/timer/timer.h"
-#include "third_party/blink/public/web/web_link_preview_triggerer.h"
-
-// Creates appropriate WebLinkPreviewTriggerer depending on feature flag and
-// params.
-std::unique_ptr<blink::WebLinkPreviewTriggerer> CreateWebLinkPreviewTriggerer();
-
-// Observes events in frame and triggers Link Preview: Alt+hover trigger.
-//
-// This class tracks the state "is Alt key pressed" and mouse hovered anchor
-// element. Alt key tracking is done by observing modifiers for each keyboard
-// events and mouse leave event. See the comment of `last_key_event_modifiers_`
-// for more details and limitations.
-class WebLinkPreviewTriggererAltHover final
-    : public blink::WebLinkPreviewTriggerer {
- public:
-  WebLinkPreviewTriggererAltHover();
-
-  ~WebLinkPreviewTriggererAltHover() override;
-
-  // Movable but not copyable.
-  WebLinkPreviewTriggererAltHover(WebLinkPreviewTriggererAltHover&& other);
-  WebLinkPreviewTriggererAltHover& operator=(
-      WebLinkPreviewTriggererAltHover&& other);
-  WebLinkPreviewTriggererAltHover(const WebLinkPreviewTriggererAltHover&) =
-      delete;
-  WebLinkPreviewTriggererAltHover& operator=(
-      const WebLinkPreviewTriggererAltHover&) = delete;
-
-  // Implements blink::WebLinkPreviewTriggerer.
-  void MaybeChangedKeyEventModifier(int modifiers) override;
-  void DidChangeHoverElement(blink::WebElement element) override;
-
- private:
-  void UpdateState(bool is_alt_on, blink::WebElement anchor_element);
-
-  void InitiatePreview();
-
-  std::unique_ptr<base::OneShotTimer> timer_;
-
-  bool is_alt_on_ = false;
-  blink::WebElement anchor_element_;
-};
-
-// Observes events in frame and triggers Link Preview: Long press trigger.
-class WebLinkPreviewTriggererLongPress final
-    : public blink::WebLinkPreviewTriggerer {
- public:
-  WebLinkPreviewTriggererLongPress();
-
-  ~WebLinkPreviewTriggererLongPress() override;
-
-  // Movable but not copyable.
-  WebLinkPreviewTriggererLongPress(WebLinkPreviewTriggererLongPress&& other);
-  WebLinkPreviewTriggererLongPress& operator=(
-      WebLinkPreviewTriggererLongPress&& other);
-  WebLinkPreviewTriggererLongPress(const WebLinkPreviewTriggererLongPress&) =
-      delete;
-  WebLinkPreviewTriggererLongPress& operator=(
-      const WebLinkPreviewTriggererLongPress&) = delete;
-
-  // Implements blink::WebLinkPreviewTriggerer.
-  void DidAnchorElementReceiveMouseEvent(
-      blink::WebElement anchor_element,
-      blink::WebMouseEvent mouse_event) override;
-
- private:
-  void InitiatePreview();
-
-  std::unique_ptr<base::OneShotTimer> timer_;
-
-  blink::WebElement anchor_element_;
-};
-
-#endif  // CHROME_RENDERER_WEB_LINK_PREVIEW_TRIGGERER_IMPL_H_
diff --git a/chrome/test/base/ui_test_utils.cc b/chrome/test/base/ui_test_utils.cc
index 4cf352e..41602d9 100644
--- a/chrome/test/base/ui_test_utils.cc
+++ b/chrome/test/base/ui_test_utils.cc
@@ -603,6 +603,17 @@
   waiter.Wait();
 }
 
+Browser* OpenNewEmptyWindowAndWaitUntilSetAsLastActive(
+    Profile* profile,
+    bool should_trigger_session_restore) {
+  BrowserChangeObserver new_browser_observer(
+      nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded);
+  chrome::NewEmptyWindow(profile, should_trigger_session_restore);
+  Browser* new_browser = new_browser_observer.Wait();
+  WaitForBrowserSetLastActive(new_browser);
+  return new_browser;
+}
+
 void SendToOmniboxAndSubmit(Browser* browser,
                             const std::string& input,
                             base::TimeTicks match_selection_timestamp) {
diff --git a/chrome/test/base/ui_test_utils.h b/chrome/test/base/ui_test_utils.h
index 509c5e82..b2e7b4a 100644
--- a/chrome/test/base/ui_test_utils.h
+++ b/chrome/test/base/ui_test_utils.h
@@ -318,6 +318,13 @@
     Browser* browser,
     bool wait_for_set_last_active_observed = false);
 
+// Opens a new browser window with chrome::NewEmptyWindow() and wait until it
+// becomes the last active browser.
+// Returns newly created browser.
+Browser* OpenNewEmptyWindowAndWaitUntilSetAsLastActive(
+    Profile* profile,
+    bool should_trigger_session_restore = false);
+
 // Send the given text to the omnibox and wait until it's updated.
 void SendToOmniboxAndSubmit(
     Browser* browser,
diff --git a/chrome/test/data/pdf/BUILD.gn b/chrome/test/data/pdf/BUILD.gn
index 7a4597e..b77e416 100644
--- a/chrome/test/data/pdf/BUILD.gn
+++ b/chrome/test/data/pdf/BUILD.gn
@@ -69,6 +69,7 @@
   }
 
   ts_definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/chrome_test.d.ts",
     "//tools/typescript/definitions/metrics_private.d.ts",
     "//tools/typescript/definitions/mime_handler_private.d.ts",
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index d265a916..4ffa5cf 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -323,6 +323,7 @@
     "//ui/webui/resources/js:build_ts",
   ]
   definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/chrome_send.d.ts",
     "//tools/typescript/definitions/chrome_timeticks.d.ts",
     "//tools/typescript/definitions/dom_automation_controller.d.ts",
diff --git a/chrome/test/data/webui/chromeos/ash_common/cr_elements/BUILD.gn b/chrome/test/data/webui/chromeos/ash_common/cr_elements/BUILD.gn
index e0b2c47..9162706e 100644
--- a/chrome/test/data/webui/chromeos/ash_common/cr_elements/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/ash_common/cr_elements/BUILD.gn
@@ -53,7 +53,10 @@
   # Using custom config to turn off useDefineForClassFields TS compiler flag
   # which is necessary when defining Polymer elements.
   ts_tsconfig_base = "tsconfig_base.json"
-  ts_definitions = [ "//tools/typescript/definitions/settings_private.d.ts" ]
+  ts_definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
+    "//tools/typescript/definitions/settings_private.d.ts",
+  ]
 
   ts_deps = [
     "//ash/webui/common/resources/cr_elements:build_ts",
diff --git a/chrome/test/data/webui/chromeos/edu_coexistence/BUILD.gn b/chrome/test/data/webui/chromeos/edu_coexistence/BUILD.gn
index 8240434e..3c4fed73 100644
--- a/chrome/test/data/webui/chromeos/edu_coexistence/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/edu_coexistence/BUILD.gn
@@ -45,6 +45,7 @@
     "//chrome/test/data/webui/chromeos/arc_account_picker/test_util.d.ts",
     "//tools/typescript/definitions/webview_tag.d.ts",
     "//tools/typescript/definitions/web_request.d.ts",
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/context_menus.d.ts",
     "//tools/typescript/definitions/tabs.d.ts",
     "//tools/typescript/definitions/extension_types.d.ts",
diff --git a/chrome/test/data/webui/chromeos/parent_access/BUILD.gn b/chrome/test/data/webui/chromeos/parent_access/BUILD.gn
index 2d9b8b7..a215ca0 100644
--- a/chrome/test/data/webui/chromeos/parent_access/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/parent_access/BUILD.gn
@@ -39,6 +39,7 @@
     "//tools/typescript/definitions/context_menus.d.ts",
     "//tools/typescript/definitions/tabs.d.ts",
     "//tools/typescript/definitions/extension_types.d.ts",
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/chrome_test.d.ts",
   ]
 }
diff --git a/chrome/test/data/webui/cr_components/BUILD.gn b/chrome/test/data/webui/cr_components/BUILD.gn
index 99c336c..cadfc3f 100644
--- a/chrome/test/data/webui/cr_components/BUILD.gn
+++ b/chrome/test/data/webui/cr_components/BUILD.gn
@@ -41,7 +41,10 @@
     }
   }
 
-  ts_definitions = [ "//tools/typescript/definitions/settings_private.d.ts" ]
+  ts_definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
+    "//tools/typescript/definitions/settings_private.d.ts",
+  ]
 
   ts_deps = [
     "//third_party/polymer/v3_0:library",
diff --git a/chrome/test/data/webui/cr_elements/BUILD.gn b/chrome/test/data/webui/cr_elements/BUILD.gn
index 9d50ef53..cb53e6f6 100644
--- a/chrome/test/data/webui/cr_elements/BUILD.gn
+++ b/chrome/test/data/webui/cr_elements/BUILD.gn
@@ -21,7 +21,6 @@
     "cr_drawer_test.ts",
     "cr_expand_button_test.ts",
     "cr_feedback_buttons_test.ts",
-    "cr_fingerprint_progress_arc_test.ts",
     "cr_focus_row_mixin_test.ts",
     "cr_grid_focus_test.ts",
     "cr_icon_button_test.ts",
@@ -71,6 +70,7 @@
   # which is necessary when defining Polymer elements.
   ts_tsconfig_base = "tsconfig_base.json"
   ts_definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/pending.d.ts",
     "//tools/typescript/definitions/settings_private.d.ts",
   ]
diff --git a/chrome/test/data/webui/cr_elements/cr_elements_browsertest.cc b/chrome/test/data/webui/cr_elements/cr_elements_browsertest.cc
index f6d7cf8..f91d7c8 100644
--- a/chrome/test/data/webui/cr_elements/cr_elements_browsertest.cc
+++ b/chrome/test/data/webui/cr_elements/cr_elements_browsertest.cc
@@ -187,14 +187,3 @@
 IN_PROC_BROWSER_TEST_F(CrElementsWithPixelOutputTest, MAYBE_CrLottie) {
   RunTest("cr_elements/cr_lottie_test.js", "mocha.run()");
 }
-
-// https://crbug.com/1044390 - maybe flaky on Mac?
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_CrFingerprintProgressArc DISABLED_CrFingerprintProgressArc
-#else
-#define MAYBE_CrFingerprintProgressArc CrFingerprintProgressArc
-#endif
-IN_PROC_BROWSER_TEST_F(CrElementsWithPixelOutputTest,
-                       MAYBE_CrFingerprintProgressArc) {
-  RunTest("cr_elements/cr_fingerprint_progress_arc_test.js", "mocha.run()");
-}
diff --git a/chrome/test/data/webui/cr_elements/cr_lit_element_test.ts b/chrome/test/data/webui/cr_elements/cr_lit_element_test.ts
index a7700f0f..41ea48a 100644
--- a/chrome/test/data/webui/cr_elements/cr_lit_element_test.ts
+++ b/chrome/test/data/webui/cr_elements/cr_lit_element_test.ts
@@ -86,6 +86,11 @@
         type: Boolean,
         notify: true,
       },
+
+      prop5: {
+        type: Boolean,
+        notify: true,
+      },
     };
   }
 
@@ -93,6 +98,7 @@
   prop2: boolean = false;
   prop3: boolean = false;
   propFour: boolean = false;
+  prop5: boolean|undefined = false;
 }
 
 customElements.define(
@@ -300,13 +306,21 @@
   test('PropertiesWithNotify', async function() {
     const element = document.createElement('cr-dummy-properties-with-notify');
 
-    // Ensure that properties without 'notify: true' don't trigger events.
     function unexpectedEventListener(e: Event) {
       assertNotReached(`Unexpected event caught: ${e.type}`);
     }
+
+    // Ensure that properties without 'notify: true' don't trigger events.
     element.addEventListener('prop2-changed', unexpectedEventListener);
     element.addEventListener('prop3-changed', unexpectedEventListener);
 
+    // Ensure that properties with 'notify: true' that
+    //   1) have a non-undefined initial value AND
+    //   2) are changed back to undefined before the element is connected
+    // also don't trigger updates.
+    element.addEventListener('prop5-changed', unexpectedEventListener);
+    element.prop5 = undefined;
+
     // Ensure that properties with 'notify: true' trigger events.
 
     // Case1: An event should be fired after the element is initialized to
diff --git a/chrome/test/data/webui/extensions/BUILD.gn b/chrome/test/data/webui/extensions/BUILD.gn
index 36681392..72d09364 100644
--- a/chrome/test/data/webui/extensions/BUILD.gn
+++ b/chrome/test/data/webui/extensions/BUILD.gn
@@ -68,12 +68,12 @@
     "//chrome/browser/resources/extensions:build_ts",
     "//third_party/lit/v3_0:build_ts",
     "//third_party/polymer/v3_0:library",
-    "//tools/typescript/definitions:library",
     "//ui/webui/resources/js:build_ts",
   ]
   ts_definitions = [
     "//tools/typescript/definitions/activity_log_private.d.ts",
     "//tools/typescript/definitions/developer_private.d.ts",
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/metrics_private.d.ts",
   ]
 }
diff --git a/chrome/test/data/webui/password_manager/BUILD.gn b/chrome/test/data/webui/password_manager/BUILD.gn
index 4190296..822665b 100644
--- a/chrome/test/data/webui/password_manager/BUILD.gn
+++ b/chrome/test/data/webui/password_manager/BUILD.gn
@@ -48,6 +48,7 @@
   }
 
   ts_definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/passwords_private.d.ts",
     "//tools/typescript/definitions/settings_private.d.ts",
   ]
diff --git a/chrome/test/data/webui/print_preview/BUILD.gn b/chrome/test/data/webui/print_preview/BUILD.gn
index 24f1f4e..d7a95f6 100644
--- a/chrome/test/data/webui/print_preview/BUILD.gn
+++ b/chrome/test/data/webui/print_preview/BUILD.gn
@@ -90,6 +90,7 @@
   ]
 
   ts_definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/pending.d.ts",
     "//tools/typescript/definitions/mime_handler_private.d.ts",
   ]
diff --git a/chrome/test/data/webui/settings/BUILD.gn b/chrome/test/data/webui/settings/BUILD.gn
index fcf88835..e80d210 100644
--- a/chrome/test/data/webui/settings/BUILD.gn
+++ b/chrome/test/data/webui/settings/BUILD.gn
@@ -37,6 +37,7 @@
     "file_system_site_entry_test.ts",
     "file_system_site_entry_item_test.ts",
     "file_system_site_list_test.ts",
+    "fingerprint_progress_arc_test.ts",
     "help_page_test.ts",
     "idle_load_test.ts",
     "on_startup_page_test.ts",
@@ -223,6 +224,7 @@
 
   ts_definitions = [
     "//tools/typescript/definitions/autofill_private.d.ts",
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/chrome_send.d.ts",
     "//tools/typescript/definitions/language_settings_private.d.ts",
     "//tools/typescript/definitions/management.d.ts",
diff --git a/chrome/test/data/webui/cr_elements/cr_fingerprint_progress_arc_test.ts b/chrome/test/data/webui/settings/fingerprint_progress_arc_test.ts
similarity index 93%
rename from chrome/test/data/webui/cr_elements/cr_fingerprint_progress_arc_test.ts
rename to chrome/test/data/webui/settings/fingerprint_progress_arc_test.ts
index c4b1ce8..43a362d 100644
--- a/chrome/test/data/webui/cr_elements/cr_fingerprint_progress_arc_test.ts
+++ b/chrome/test/data/webui/settings/fingerprint_progress_arc_test.ts
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'chrome://resources/cr_elements/cr_lottie/cr_lottie.js';
+import 'chrome://settings/lazy_load.js';
 
-import type {CrFingerprintProgressArcElement} from 'chrome://resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.js';
-import {FINGERPRINT_CHECK_DARK_URL, FINGERPRINT_CHECK_LIGHT_URL, FINGERPRINT_SCANNED_ICON_DARK, FINGERPRINT_SCANNED_ICON_LIGHT, PROGRESS_CIRCLE_BACKGROUND_COLOR_DARK, PROGRESS_CIRCLE_BACKGROUND_COLOR_LIGHT, PROGRESS_CIRCLE_FILL_COLOR_DARK, PROGRESS_CIRCLE_FILL_COLOR_LIGHT} from 'chrome://resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.js';
+import type {FingerprintProgressArcElement} from 'chrome://settings/lazy_load.js';
+import {FINGERPRINT_CHECK_DARK_URL, FINGERPRINT_CHECK_LIGHT_URL, FINGERPRINT_SCANNED_ICON_DARK, FINGERPRINT_SCANNED_ICON_LIGHT, PROGRESS_CIRCLE_BACKGROUND_COLOR_DARK, PROGRESS_CIRCLE_BACKGROUND_COLOR_LIGHT, PROGRESS_CIRCLE_FILL_COLOR_DARK, PROGRESS_CIRCLE_FILL_COLOR_LIGHT} from 'chrome://settings/lazy_load.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {assertEquals} from 'chrome://webui-test/chai_assert.js';
 import {MockController} from 'chrome://webui-test/mock_controller.js';
@@ -53,7 +53,7 @@
   }
 }
 
-/** @fileoverview Suite of tests for cr-fingerprint-progress-arc. */
+/** @fileoverview Suite of tests for fingerprint-progress-arc. */
 suite('cr_fingerprint_progress_arc_test', function() {
   /**
    * An object descrbing a 2d point.
@@ -65,7 +65,7 @@
 
   const canvasColor: string = 'rgba(255, 255, 255, 1.0)';
 
-  let progressArc: CrFingerprintProgressArcElement;
+  let progressArc: FingerprintProgressArcElement;
   let canvas: HTMLCanvasElement;
   let mockController: MockController;
   let fakeMediaQueryList: FakeMediaQueryList;
@@ -84,8 +84,7 @@
     matchMediaMock.returnValue = fakeMediaQueryList;
 
     document.body.innerHTML = window.trustedTypes!.emptyHTML;
-    progressArc = /** @type {!CrFingerprintProgressArcElement} */ (
-        document.createElement('cr-fingerprint-progress-arc'));
+    progressArc = document.createElement('fingerprint-progress-arc');
     document.body.appendChild(progressArc);
 
     // Override some parameters and function for testing purposes.
@@ -180,7 +179,7 @@
       progressArc.setProgress(
           this.prevPercentComplete_, this.currPercentComplete_,
           this.isComplete_);
-      await eventToPromise('cr-fingerprint-progress-arc-drawn', progressArc);
+      await eventToPromise('fingerprint-progress-arc-drawn', progressArc);
 
       this.verifyProgressCircleColors();
     }
diff --git a/chrome/test/data/webui/settings/settings_browsertest.cc b/chrome/test/data/webui/settings/settings_browsertest.cc
index dbf5a44e..30482f9 100644
--- a/chrome/test/data/webui/settings/settings_browsertest.cc
+++ b/chrome/test/data/webui/settings/settings_browsertest.cc
@@ -16,6 +16,7 @@
 #include "content/public/common/content_features.h"
 #include "content/public/test/browser_test.h"
 #include "third_party/blink/public/common/features_generated.h"
+#include "ui/compositor/compositor_switches.h"
 
 class SettingsBrowserTest : public WebUIMochaBrowserTest {
  protected:
@@ -611,6 +612,27 @@
           "runMochaSuite('TrackingProtectionSettingsRollbackNotice')");
 }
 
+// Test with --enable-pixel-output-in-tests enabled, required by fingerprint
+// element test using HTML canvas.
+class SettingsWithPixelOutputTest : public SettingsBrowserTest {
+ protected:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    command_line->AppendSwitch(::switches::kEnablePixelOutputInTests);
+    SettingsBrowserTest::SetUpCommandLine(command_line);
+  }
+};
+
+// https://crbug.com/1044390 - maybe flaky on Mac?
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_FingerprintProgressArc DISABLED_FingerprintProgressArc
+#else
+#define MAYBE_FingerprintProgressArc FingerprintProgressArc
+#endif
+IN_PROC_BROWSER_TEST_F(SettingsWithPixelOutputTest,
+                       MAYBE_FingerprintProgressArc) {
+  RunTest("settings/fingerprint_progress_arc_test.js", "mocha.run()");
+}
+
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
 using SettingsLanguagePageTest = SettingsBrowserTest;
 
diff --git a/chrome/test/data/webui/side_panel/BUILD.gn b/chrome/test/data/webui/side_panel/BUILD.gn
index d1789c0..f0ba4f8d 100644
--- a/chrome/test/data/webui/side_panel/BUILD.gn
+++ b/chrome/test/data/webui/side_panel/BUILD.gn
@@ -66,6 +66,7 @@
   ts_definitions = [
     "//tools/typescript/definitions/bookmarks.d.ts",
     "//tools/typescript/definitions/bookmark_manager_private.d.ts",
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/metrics_private.d.ts",
     "//tools/typescript/definitions/pending.d.ts",
   ]
diff --git a/chrome/test/data/webui/side_panel/customize_chrome/appearance_test.ts b/chrome/test/data/webui/side_panel/customize_chrome/appearance_test.ts
index 8dd1085f..dbc43eb 100644
--- a/chrome/test/data/webui/side_panel/customize_chrome/appearance_test.ts
+++ b/chrome/test/data/webui/side_panel/customize_chrome/appearance_test.ts
@@ -327,12 +327,33 @@
           appearanceElement.$.setClassicChromeButton, 'display', 'none');
       assertStyle(appearanceElement.$.themeSnapshot, 'display', 'none');
       assertNotStyle(appearanceElement.$.chromeColors, 'display', 'none');
-
-      const clickEvent =
-          eventToPromise('wallpaper-search-click', appearanceElement);
-      appearanceElement.$.searchedImageButton.click();
-      await clickEvent;
     });
+
+    test(
+        'searched image button opens themes when feature disabled',
+        async () => {
+          const clickEvent =
+              eventToPromise('edit-theme-click', appearanceElement);
+          appearanceElement.$.searchedImageButton.click();
+          await clickEvent;
+        });
+  });
+
+  suite('WallpaperSearch', async () => {
+    suiteSetup(() => {
+      loadTimeData.overrideValues({
+        'wallpaperSearchEnabled': true,
+      });
+    });
+
+    test(
+        'searched image button opens wallpaper search when feature enabled',
+        async () => {
+          const clickEvent =
+              eventToPromise('wallpaper-search-click', appearanceElement);
+          appearanceElement.$.searchedImageButton.click();
+          await clickEvent;
+        });
   });
 
   suite('Metrics', () => {
diff --git a/chrome/test/data/webui/tab_strip/BUILD.gn b/chrome/test/data/webui/tab_strip/BUILD.gn
index 964d4e9..797d237 100644
--- a/chrome/test/data/webui/tab_strip/BUILD.gn
+++ b/chrome/test/data/webui/tab_strip/BUILD.gn
@@ -23,7 +23,10 @@
       [ "chrome://tab-strip.top-chrome/*|" +
         rebase_path("$root_gen_dir/chrome/browser/resources/tab_strip/tsc/*",
                     target_gen_dir) ]
-  ts_definitions = [ "//tools/typescript/definitions/tabs.d.ts" ]
+  ts_definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
+    "//tools/typescript/definitions/tabs.d.ts",
+  ]
   ts_deps = [
     "//chrome/browser/resources/tab_strip:build_ts",
     "//ui/webui/resources/js:build_ts",
diff --git a/chrome/test/data/webui/webview/BUILD.gn b/chrome/test/data/webui/webview/BUILD.gn
index deab546..b19faa4 100644
--- a/chrome/test/data/webui/webview/BUILD.gn
+++ b/chrome/test/data/webui/webview/BUILD.gn
@@ -9,6 +9,7 @@
 
 build_webui_tests("build") {
   ts_definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/webview_tag.d.ts",
     "//tools/typescript/definitions/web_request.d.ts",
     "//tools/typescript/definitions/context_menus.d.ts",
diff --git a/chrome/test/data/webui/welcome/BUILD.gn b/chrome/test/data/webui/welcome/BUILD.gn
index 7be1461..8d4055a 100644
--- a/chrome/test/data/webui/welcome/BUILD.gn
+++ b/chrome/test/data/webui/welcome/BUILD.gn
@@ -30,7 +30,10 @@
       [ "chrome://welcome/*|" +
         rebase_path("$root_gen_dir/chrome/browser/resources/welcome/tsc/*",
                     target_gen_dir) ]
-  ts_definitions = [ "//tools/typescript/definitions/bookmarks.d.ts" ]
+  ts_definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
+    "//tools/typescript/definitions/bookmarks.d.ts",
+  ]
   ts_deps = [
     "//chrome/browser/resources/welcome:build_ts",
     "//third_party/polymer/v3_0:library",
diff --git a/chromeos/process_proxy/process_output_watcher_unittest.cc b/chromeos/process_proxy/process_output_watcher_unittest.cc
index 4473442..d233bd8 100644
--- a/chromeos/process_proxy/process_output_watcher_unittest.cc
+++ b/chromeos/process_proxy/process_output_watcher_unittest.cc
@@ -10,6 +10,7 @@
 #include <memory>
 #include <queue>
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "base/files/file_util.h"
@@ -174,7 +175,7 @@
       if (test_cases[i].should_send_terminating_null)
         test_size += sizeof(*test_str.c_str());
       EXPECT_TRUE(base::WriteFileDescriptor(
-          pt_pipe[1], base::StringPiece(test_str.c_str(), test_size)));
+          pt_pipe[1], std::string_view(test_str.c_str(), test_size)));
 
       run_loop.Run();
       EXPECT_TRUE(expectations_.IsDone());
diff --git a/clank b/clank
index eadffcd..8a57d2d3 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit eadffcd4b5ec79ec69e29f75c6695edf9c69aff1
+Subproject commit 8a57d2d318a0d62648d9590be11bc6d60f247b7d
diff --git a/components/autofill/content/browser/content_autofill_driver.h b/components/autofill/content/browser/content_autofill_driver.h
index 974b835..ddc4eb3 100644
--- a/components/autofill/content/browser/content_autofill_driver.h
+++ b/components/autofill/content/browser/content_autofill_driver.h
@@ -161,7 +161,6 @@
   bool IsPrerendering() const override;
   bool HasSharedAutofillPermission() const override;
   bool CanShowAutofillUi() const override;
-  void HandleParsedForms(const std::vector<FormData>& forms) override {}
   void PopupHidden() override;
   net::IsolationInfo IsolationInfo() override;
 
diff --git a/components/autofill/core/browser/autofill_driver.h b/components/autofill/core/browser/autofill_driver.h
index a76c0bb..159a3ebe 100644
--- a/components/autofill/core/browser/autofill_driver.h
+++ b/components/autofill/core/browser/autofill_driver.h
@@ -190,9 +190,6 @@
                                 const FieldGlobalId& field_id,
                                 const std::u16string& value) = 0;
 
-  // Forwards parsed |forms| to the embedder.
-  virtual void HandleParsedForms(const std::vector<FormData>& forms) = 0;
-
   // Sends the field type predictions specified in |forms| to the renderer. This
   // method is a no-op if the renderer is not available or the appropriate
   // command-line flag is not set.
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index c4a1b11..9c3e06ba 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -318,8 +318,6 @@
   DCHECK(!forms.empty());
   OnBeforeProcessParsedForms();
 
-  driver().HandleParsedForms(forms);
-
   std::vector<raw_ptr<FormStructure, VectorExperimental>> non_queryable_forms;
   std::vector<raw_ptr<FormStructure, VectorExperimental>> queryable_forms;
   DenseSet<FormType> form_types;
diff --git a/components/autofill/core/browser/browser_autofill_manager.cc b/components/autofill/core/browser/browser_autofill_manager.cc
index dd9dfb8..784f66c 100644
--- a/components/autofill/core/browser/browser_autofill_manager.cc
+++ b/components/autofill/core/browser/browser_autofill_manager.cc
@@ -127,6 +127,8 @@
 #include "components/prefs/pref_service.h"
 #include "components/security_interstitials/core/pref_names.h"
 #include "components/security_state/core/security_state.h"
+#include "components/signin/public/base/consent_level.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/strings/grit/components_strings.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -262,6 +264,52 @@
   }
 }
 
+// Is `suggestions` contains Autocomplete suggestions, then this function logs
+// a metric to record whether Autocomplete would have been suppressed due to
+// a plus address suggestion.
+// It only logs these metrics for users that are signed in and tabs that are not
+// in incognito mode.
+// TODO(b/327328460): Clean up once the metric is has been evaluated.
+void MaybeLogAutocompleteSuppressionByPlusAddresses(
+    AutofillClient& client,
+    base::span<const Suggestion> suggestions,
+    AutofillField* focused_field) {
+  if (client.IsOffTheRecord()) {
+    return;
+  }
+
+  // Do not log metrics for users that are not signed in.
+  if (signin::IdentityManager* identity_manager = client.GetIdentityManager();
+      !identity_manager ||
+      identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin)
+          .IsEmpty()) {
+    return;
+  }
+
+  if (suggestions.empty() ||
+      GetFillingProductFromPopupItemId(suggestions[0].popup_item_id) !=
+          FillingProduct::kAutocomplete) {
+    return;
+  }
+
+  // If the focused field is not classified as an email address, plus addresses
+  // would never be shown.
+  using enum AutocompleteSuppressionByPlusAddress;
+  if (!focused_field ||
+      focused_field->Type().group() != FieldTypeGroup::kEmail) {
+    base::UmaHistogramEnumeration(kAutocompleteSuppressionByPlusAddressUma,
+                                  kNotSuppressed);
+    return;
+  }
+  const bool has_email =
+      base::ranges::any_of(suggestions, [](const Suggestion& suggestion) {
+        return IsValidEmailAddress(suggestion.main_text.value);
+      });
+  base::UmaHistogramEnumeration(
+      kAutocompleteSuppressionByPlusAddressUma,
+      has_email ? kSuppressedWithEmailResults : kSuppressedWithoutEmailResults);
+}
+
 // Emits a metric that measures how long it took to show a single field form
 // filling suggestion.
 // TODO(b/324553809): Remove once we know the average time for a suggestion to
@@ -1184,17 +1232,22 @@
               field, client(),
               base::BindRepeating(
                   [](base::WeakPtr<BrowserAutofillManager> self,
-                     base::TimeTicks request_start_time, FieldGlobalId field_id,
+                     base::TimeTicks request_start_time,
+                     AutofillField* focused_field, FieldGlobalId field_id,
                      const std::vector<Suggestion>& suggestions) {
-                    if (self) {
-                      LogTimeDelayForSingleFieldFormFill(
-                          suggestions,
-                          base::TimeTicks::Now() - request_start_time);
-                      self->external_delegate_->OnSuggestionsReturned(
-                          field_id, suggestions);
+                    if (!self) {
+                      return;
                     }
+                    MaybeLogAutocompleteSuppressionByPlusAddresses(
+                        self->client(), suggestions, focused_field);
+                    LogTimeDelayForSingleFieldFormFill(
+                        suggestions,
+                        base::TimeTicks::Now() - request_start_time);
+                    self->external_delegate_->OnSuggestionsReturned(
+                        field_id, suggestions);
                   },
-                  weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now()),
+                  weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now(),
+                  context.focused_field),
               context);
       if (handled_by_single_field_form_filler) {
         return false;
diff --git a/components/autofill/core/browser/browser_autofill_manager.h b/components/autofill/core/browser/browser_autofill_manager.h
index 6cd345dd..a4fb41a 100644
--- a/components/autofill/core/browser/browser_autofill_manager.h
+++ b/components/autofill/core/browser/browser_autofill_manager.h
@@ -108,6 +108,26 @@
   kMaxValue = kIban,
 };
 
+// Describes whether Autocomplete suggestions would have been suppressed by a
+// plus address suggestion.
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+// TODO(b/327328460): Clean up once the metric is has been evaluated.
+enum class AutocompleteSuppressionByPlusAddress {
+  // The Autocomplete suggestions would not have been suppressed.
+  kNotSuppressed = 0,
+  // The Autocomplete suggestions would have been suppressed and would have
+  // contained email addresses.
+  kSuppressedWithEmailResults = 1,
+  // The Autocomplete suggestions would have been suppressed and would not have
+  // contained email addresses.
+  kSuppressedWithoutEmailResults = 2,
+  kMaxValue = kSuppressedWithoutEmailResults,
+};
+
+inline constexpr char kAutocompleteSuppressionByPlusAddressUma[] =
+    "Autofill.Autocomplete.SuppressionByPlusAddress";
+
 // Manages saving and restoring the user's personal information entered into web
 // forms. One per frame; owned by the AutofillDriver.
 class BrowserAutofillManager : public AutofillManager {
diff --git a/components/autofill/core/browser/browser_autofill_manager_unittest.cc b/components/autofill/core/browser/browser_autofill_manager_unittest.cc
index 31a32aa..b56cc9af 100644
--- a/components/autofill/core/browser/browser_autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/browser_autofill_manager_unittest.cc
@@ -43,6 +43,7 @@
 #include "components/autofill/core/browser/crowdsourcing/mock_autofill_crowdsourcing_manager.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/filling_product.h"
 #include "components/autofill/core/browser/form_data_importer_test_api.h"
 #include "components/autofill/core/browser/form_structure_test_api.h"
@@ -107,6 +108,8 @@
 
 namespace {
 
+using ::base::Bucket;
+using ::base::BucketsAre;
 using ::base::UTF8ToUTF16;
 using mojom::SubmissionIndicatorEvent;
 using mojom::SubmissionSource;
@@ -2002,6 +2005,121 @@
       "Autofill.Popup.SingleFieldFormFillerDelay.Autocomplete", 1);
 }
 
+// Tests that metrics are logged to measure whether Autocomplete would have been
+// suppressed by Plus Address suggestions whenever an Autocomplete popup is
+// shown. Simulates Autocomplete suggestions that do not contain email strings.
+TEST_F(BrowserAutofillManagerTest,
+       AutocompleteSuppressionWithoutEmailSuggestions) {
+  // Required to enable heuristics for small forms.
+  base::test::ScopedFeatureList feature_list{
+      features::kAutofillEnableEmailHeuristicOnlyAddressForms};
+
+  autofill_client_.identity_test_environment().MakePrimaryAccountAvailable(
+      "plus@plus.plus", signin::ConsentLevel::kSignin);
+  // Clear profiles to avoid that Autofill takes precedence.
+  personal_data().ClearProfiles();
+  FormData form_without_email =
+      test::GetFormData({.fields = {{.role = NAME_FIRST}}});
+  FormData form_with_email =
+      test::GetFormData({.fields = {{.role = EMAIL_ADDRESS}}});
+  FormsSeen({form_without_email, form_with_email});
+
+  ON_CALL(single_field_form_fill_router(), OnGetSingleFieldSuggestions)
+      .WillByDefault(
+          [&](const FormFieldData& field, const AutofillClient&,
+              SingleFieldFormFiller::OnSuggestionsReturnedCallback callback,
+              const SuggestionsContext&) {
+            std::move(callback).Run(field.global_id(),
+                                    {Suggestion(u"one"), Suggestion(u"test@")});
+            return true;
+          });
+
+  // An interaction with a non-email field will never lead to a suppression of
+  // Autocomplete.
+  {
+    base::HistogramTester histogram_tester;
+    GetAutofillSuggestions(
+        form_without_email, form_without_email.fields[0],
+        AutofillSuggestionTriggerSource::kFormControlElementClicked);
+    histogram_tester.ExpectUniqueSample(
+        kAutocompleteSuppressionByPlusAddressUma,
+        AutocompleteSuppressionByPlusAddress::kNotSuppressed, 1);
+  }
+
+  // But an interaction with an email field will suppress Autocomplete.
+  {
+    base::HistogramTester histogram_tester;
+    GetAutofillSuggestions(
+        form_with_email, form_with_email.fields[0],
+        AutofillSuggestionTriggerSource::kFormControlElementClicked);
+    histogram_tester.ExpectUniqueSample(
+        kAutocompleteSuppressionByPlusAddressUma,
+        AutocompleteSuppressionByPlusAddress::kSuppressedWithoutEmailResults,
+        1);
+  }
+}
+
+// Tests that metrics are logged to measure whether Autocomplete would have been
+// suppressed by Plus Address suggestions. Simulates Autocomplete suggestions
+// with email strings. Also tests that no metrics are emitted for signed-out
+// users and in incognito mode.
+TEST_F(BrowserAutofillManagerTest,
+       AutocompleteSuppressionWithEmailSuggestions) {
+  // Required to enable heuristics for small forms.
+  base::test::ScopedFeatureList feature_list{
+      features::kAutofillEnableEmailHeuristicOnlyAddressForms};
+
+  // Clear profiles to avoid that Autofill takes precedence.
+  personal_data().ClearProfiles();
+  FormData form = test::GetFormData({.fields = {{.role = EMAIL_ADDRESS}}});
+  FormsSeen({form});
+  ON_CALL(single_field_form_fill_router(), OnGetSingleFieldSuggestions)
+      .WillByDefault(
+          [&](const FormFieldData& field, const AutofillClient&,
+              SingleFieldFormFiller::OnSuggestionsReturnedCallback callback,
+              const SuggestionsContext&) {
+            std::move(callback).Run(
+                field.global_id(),
+                {Suggestion(u"one"), Suggestion(u"test@foo.com")});
+            return true;
+          });
+
+  // No metrics are recorded if the user is not signed in.
+  {
+    base::HistogramTester histogram_tester;
+    GetAutofillSuggestions(
+        form, form.fields[0],
+        AutofillSuggestionTriggerSource::kFormControlElementClicked);
+    histogram_tester.ExpectTotalCount(kAutocompleteSuppressionByPlusAddressUma,
+                                      0);
+  }
+
+  // An interaction with an email field will suppress Autocomplete for a
+  // signed-in user.
+  autofill_client_.identity_test_environment().MakePrimaryAccountAvailable(
+      "plus@plus.plus", signin::ConsentLevel::kSignin);
+  {
+    base::HistogramTester histogram_tester;
+    GetAutofillSuggestions(
+        form, form.fields[0],
+        AutofillSuggestionTriggerSource::kFormControlElementClicked);
+    histogram_tester.ExpectUniqueSample(
+        kAutocompleteSuppressionByPlusAddressUma,
+        AutocompleteSuppressionByPlusAddress::kSuppressedWithEmailResults, 1);
+  }
+
+  // No metrics are recorded in incognito mode.
+  autofill_client_.set_is_off_the_record(true);
+  {
+    base::HistogramTester histogram_tester;
+    GetAutofillSuggestions(
+        form, form.fields[0],
+        AutofillSuggestionTriggerSource::kFormControlElementClicked);
+    histogram_tester.ExpectTotalCount(kAutocompleteSuppressionByPlusAddressUma,
+                                      0);
+  }
+}
+
 class BrowserAutofillManagerTestForMetadataCardSuggestions
     : public BrowserAutofillManagerTest,
       public testing::WithParamInterface<bool> {
diff --git a/components/autofill/core/browser/test_autofill_client.h b/components/autofill/core/browser/test_autofill_client.h
index 83bfae9..c9c0e6a0 100644
--- a/components/autofill/core/browser/test_autofill_client.h
+++ b/components/autofill/core/browser/test_autofill_client.h
@@ -736,6 +736,10 @@
 
   ukm::TestUkmRecorder* GetTestUkmRecorder() { return &test_ukm_recorder_; }
 
+  signin::IdentityTestEnvironment& identity_test_environment() {
+    return identity_test_env_;
+  }
+
  private:
   ukm::TestAutoSetUkmRecorder test_ukm_recorder_;
   signin::IdentityTestEnvironment identity_test_env_;
diff --git a/components/autofill/core/browser/test_autofill_driver.h b/components/autofill/core/browser/test_autofill_driver.h
index 12b4b91..da5f8863d 100644
--- a/components/autofill/core/browser/test_autofill_driver.h
+++ b/components/autofill/core/browser/test_autofill_driver.h
@@ -68,7 +68,6 @@
                         mojom::ActionPersistence action_persistence,
                         const FieldGlobalId& field,
                         const std::u16string& value) override {}
-  void HandleParsedForms(const std::vector<FormData>& forms) override {}
   void SendAutofillTypePredictionsToRenderer(
       const std::vector<raw_ptr<FormStructure, VectorExperimental>>& forms)
       override {}
diff --git a/components/autofill/ios/browser/autofill_driver_ios.h b/components/autofill/ios/browser/autofill_driver_ios.h
index fb2bc065..1db0361 100644
--- a/components/autofill/ios/browser/autofill_driver_ios.h
+++ b/components/autofill/ios/browser/autofill_driver_ios.h
@@ -9,6 +9,7 @@
 
 #import "base/containers/flat_map.h"
 #import "base/containers/flat_set.h"
+#import "base/containers/span.h"
 #import "base/memory/raw_ptr.h"
 #import "base/memory/weak_ptr.h"
 #import "components/autofill/core/browser/autofill_client.h"
@@ -37,6 +38,7 @@
 // AutofillDriverIOS is associated with exactly one WebFrame and its lifecycle
 // is bound to that WebFrame.
 class AutofillDriverIOS : public AutofillDriver,
+                          public AutofillManager::Observer,
                           public web::WebFrameUserData<AutofillDriverIOS> {
  public:
   // Returns the AutofillDriverIOS for `web_state` and `web_frame`. Creates the
@@ -78,7 +80,6 @@
       FormGlobalId form,
       base::OnceCallback<void(AutofillDriver*, const std::optional<FormData>&)>
           response_callback) override;
-  void HandleParsedForms(const std::vector<FormData>& forms) override;
   void SendAutofillTypePredictionsToRenderer(
       const std::vector<raw_ptr<FormStructure, VectorExperimental>>& forms)
       override;
@@ -101,8 +102,9 @@
   AutofillClient* client() { return client_; }
 
   void set_autofill_manager_for_testing(
-      std::unique_ptr<BrowserAutofillManager> browser_autofill_manager) {
-    browser_autofill_manager_ = std::move(browser_autofill_manager);
+      std::unique_ptr<BrowserAutofillManager> manager) {
+    manager_ = std::move(manager);
+    manager_observation_.Observe(manager_.get());
   }
 
   void RendererShouldSetSuggestionAvailability(
@@ -149,6 +151,11 @@
   // Other callers should use FromWebStateAndWebFrame() instead.
   using web::WebFrameUserData<AutofillDriverIOS>::FromWebFrame;
 
+  // AutofillManager::Observer:
+  void OnAutofillManagerDestroyed(AutofillManager& manager) override;
+  void OnAfterFormsSeen(AutofillManager& manager,
+                        base::span<const FormGlobalId> forms) override;
+
   // The WebState with which this object is associated.
   raw_ptr<web::WebState> web_state_ = nullptr;
 
@@ -178,9 +185,10 @@
   // The embedder's AutofillClient instance.
   raw_ptr<AutofillClient> client_;
 
-  // BrowserAutofillManager instance via which this object drives the shared
-  // Autofill code.
-  std::unique_ptr<BrowserAutofillManager> browser_autofill_manager_;
+  std::unique_ptr<BrowserAutofillManager> manager_;
+
+  base::ScopedObservation<AutofillManager, AutofillManager::Observer>
+      manager_observation_{this};
 
   base::WeakPtrFactory<AutofillDriverIOS> weak_ptr_factory_{this};
 };
diff --git a/components/autofill/ios/browser/autofill_driver_ios.mm b/components/autofill/ios/browser/autofill_driver_ios.mm
index 93a3d5a..cfc7cf1 100644
--- a/components/autofill/ios/browser/autofill_driver_ios.mm
+++ b/components/autofill/ios/browser/autofill_driver_ios.mm
@@ -47,11 +47,12 @@
                                      id<AutofillDriverIOSBridge> bridge,
                                      const std::string& app_locale)
     : web_state_(web_state),
+      web_frame_id_(web_frame ? web_frame->GetFrameId() : ""),
       bridge_(bridge),
       client_(client),
-      browser_autofill_manager_(
+      manager_(
           std::make_unique<BrowserAutofillManager>(this, client, app_locale)) {
-  web_frame_id_ = web_frame ? web_frame->GetFrameId() : "";
+  manager_observation_.Observe(manager_.get());
 
   if (base::FeatureList::IsEnabled(
           autofill::features::kAutofillAcrossIframesIos)) {
@@ -89,7 +90,7 @@
 }
 
 BrowserAutofillManager& AutofillDriverIOS::GetAutofillManager() {
-  return *browser_autofill_manager_;
+  return *manager_;
 }
 
 // Return true as iOS has no MPArch.
@@ -166,25 +167,6 @@
   NOTIMPLEMENTED();
 }
 
-void AutofillDriverIOS::HandleParsedForms(const std::vector<FormData>& forms) {
-  const std::map<FormGlobalId, std::unique_ptr<FormStructure>>& map =
-      browser_autofill_manager_->form_structures();
-  std::vector<raw_ptr<FormStructure, VectorExperimental>> form_structures;
-  form_structures.reserve(forms.size());
-
-  for (const FormData& form : forms) {
-    auto it = map.find(form.global_id());
-    if (it != map.end())
-      form_structures.push_back(it->second.get());
-  }
-
-  web::WebFrame* frame = web_frame();
-  if (!frame) {
-    return;
-  }
-  [bridge_ handleParsedForms:form_structures inFrame:frame];
-}
-
 void AutofillDriverIOS::SendAutofillTypePredictionsToRenderer(
     const std::vector<raw_ptr<FormStructure, VectorExperimental>>& forms) {
   web::WebFrame* frame = web_frame();
@@ -336,4 +318,26 @@
   }
 }
 
+void AutofillDriverIOS::OnAutofillManagerDestroyed(AutofillManager& manager) {
+  manager_observation_.Reset();
+}
+
+void AutofillDriverIOS::OnAfterFormsSeen(AutofillManager& manager,
+                                         base::span<const FormGlobalId> forms) {
+  DCHECK_EQ(&manager, manager_.get());
+  if (forms.empty()) {
+    return;
+  }
+  std::vector<raw_ptr<FormStructure, VectorExperimental>> form_structures;
+  form_structures.reserve(forms.size());
+  for (const FormGlobalId& form : forms) {
+    if (FormStructure* form_structure = manager.FindCachedFormById(form)) {
+      form_structures.push_back(form_structure);
+    }
+  }
+  if (web::WebFrame* frame = web_frame()) {
+    [bridge_ handleParsedForms:form_structures inFrame:frame];
+  }
+}
+
 }  // namespace autofill
diff --git a/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter.cc b/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter.cc
index 483c6c5..e149be459 100644
--- a/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter.cc
+++ b/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter.cc
@@ -38,32 +38,6 @@
   return config;
 }
 
-std::vector<Rule> ExtractRedactRules(const proto::RedactRules& proto_rules) {
-  std::vector<Rule> rules;
-  if (proto_rules.rules_size()) {
-    for (const auto& rule : proto_rules.rules()) {
-      if (rule.has_regex() && rule.has_behavior()) {
-        rules.push_back(Rule());
-        rules.back().regex = rule.regex();
-        rules.back().behavior = rule.behavior();
-        if (rule.has_replacement_string()) {
-          rules.back().replacement_string = rule.replacement_string();
-        }
-        if (rule.has_min_pattern_length()) {
-          rules.back().min_pattern_length = rule.min_pattern_length();
-        }
-        if (rule.has_max_pattern_length()) {
-          rules.back().max_pattern_length = rule.max_pattern_length();
-        }
-        if (rule.has_group_index()) {
-          rules.back().matching_group = rule.group_index();
-        }
-      }
-    }
-  }
-  return rules;
-}
-
 }  // namespace
 
 OnDeviceModelExecutionConfigInterpreter::
@@ -142,8 +116,8 @@
   if (config.has_output_config() && config.output_config().has_redact_rules() &&
       config.output_config().redact_rules().fields_to_check_size() &&
       !config.output_config().redact_rules().rules().empty()) {
-    feature_data->redactor = std::make_unique<Redactor>(
-        ExtractRedactRules(config.output_config().redact_rules()));
+    feature_data->redactor =
+        Redactor::FromProto(config.output_config().redact_rules());
   }
   feature_to_data_[config.feature()] = std::move(feature_data);
 }
diff --git a/components/optimization_guide/core/model_execution/redactor.cc b/components/optimization_guide/core/model_execution/redactor.cc
index 88ef80c..91764a2 100644
--- a/components/optimization_guide/core/model_execution/redactor.cc
+++ b/components/optimization_guide/core/model_execution/redactor.cc
@@ -6,12 +6,43 @@
 
 #include <algorithm>
 
+#include "base/memory/ptr_util.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "third_party/re2/src/re2/re2.h"
 
 namespace optimization_guide {
 
+namespace {
+
+std::vector<Rule> ExtractRedactRules(const proto::RedactRules& proto_rules) {
+  std::vector<Rule> rules;
+  if (proto_rules.rules_size()) {
+    for (const auto& rule : proto_rules.rules()) {
+      if (rule.has_regex() && rule.has_behavior()) {
+        rules.push_back(Rule());
+        rules.back().regex = rule.regex();
+        rules.back().behavior = rule.behavior();
+        if (rule.has_replacement_string()) {
+          rules.back().replacement_string = rule.replacement_string();
+        }
+        if (rule.has_min_pattern_length()) {
+          rules.back().min_pattern_length = rule.min_pattern_length();
+        }
+        if (rule.has_max_pattern_length()) {
+          rules.back().max_pattern_length = rule.max_pattern_length();
+        }
+        if (rule.has_group_index()) {
+          rules.back().matching_group = rule.group_index();
+        }
+      }
+    }
+  }
+  return rules;
+}
+
+}  // namespace
+
 Rule::Rule() = default;
 Rule::Rule(const Rule& r) = default;
 Rule::~Rule() = default;
@@ -41,6 +72,12 @@
 
 Redactor::~Redactor() = default;
 
+// static
+std::unique_ptr<Redactor> Redactor::FromProto(
+    const proto::RedactRules& proto_rules) {
+  return base::WrapUnique(new Redactor(ExtractRedactRules(proto_rules)));
+}
+
 RedactResult Redactor::Redact(const std::string& input,
                               std::string& output) const {
   for (auto& rule : rules_) {
diff --git a/components/optimization_guide/core/model_execution/redactor.h b/components/optimization_guide/core/model_execution/redactor.h
index a608b01..22fb18f 100644
--- a/components/optimization_guide/core/model_execution/redactor.h
+++ b/components/optimization_guide/core/model_execution/redactor.h
@@ -10,7 +10,7 @@
 #include <string>
 #include <vector>
 
-#include "components/optimization_guide/proto/model_execution.pb.h"
+#include "components/optimization_guide/proto/redaction.pb.h"
 
 namespace re2 {
 class RE2;
@@ -41,16 +41,21 @@
 };
 
 // Used to redact (or reject) text.
-class Redactor {
+class Redactor final {
  public:
-  explicit Redactor(const std::vector<Rule>& rules);
   ~Redactor();
 
+  // Construct a Redactor that implements the RedactRules.
+  static std::unique_ptr<Redactor> FromProto(
+      const proto::RedactRules& proto_rules);
+
   // Redacts (or rejects) the applicable text in`output`. `input` is the string
   // regexes of type REDACT_IF_ONLY_IN_OUTPUT checks.
   RedactResult Redact(const std::string& input, std::string& output) const;
 
  private:
+  explicit Redactor(const std::vector<Rule>& rules);
+
   struct CachedRule {
     CachedRule();
     ~CachedRule();
diff --git a/components/optimization_guide/core/model_execution/redactor_unittest.cc b/components/optimization_guide/core/model_execution/redactor_unittest.cc
index c5e1f42..de01211a 100644
--- a/components/optimization_guide/core/model_execution/redactor_unittest.cc
+++ b/components/optimization_guide/core/model_execution/redactor_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "components/optimization_guide/core/model_execution/redactor.h"
+#include <initializer_list>
 
 #include "base/strings/string_number_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -12,114 +13,132 @@
 
 using proto::RedactBehavior;
 
-Rule CreateRule(
+std::unique_ptr<Redactor> CreateRedactor(
+    std::initializer_list<proto::RedactRule> rules) {
+  proto::RedactRules proto_rules;
+  for (auto& rule : rules) {
+    proto_rules.add_rules()->CopyFrom(rule);
+  }
+  return Redactor::FromProto(proto_rules);
+}
+
+proto::RedactRule CreateRule(
     const std::string& regex,
     RedactBehavior behavior = RedactBehavior::REDACT_IF_ONLY_IN_OUTPUT,
     std::optional<std::string> replacement_string = std::nullopt,
     std::optional<int> min_pattern_length = std::nullopt,
     std::optional<int> max_pattern_length = std::nullopt,
     std::optional<int> group = std::nullopt) {
-  Rule rule;
-  rule.regex = regex;
-  rule.behavior = behavior;
-  rule.replacement_string = std::move(replacement_string);
-  rule.matching_group = std::move(group);
-  rule.min_pattern_length = std::move(min_pattern_length);
-  rule.max_pattern_length = std::move(max_pattern_length);
+  proto::RedactRule rule;
+  rule.set_regex(regex);
+  rule.set_behavior(behavior);
+  if (replacement_string) {
+    rule.set_replacement_string(*replacement_string);
+  }
+  if (group) {
+    rule.set_group_index(*group);
+  }
+  if (min_pattern_length) {
+    rule.set_min_pattern_length(*min_pattern_length);
+  }
+  if (max_pattern_length) {
+    rule.set_max_pattern_length(*max_pattern_length);
+  }
   return rule;
 }
 
 TEST(RedactorTest, RedactMultipleHitsNotPresentInInput) {
-  Redactor redactor({CreateRule("ab")});
+  auto redactor = CreateRedactor({CreateRule("ab")});
   std::string output("ab cab");
-  EXPECT_EQ(RedactResult::kContinue, redactor.Redact(std::string(), output));
+  EXPECT_EQ(RedactResult::kContinue, redactor->Redact(std::string(), output));
   EXPECT_EQ("[##] c[##]", output);
 }
 
 TEST(RedactorTest, RedactMultipleHits) {
-  Redactor redactor({CreateRule("ab")});
+  auto redactor = CreateRedactor({CreateRule("ab")});
   std::string output("ab cab");
-  redactor.Redact("zabq", output);
+  redactor->Redact("zabq", output);
   EXPECT_EQ("ab cab", output);
 }
 
 TEST(RedactorTest, RedactMultipleHitsMultipleRegex) {
-  Redactor redactor({CreateRule("ab"), CreateRule("z")});
+  auto redactor = CreateRedactor({CreateRule("ab"), CreateRule("z")});
   std::string output("ab zcab");
-  redactor.Redact(std::string(), output);
+  redactor->Redact(std::string(), output);
   EXPECT_EQ("[##] [#]c[##]", output);
 }
 
 TEST(RedactorTest, RedactNotAtEnd) {
-  Redactor redactor({CreateRule("ab")});
+  auto redactor = CreateRedactor({CreateRule("ab")});
   std::string output("abc");
-  redactor.Redact(std::string(), output);
+  redactor->Redact(std::string(), output);
   EXPECT_EQ("[##]c", output);
 }
 
 TEST(RedactorTest, RedactAlways) {
-  Redactor redactor({CreateRule("ab", RedactBehavior::REDACT_ALWAYS)});
+  auto redactor =
+      CreateRedactor({CreateRule("ab", RedactBehavior::REDACT_ALWAYS)});
   std::string output("abc");
-  redactor.Redact("ab", output);
+  redactor->Redact("ab", output);
   EXPECT_EQ("[##]c", output);
 }
 
 TEST(RedactorTest, Reject) {
-  Redactor redactor({CreateRule("ab", RedactBehavior::REJECT)});
+  auto redactor = CreateRedactor({CreateRule("ab", RedactBehavior::REJECT)});
   std::string output("abc");
-  EXPECT_EQ(RedactResult::kReject, redactor.Redact(std::string(), output));
+  EXPECT_EQ(RedactResult::kReject, redactor->Redact(std::string(), output));
 }
 
 TEST(RedactorTest, RedactWithReplacmentText) {
-  Redactor redactor({CreateRule("ab", RedactBehavior::REDACT_IF_ONLY_IN_OUTPUT,
-                                "|redacted)")});
+  auto redactor = CreateRedactor({CreateRule(
+      "ab", RedactBehavior::REDACT_IF_ONLY_IN_OUTPUT, "|redacted)")});
   std::string output("ab cab");
-  EXPECT_EQ(RedactResult::kContinue, redactor.Redact(std::string(), output));
+  EXPECT_EQ(RedactResult::kContinue, redactor->Redact(std::string(), output));
   EXPECT_EQ("|redacted) c|redacted)", output);
 }
 
 TEST(RedactorTest, DontRedactIfMatchTooMuch) {
-  Redactor redactor(
+  auto redactor = CreateRedactor(
       {CreateRule("a*", RedactBehavior::REDACT_ALWAYS, std::string(), 2, 4)});
   const std::string original_output("baaaaaaac");
   std::string output(original_output);
-  EXPECT_EQ(RedactResult::kContinue, redactor.Redact(std::string(), output));
+  EXPECT_EQ(RedactResult::kContinue, redactor->Redact(std::string(), output));
   // No redact should happen because too much matched.
   EXPECT_EQ(original_output, output);
 }
 
 TEST(RedactorTest, DontRedactIfMatchTooLittle) {
-  Redactor redactor(
+  auto redactor = CreateRedactor(
       {CreateRule("a*", RedactBehavior::REDACT_ALWAYS, std::string(), 2, 4)});
   const std::string original_output("bad");
   std::string output(original_output);
-  EXPECT_EQ(RedactResult::kContinue, redactor.Redact(std::string(), output));
+  EXPECT_EQ(RedactResult::kContinue, redactor->Redact(std::string(), output));
   // No redact should happen because it didn't match enough.
   EXPECT_EQ(original_output, output);
 }
 
 TEST(RedactorTest, MatchLimits) {
-  Redactor redactor(
+  auto redactor = CreateRedactor(
       {CreateRule("a*", RedactBehavior::REDACT_ALWAYS, std::nullopt, 2, 4)});
   const std::string original_output("baaad");
   std::string output(original_output);
-  EXPECT_EQ(RedactResult::kContinue, redactor.Redact(std::string(), output));
+  EXPECT_EQ(RedactResult::kContinue, redactor->Redact(std::string(), output));
   EXPECT_EQ("b[###]d", output);
 }
 
 TEST(RedactorTest, ReplaceGroup) {
-  Redactor redactor({CreateRule("(?:a)(b+)", RedactBehavior::REDACT_ALWAYS,
-                                std::nullopt, 2, 4, 1)});
+  auto redactor = CreateRedactor({CreateRule(
+      "(?:a)(b+)", RedactBehavior::REDACT_ALWAYS, std::nullopt, 2, 4, 1)});
   std::string output("abbbcd");
-  EXPECT_EQ(RedactResult::kContinue, redactor.Redact(std::string(), output));
+  EXPECT_EQ(RedactResult::kContinue, redactor->Redact(std::string(), output));
   EXPECT_EQ("a[###]cd", output);
 }
 
 TEST(RedactorTest, ReplaceGroup2) {
-  Redactor redactor({CreateRule("(a)(b+)", RedactBehavior::REDACT_ALWAYS,
-                                std::nullopt, 2, 4, 2)});
+  auto redactor = CreateRedactor({CreateRule(
+      "(a)(b+)", RedactBehavior::REDACT_ALWAYS, std::nullopt, 2, 4, 2)});
   std::string output("abbbcd");
-  EXPECT_EQ(RedactResult::kContinue, redactor.Redact(std::string(), output));
+  EXPECT_EQ(RedactResult::kContinue, redactor->Redact(std::string(), output));
   EXPECT_EQ("a[###]cd", output);
 }
 
diff --git a/components/signin/public/identity_manager/identity_test_utils.h b/components/signin/public/identity_manager/identity_test_utils.h
index 69ff88f6..2d9c8d3d 100644
--- a/components/signin/public/identity_manager/identity_test_utils.h
+++ b/components/signin/public/identity_manager/identity_test_utils.h
@@ -159,7 +159,7 @@
       nullptr;
 
   const signin_metrics::AccessPoint access_point =
-      signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN;
+      signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS;
 
   explicit AccountAvailabilityOptions(base::StringPiece email);
   ~AccountAvailabilityOptions();
@@ -230,7 +230,7 @@
   std::optional<std::string> refresh_token_ = std::string();
   bool with_cookie_ = false;
   signin_metrics::AccessPoint access_point_ =
-      signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN;
+      signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS;
 };
 
 // Sets up an account identified by `email` according to options provided. See
diff --git a/components/viz/service/display/dc_layer_overlay.cc b/components/viz/service/display/dc_layer_overlay.cc
index c7923c0f..6a2a87d7 100644
--- a/components/viz/service/display/dc_layer_overlay.cc
+++ b/components/viz/service/display/dc_layer_overlay.cc
@@ -607,21 +607,23 @@
 
 bool AllowRemoveClearVideoQuadCandidatesWhenMoving(
     DisplayResourceProvider* resource_provider,
-    const QuadList::ConstIterator& it) {
+    const QuadList::ConstIterator& it,
+    bool force_overlay_for_auto_hdr) {
   if (!IsClearVideoQuad(it)) {
     return false;
   }
-  // Do not allow remove clear video quad candidates for HDR videos, since there
-  // will always be a huge visual difference between compositor tone-mapping (by
-  // Chrome) and MPO tone-mapping (by Driver).
+  // Do not allow remove clear video quad candidates for HDR videos or SDR to
+  // HDR videos, since there will always be a huge visual difference between
+  // compositor tone-mapping (by Chrome) and MPO tone-mapping (by Driver).
   switch (it->material) {
     case DrawQuad::Material::kYuvVideoContent: {
       const YUVVideoDrawQuad* quad = YUVVideoDrawQuad::MaterialCast(*it);
-      return !quad->video_color_space.IsHDR();
+      return !(quad->video_color_space.IsHDR() || force_overlay_for_auto_hdr);
     }
     case DrawQuad::Material::kTextureContent: {
       const TextureDrawQuad* quad = TextureDrawQuad::MaterialCast(*it);
-      return !resource_provider->GetColorSpace(quad->resource_id()).IsHDR();
+      return !(resource_provider->GetColorSpace(quad->resource_id()).IsHDR() ||
+               force_overlay_for_auto_hdr);
     }
     default:
       NOTREACHED_NORETURN();
@@ -760,12 +762,16 @@
     bool skip_initialization_for_testing)
     : has_overlay_support_(skip_initialization_for_testing),
       allowed_yuv_overlay_count_(allowed_yuv_overlay_count),
+      is_on_battery_power_(
+          base::PowerMonitor::AddPowerStateObserverAndReturnOnBatteryState(
+              this)),
       no_undamaged_overlay_promotion_(base::FeatureList::IsEnabled(
           features::kNoUndamagedOverlayPromotion)) {
   if (!skip_initialization_for_testing) {
     UpdateHasHwOverlaySupport();
     UpdateSystemHDRStatus();
     UpdateP010VideoProcessorSupport();
+    UpdateAutoHDRVideoProcessorSupport();
     gl::DirectCompositionOverlayCapsMonitor::GetInstance()->AddObserver(this);
   }
   allow_promotion_hinting_ = media::SupportMediaFoundationClearPlayback();
@@ -773,6 +779,7 @@
 
 DCLayerOverlayProcessor::~DCLayerOverlayProcessor() {
   gl::DirectCompositionOverlayCapsMonitor::GetInstance()->RemoveObserver(this);
+  base::PowerMonitor::RemovePowerStateObserver(this);
 }
 
 void DCLayerOverlayProcessor::UpdateHasHwOverlaySupport() {
@@ -792,12 +799,21 @@
       gl::CheckVideoProcessorFormatSupport(DXGI_FORMAT_P010);
 }
 
+void DCLayerOverlayProcessor::UpdateAutoHDRVideoProcessorSupport() {
+  has_auto_hdr_video_processor_support_ = gl::VideoProcessorAutoHDRSupported();
+}
+
+void DCLayerOverlayProcessor::OnPowerStateChange(bool on_battery_power) {
+  is_on_battery_power_ = on_battery_power;
+}
+
 // Called on the Viz Compositor thread.
 void DCLayerOverlayProcessor::OnOverlayCapsChanged() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   UpdateHasHwOverlaySupport();
   UpdateSystemHDRStatus();
   UpdateP010VideoProcessorSupport();
+  UpdateAutoHDRVideoProcessorSupport();
 }
 
 void DCLayerOverlayProcessor::RemoveOverlayDamageRect(
@@ -902,8 +918,8 @@
     current_overlay_candidate_rects.reserve(
         current_overlay_candidate_rects.size() + candidates.size());
     for (auto candidate_it : candidates) {
-      if (AllowRemoveClearVideoQuadCandidatesWhenMoving(resource_provider,
-                                                        candidate_it)) {
+      if (AllowRemoveClearVideoQuadCandidatesWhenMoving(
+              resource_provider, candidate_it, force_overlay_for_auto_hdr())) {
         gfx::Rect quad_rect_in_target_space =
             ClippedQuadRectangle(*candidate_it);
         gfx::Rect quad_rect_in_root_space =
@@ -933,8 +949,9 @@
 
       auto candidate_it = candidates.begin();
       while (candidate_it != candidates.end()) {
-        if (AllowRemoveClearVideoQuadCandidatesWhenMoving(resource_provider,
-                                                          *candidate_it)) {
+        if (AllowRemoveClearVideoQuadCandidatesWhenMoving(
+                resource_provider, *candidate_it,
+                force_overlay_for_auto_hdr())) {
           RecordDCLayerResult(DC_LAYER_FAILED_YUV_VIDEO_QUAD_MOVED,
                               *candidate_it);
           candidate_it = candidates.erase(candidate_it);
diff --git a/components/viz/service/display/dc_layer_overlay.h b/components/viz/service/display/dc_layer_overlay.h
index 7fc5139..75d22a8 100644
--- a/components/viz/service/display/dc_layer_overlay.h
+++ b/components/viz/service/display/dc_layer_overlay.h
@@ -10,6 +10,7 @@
 #include "base/check_is_test.h"
 #include "base/containers/flat_map.h"
 #include "base/memory/raw_ptr.h"
+#include "base/power_monitor/power_monitor.h"
 #include "base/threading/thread_checker.h"
 #include "components/viz/common/quads/aggregated_render_pass.h"
 #include "components/viz/service/display/aggregated_frame.h"
@@ -26,7 +27,8 @@
 class DisplayResourceProvider;
 
 class VIZ_SERVICE_EXPORT DCLayerOverlayProcessor final
-    : public gl::DirectCompositionOverlayCapsObserver {
+    : public gl::DirectCompositionOverlayCapsObserver,
+      public base::PowerStateObserver {
  public:
   using FilterOperationsMap =
       base::flat_map<AggregatedRenderPassId, cc::FilterOperations*>;
@@ -81,19 +83,33 @@
 
   // DirectCompositionOverlayCapsObserver implementation.
   void OnOverlayCapsChanged() override;
+  // base::PowerStateObserver implementation.
+  void OnPowerStateChange(bool on_battery_power) override;
+
   void UpdateHasHwOverlaySupport();
   void UpdateSystemHDRStatus();
   void UpdateP010VideoProcessorSupport();
+  void UpdateAutoHDRVideoProcessorSupport();
 
   void set_frames_since_last_qualified_multi_overlays_for_testing(int value) {
     frames_since_last_qualified_multi_overlays_ = value;
   }
-  void set_system_hdr_enabled_for_testing(int value) {
+  void set_system_hdr_enabled_for_testing(bool value) {
     system_hdr_enabled_ = value;
   }
-  void set_has_p010_video_processor_support_for_testing(int value) {
+  void set_has_p010_video_processor_support_for_testing(bool value) {
     has_p010_video_processor_support_ = value;
   }
+  void set_has_auto_hdr_video_processor_support_for_testing(bool value) {
+    has_auto_hdr_video_processor_support_ = value;
+  }
+  void set_is_on_battery_power_for_testing(bool value) {
+    is_on_battery_power_ = value;
+  }
+  bool force_overlay_for_auto_hdr() {
+    return system_hdr_enabled_ && has_auto_hdr_video_processor_support_ &&
+           !is_on_battery_power_;
+  }
   size_t get_previous_frame_render_pass_count() const {
     CHECK_IS_TEST();
     return previous_frame_render_pass_states_.size();
@@ -318,11 +334,13 @@
 
   bool has_overlay_support_;
   bool has_p010_video_processor_support_ = false;
+  bool has_auto_hdr_video_processor_support_ = false;
   bool system_hdr_enabled_ = false;
   const int allowed_yuv_overlay_count_;
   uint64_t frames_since_last_qualified_multi_overlays_ = 0;
 
   bool allow_promotion_hinting_ = false;
+  bool is_on_battery_power_ = false;
 
   // Information about overlays from the previous frame.
   base::flat_map<AggregatedRenderPassId, RenderPassPreviousFrameState>
diff --git a/components/viz/service/display/overlay_dc_unittest.cc b/components/viz/service/display/overlay_dc_unittest.cc
index 6ec0c4e..4f3e2feb 100644
--- a/components/viz/service/display/overlay_dc_unittest.cc
+++ b/components/viz/service/display/overlay_dc_unittest.cc
@@ -281,7 +281,8 @@
 TEST_F(DCLayerOverlayTest, DisableVideoOverlayIfMovingFeature) {
   InitializeOverlayProcessor();
   auto ProcessForOverlaysSingleVideoRectWithOffset =
-      [&](gfx::Vector2d video_rect_offset, bool is_hdr = false) {
+      [&](gfx::Vector2d video_rect_offset, bool is_hdr = false,
+          bool is_sdr_to_hdr = false) {
         auto pass = CreateRenderPass();
         auto* video_quad = CreateFullscreenCandidateYUVVideoQuad(
             resource_provider_.get(), child_resource_provider_.get(),
@@ -319,6 +320,25 @@
 
           // Content has HDR10 colorspace.
           video_quad->video_color_space = gfx::ColorSpace::CreateHDR10();
+        } else if (is_sdr_to_hdr) {
+          // Render Pass has SDR content usage.
+          pass->content_color_usage = gfx::ContentColorUsage::kSRGB;
+
+          // Content is 8bit NV12 content.
+          video_quad->bits_per_channel = 8;
+
+          // Device is not using battery power.
+          overlay_processor_->set_is_on_battery_power_for_testing(false);
+
+          // Device enabled system HDR feature.
+          overlay_processor_->set_system_hdr_enabled_for_testing(true);
+
+          // Device has video processor auto hdr support.
+          overlay_processor_
+              ->set_has_auto_hdr_video_processor_support_for_testing(true);
+
+          // Content has 709 colorspace.
+          video_quad->video_color_space = gfx::ColorSpace::CreateREC709();
         }
 
         OverlayCandidateList dc_layer_list;
@@ -372,6 +392,27 @@
         features::kDisableVideoOverlayIfMoving);
     // We expect an overlay promotion after a couple frames of no movement
     for (int i = 0; i < 10; i++) {
+      ProcessForOverlaysSingleVideoRectWithOffset({0, 0}, /*is_hdr=*/false,
+                                                  /*is_sdr_to_hdr*/ true)
+          .size();
+    }
+    EXPECT_EQ(1U, ProcessForOverlaysSingleVideoRectWithOffset(
+                      {0, 0}, /*is_hdr=*/false, /*is_sdr_to_hdr*/ true)
+                      .size());
+    // We still expect an overlay promotion for SDR video when auto hdr is
+    // enabled and when moving to ensure uniform tone mapping results between
+    // viz and GPU driver.
+    EXPECT_EQ(1U, ProcessForOverlaysSingleVideoRectWithOffset(
+                      {1, 0}, /*is_hdr=*/false, /*is_sdr_to_hdr*/ true)
+                      .size());
+  }
+
+  {
+    base::test::ScopedFeatureList scoped_feature_list;
+    scoped_feature_list.InitAndEnableFeature(
+        features::kDisableVideoOverlayIfMoving);
+    // We expect an overlay promotion after a couple frames of no movement
+    for (int i = 0; i < 10; i++) {
       ProcessForOverlaysSingleVideoRectWithOffset({0, 0}, /*is_hdr=*/true)
           .size();
     }
diff --git a/components/viz/service/display/overlay_processor_win.h b/components/viz/service/display/overlay_processor_win.h
index 4d46943..6da6f5cd 100644
--- a/components/viz/service/display/overlay_processor_win.h
+++ b/components/viz/service/display/overlay_processor_win.h
@@ -77,13 +77,24 @@
     GetOverlayProcessor()
         ->set_frames_since_last_qualified_multi_overlays_for_testing(value);
   }
-  void set_system_hdr_enabled_for_testing(int value) {
+  void set_system_hdr_enabled_for_testing(bool value) {
+    CHECK_IS_TEST();
     GetOverlayProcessor()->set_system_hdr_enabled_for_testing(value);
   }
-  void set_has_p010_video_processor_support_for_testing(int value) {
+  void set_has_p010_video_processor_support_for_testing(bool value) {
+    CHECK_IS_TEST();
     GetOverlayProcessor()->set_has_p010_video_processor_support_for_testing(
         value);
   }
+  void set_has_auto_hdr_video_processor_support_for_testing(bool value) {
+    CHECK_IS_TEST();
+    GetOverlayProcessor()->set_has_auto_hdr_video_processor_support_for_testing(
+        value);
+  }
+  void set_is_on_battery_power_for_testing(bool value) {
+    CHECK_IS_TEST();
+    GetOverlayProcessor()->set_is_on_battery_power_for_testing(value);
+  }
   size_t get_previous_frame_render_pass_count() {
     CHECK_IS_TEST();
     return GetOverlayProcessor()->get_previous_frame_render_pass_count();
diff --git a/content/common/service_worker/race_network_request_read_buffer_manager.cc b/content/common/service_worker/race_network_request_read_buffer_manager.cc
index 7e76de6..5890a74f 100644
--- a/content/common/service_worker/race_network_request_read_buffer_manager.cc
+++ b/content/common/service_worker/race_network_request_read_buffer_manager.cc
@@ -4,10 +4,7 @@
 
 #include "content/common/service_worker/race_network_request_read_buffer_manager.h"
 #include "base/debug/crash_logging.h"
-#include "base/memory/scoped_refptr.h"
 #include "mojo/public/c/system/types.h"
-#include "net/base/io_buffer.h"
-#include "services/network/public/cpp/features.h"
 
 namespace content {
 RaceNetworkRequestReadBufferManager::RaceNetworkRequestReadBufferManager(
@@ -31,41 +28,33 @@
   watcher_.ArmOrNotify();
 }
 
+MojoResult RaceNetworkRequestReadBufferManager::EndReadData(
+    size_t num_bytes_read) {
+  return consumer_handle_->EndReadData(num_bytes_read);
+}
 
 void RaceNetworkRequestReadBufferManager::CancelWatching() {
   watcher_.Cancel();
 }
 
 std::pair<MojoResult, base::span<const char>>
-RaceNetworkRequestReadBufferManager::ReadData() {
-  CHECK_EQ(BytesRemaining(), 0u);
-  uint32_t num_bytes = network::features::GetDataPipeDefaultAllocationSize(
-      network::features::DataPipeAllocationSize::kLargerSizeIfPossible);
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBufferWithSize>(num_bytes);
-  MojoResult result = consumer_handle_->ReadData(buffer->data(), &num_bytes,
-                                                 MOJO_READ_DATA_FLAG_NONE);
+RaceNetworkRequestReadBufferManager::BeginReadData() {
+  const void* buffer;
+  uint32_t buffer_num_bytes = 0;
+  base::span<const char> read_buffer;
+  MojoResult result = consumer_handle_->BeginReadData(
+      &buffer, &buffer_num_bytes, MOJO_BEGIN_READ_DATA_FLAG_NONE);
   if (result == MOJO_RESULT_OK) {
-    buffer_ = base::MakeRefCounted<net::DrainableIOBuffer>(std::move(buffer),
-                                                           num_bytes);
+    SCOPED_CRASH_KEY_NUMBER("SWRace", "num_bytes_read_buffer",
+                            buffer_num_bytes);
+    volatile const char* buffer_v = static_cast<volatile const char*>(buffer);
+    for (size_t i = 0; i < buffer_num_bytes; ++i) {
+      buffer_v[i];
+    }
+    read_buffer =
+        base::make_span(static_cast<const char*>(buffer), buffer_num_bytes);
   }
 
-  return std::make_pair(result,
-                        buffer_ ? buffer_->span() : base::span<const char>());
-}
-
-void RaceNetworkRequestReadBufferManager::ConsumeData(size_t num_bytes_read) {
-  CHECK(buffer_);
-  buffer_->DidConsume(num_bytes_read);
-}
-
-size_t RaceNetworkRequestReadBufferManager::BytesRemaining() const {
-  return buffer_ ? buffer_->BytesRemaining() : 0;
-}
-
-base::span<const char> RaceNetworkRequestReadBufferManager::RemainingBuffer()
-    const {
-  CHECK(buffer_);
-  return buffer_->span();
+  return std::make_pair(result, read_buffer);
 }
 }  // namespace content
diff --git a/content/common/service_worker/race_network_request_read_buffer_manager.h b/content/common/service_worker/race_network_request_read_buffer_manager.h
index 77d965e..be56ab8 100644
--- a/content/common/service_worker/race_network_request_read_buffer_manager.h
+++ b/content/common/service_worker/race_network_request_read_buffer_manager.h
@@ -8,12 +8,10 @@
 #include <optional>
 
 #include "base/containers/span.h"
-#include "base/memory/scoped_refptr.h"
 #include "content/common/content_export.h"
 #include "mojo/public/c/system/types.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "mojo/public/cpp/system/simple_watcher.h"
-#include "net/base/io_buffer.h"
 
 namespace content {
 class CONTENT_EXPORT RaceNetworkRequestReadBufferManager {
@@ -31,19 +29,12 @@
   void CancelWatching();
   bool IsWatching() { return watcher_.IsWatching(); }
 
-  // Returns MojoResult of DataPipe::ReadData() result, and actual read data.
-  // The caller must call this only when |RemainingBuffer()| size is zero.
-  std::pair<MojoResult, base::span<const char>> ReadData();
-  // Consumes |buffer_| by given |num_bytes_read| bytes.
-  void ConsumeData(size_t num_bytes_read);
-
-  size_t BytesRemaining() const;
-  base::span<const char> RemainingBuffer() const;
+  std::pair<MojoResult, base::span<const char>> BeginReadData();
+  MojoResult EndReadData(size_t num_bytes_read);
 
  private:
   mojo::ScopedDataPipeConsumerHandle consumer_handle_;
   mojo::SimpleWatcher watcher_;
-  scoped_refptr<net::DrainableIOBuffer> buffer_;
 };
 }  // namespace content
 
diff --git a/content/common/service_worker/race_network_request_read_buffer_manager_unittest.cc b/content/common/service_worker/race_network_request_read_buffer_manager_unittest.cc
index fc30c36..2295732c 100644
--- a/content/common/service_worker/race_network_request_read_buffer_manager_unittest.cc
+++ b/content/common/service_worker/race_network_request_read_buffer_manager_unittest.cc
@@ -54,13 +54,13 @@
   buffer_manager.Watch(base::BindLambdaForTesting(
       [&](MojoResult result, const mojo::HandleSignalsState& state) {
         EXPECT_EQ(result, MOJO_RESULT_OK);
-        auto [read_result, buffer] = buffer_manager.ReadData();
+        auto [read_result, buffer] = buffer_manager.BeginReadData();
         EXPECT_EQ(read_result, MOJO_RESULT_OK);
         EXPECT_EQ(result, MOJO_RESULT_OK);
         EXPECT_EQ(buffer.size(), num_bytes);
         std::string_view expected_str(expected_data);
         EXPECT_EQ(buffer.data(), expected_str);
-        buffer_manager.ConsumeData(num_bytes);
+        EXPECT_EQ(buffer_manager.EndReadData(num_bytes), MOJO_RESULT_OK);
         base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
             FROM_HERE, run_loop.QuitClosure());
       }));
diff --git a/content/common/service_worker/race_network_request_url_loader_client.cc b/content/common/service_worker/race_network_request_url_loader_client.cc
index 9500ec9..b3198c5 100644
--- a/content/common/service_worker/race_network_request_url_loader_client.cc
+++ b/content/common/service_worker/race_network_request_url_loader_client.cc
@@ -383,77 +383,46 @@
 }
 
 void ServiceWorkerRaceNetworkRequestURLLoaderClient::WatchDataUpdate() {
-  auto write_callback =
+  auto callback_func =
       base::GetFieldTrialParamByFeatureAsBool(
           features::kServiceWorkerAutoPreload, "use_two_phase_write", true)
-          ? &ServiceWorkerRaceNetworkRequestURLLoaderClient::TwoPhaseWrite
-          : &ServiceWorkerRaceNetworkRequestURLLoaderClient::Write;
+          ? &ServiceWorkerRaceNetworkRequestURLLoaderClient::
+                ReadAndTwoPhaseWrite
+          : &ServiceWorkerRaceNetworkRequestURLLoaderClient::ReadAndWrite;
   CHECK(read_buffer_manager_.has_value());
   read_buffer_manager_->Watch(
-      base::BindRepeating(&ServiceWorkerRaceNetworkRequestURLLoaderClient::Read,
-                          weak_factory_.GetWeakPtr()));
+      base::BindRepeating(callback_func, weak_factory_.GetWeakPtr()));
   read_buffer_manager_->ArmOrNotify();
   write_buffer_manager_for_race_network_request_.Watch(
-      base::BindRepeating(write_callback, weak_factory_.GetWeakPtr()));
+      base::BindRepeating(callback_func, weak_factory_.GetWeakPtr()));
   write_buffer_manager_for_fetch_handler_.Watch(
-      base::BindRepeating(write_callback, weak_factory_.GetWeakPtr()));
+      base::BindRepeating(callback_func, weak_factory_.GetWeakPtr()));
 }
 
-void ServiceWorkerRaceNetworkRequestURLLoaderClient::Read(
+void ServiceWorkerRaceNetworkRequestURLLoaderClient::ReadAndTwoPhaseWrite(
     MojoResult result,
     const mojo::HandleSignalsState& state) {
-  if (!IsReadyToHandleReadWrite(result)) {
+  std::optional<base::span<const char>> read_buffer = StartReadData(result);
+  if (!read_buffer.has_value()) {
     return;
   }
+  TwoPhaseWrite(read_buffer.value());
+}
 
-  CHECK(read_buffer_manager_.has_value());
-  if (read_buffer_manager_->BytesRemaining() > 0) {
-    write_buffer_manager_for_race_network_request_.ArmOrNotify();
-    write_buffer_manager_for_fetch_handler_.ArmOrNotify();
+void ServiceWorkerRaceNetworkRequestURLLoaderClient::ReadAndWrite(
+    MojoResult result,
+    const mojo::HandleSignalsState& state) {
+  std::optional<base::span<const char>> read_buffer = StartReadData(result);
+  if (!read_buffer.has_value()) {
     return;
   }
-
-  auto [read_result, read_buffer] = read_buffer_manager_->ReadData();
-  TRACE_EVENT_WITH_FLOW2("ServiceWorker",
-                         "ServiceWorkerRaceNetworkRequestURLLoaderClient::Read",
-                         TRACE_ID_LOCAL(this),
-                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
-                         "url", request_.url, "read_data_result", result);
-  RecordMojoResultForDataTransfer(result, "Read");
-  switch (read_result) {
-    case MOJO_RESULT_OK:
-      CHECK(state.readable());
-      write_buffer_manager_for_race_network_request_.ArmOrNotify();
-      write_buffer_manager_for_fetch_handler_.ArmOrNotify();
-      return;
-    case MOJO_RESULT_FAILED_PRECONDITION:
-      // Successfully read the whole data. This case the peer is already closed.
-      CHECK(state.peer_closed());
-      OnDataTransferComplete();
-      return;
-    case MOJO_RESULT_BUSY:
-    case MOJO_RESULT_SHOULD_WAIT:
-      return;
-    default:
-      NOTREACHED() << "ReadData result:" << result;
-      return;
-  }
+  Write(read_buffer.value());
 }
 
 void ServiceWorkerRaceNetworkRequestURLLoaderClient::TwoPhaseWrite(
-    MojoResult result,
-    const mojo::HandleSignalsState& state) {
-  if (!IsReadyToHandleReadWrite(result)) {
-    return;
-  }
-
+    base::span<const char> read_buffer) {
   CHECK(read_buffer_manager_.has_value());
-  if (read_buffer_manager_->BytesRemaining() == 0) {
-    read_buffer_manager_->ArmOrNotify();
-    return;
-  }
-  base::span<const char> read_buffer = read_buffer_manager_->RemainingBuffer();
-
+  MojoResult result;
   uint32_t num_bytes_to_consume = 0;
   if (write_buffer_manager_for_race_network_request_.IsWatching() &&
       write_buffer_manager_for_fetch_handler_.IsWatching()) {
@@ -465,6 +434,7 @@
       case MOJO_RESULT_OK:
         break;
       case MOJO_RESULT_FAILED_PRECONDITION:
+        read_buffer_manager_->EndReadData(0);
         // The data pipe consumer is aborted.
         TransitionState(State::kAborted);
         Abort();
@@ -472,6 +442,7 @@
       case MOJO_RESULT_SHOULD_WAIT:
         // The data pipe is not writable yet. We don't consume data from |body_|
         // and write any data in this case. And retry it later.
+        read_buffer_manager_->EndReadData(0);
         write_buffer_manager_for_race_network_request_.EndWriteData(0);
         write_buffer_manager_for_race_network_request_.ArmOrNotify();
         return;
@@ -482,6 +453,7 @@
       case MOJO_RESULT_OK:
         break;
       case MOJO_RESULT_FAILED_PRECONDITION:
+        read_buffer_manager_->EndReadData(0);
         TransitionState(State::kAborted);
         Abort();
         return;
@@ -490,6 +462,7 @@
         // not consumed yet but the buffer is full. Stop processing the data
         // pipe for the fetch handler side, not to make the data transfer
         // process for the race network request side being stuck.
+        read_buffer_manager_->EndReadData(0);
         write_buffer_manager_for_race_network_request_.EndWriteData(0);
         write_buffer_manager_for_fetch_handler_.EndWriteData(0);
         write_buffer_manager_for_fetch_handler_.CancelWatching();
@@ -524,10 +497,12 @@
       case MOJO_RESULT_OK:
         break;
       case MOJO_RESULT_FAILED_PRECONDITION:
+        read_buffer_manager_->EndReadData(0);
         TransitionState(State::kAborted);
         Abort();
         return;
       case MOJO_RESULT_SHOULD_WAIT:
+        read_buffer_manager_->EndReadData(0);
         write_buffer_manager_for_race_network_request_.EndWriteData(0);
         write_buffer_manager_for_race_network_request_.ArmOrNotify();
         return;
@@ -544,10 +519,12 @@
       case MOJO_RESULT_OK:
         break;
       case MOJO_RESULT_FAILED_PRECONDITION:
+        read_buffer_manager_->EndReadData(0);
         TransitionState(State::kAborted);
         Abort();
         return;
       case MOJO_RESULT_SHOULD_WAIT:
+        read_buffer_manager_->EndReadData(0);
         write_buffer_manager_for_fetch_handler_.EndWriteData(0);
         write_buffer_manager_for_fetch_handler_.ArmOrNotify();
         return;
@@ -560,19 +537,9 @@
 }
 
 void ServiceWorkerRaceNetworkRequestURLLoaderClient::Write(
-    MojoResult result,
-    const mojo::HandleSignalsState& state) {
-  if (!IsReadyToHandleReadWrite(result)) {
-    return;
-  }
-
+    base::span<const char> read_buffer) {
   CHECK(read_buffer_manager_.has_value());
-  if (read_buffer_manager_->BytesRemaining() == 0) {
-    read_buffer_manager_->ArmOrNotify();
-    return;
-  }
-  base::span<const char> read_buffer = read_buffer_manager_->RemainingBuffer();
-
+  MojoResult result;
   size_t num_bytes_to_consume = read_buffer.size();
   if (write_buffer_manager_for_race_network_request_.IsWatching() &&
       write_buffer_manager_for_fetch_handler_.IsWatching()) {
@@ -585,6 +552,7 @@
       case MOJO_RESULT_OK:
         break;
       case MOJO_RESULT_FAILED_PRECONDITION:
+        read_buffer_manager_->EndReadData(0);
         // The data pipe consumer is aborted.
         TransitionState(State::kAborted);
         Abort();
@@ -593,6 +561,7 @@
       case MOJO_RESULT_OUT_OF_RANGE:
         // The data pipe is not writable yet. We don't consume data from |body_|
         // and write any data in this case. And retry it later.
+        read_buffer_manager_->EndReadData(0);
         write_buffer_manager_for_race_network_request_.ArmOrNotify();
         return;
     }
@@ -603,6 +572,7 @@
       case MOJO_RESULT_OK:
         break;
       case MOJO_RESULT_FAILED_PRECONDITION:
+        read_buffer_manager_->EndReadData(0);
         TransitionState(State::kAborted);
         Abort();
         return;
@@ -612,6 +582,7 @@
         // not consumed yet but the buffer is full. Stop processing the data
         // pipe for the fetch handler side, not to make the data transfer
         // process for the race network request side being stuck.
+        read_buffer_manager_->EndReadData(read_buffer.size());
         write_buffer_manager_for_fetch_handler_.CancelWatching();
         write_buffer_manager_for_race_network_request_.ArmOrNotify();
         return;
@@ -630,11 +601,13 @@
       case MOJO_RESULT_OK:
         break;
       case MOJO_RESULT_FAILED_PRECONDITION:
+        read_buffer_manager_->EndReadData(0);
         TransitionState(State::kAborted);
         Abort();
         return;
       case MOJO_RESULT_SHOULD_WAIT:
       case MOJO_RESULT_OUT_OF_RANGE:
+        read_buffer_manager_->EndReadData(0);
         write_buffer_manager_for_race_network_request_.ArmOrNotify();
         return;
     }
@@ -648,11 +621,13 @@
       case MOJO_RESULT_OK:
         break;
       case MOJO_RESULT_FAILED_PRECONDITION:
+        read_buffer_manager_->EndReadData(0);
         TransitionState(State::kAborted);
         Abort();
         return;
       case MOJO_RESULT_SHOULD_WAIT:
       case MOJO_RESULT_OUT_OF_RANGE:
+        read_buffer_manager_->EndReadData(0);
         write_buffer_manager_for_fetch_handler_.ArmOrNotify();
         return;
     }
@@ -660,21 +635,44 @@
   CompleteReadData(num_bytes_to_consume);
 }
 
-bool ServiceWorkerRaceNetworkRequestURLLoaderClient::IsReadyToHandleReadWrite(
-    MojoResult result) {
+std::optional<base::span<const char>>
+ServiceWorkerRaceNetworkRequestURLLoaderClient::StartReadData(
+    MojoResult initial_mojo_result) {
   if (!owner_) {
-    return false;
+    return std::nullopt;
   }
   if (state_ == State::kDataTransferFinished) {
-    return false;
+    return std::nullopt;
   }
 
-  RecordMojoResultForDataTransfer(result, "Initial");
-  if (result != MOJO_RESULT_OK) {
-    return false;
+  RecordMojoResultForDataTransfer(initial_mojo_result, "Initial");
+  if (initial_mojo_result != MOJO_RESULT_OK) {
+    return std::nullopt;
   }
 
-  return true;
+  CHECK(read_buffer_manager_.has_value());
+  auto [result, read_buffer] = read_buffer_manager_->BeginReadData();
+  TRACE_EVENT_WITH_FLOW2(
+      "ServiceWorker",
+      "ServiceWorkerRaceNetworkRequestURLLoaderClient::ReadAndWrite",
+      TRACE_ID_LOCAL(this),
+      TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "url", request_.url,
+      "read_data_result", result);
+  RecordMojoResultForDataTransfer(result, "Read");
+  switch (result) {
+    case MOJO_RESULT_OK:
+      return read_buffer;
+    case MOJO_RESULT_FAILED_PRECONDITION:
+      // Successfully read the whole data.
+      OnDataTransferComplete();
+      return std::nullopt;
+    case MOJO_RESULT_BUSY:
+    case MOJO_RESULT_SHOULD_WAIT:
+      return std::nullopt;
+    default:
+      NOTREACHED() << "BeginReadData result:" << result;
+      return std::nullopt;
+  }
 }
 
 void ServiceWorkerRaceNetworkRequestURLLoaderClient::RecordMojoResultForWrite(
@@ -685,7 +683,8 @@
 void ServiceWorkerRaceNetworkRequestURLLoaderClient::CompleteReadData(
     uint32_t num_bytes_to_consume) {
   CHECK(read_buffer_manager_.has_value());
-  read_buffer_manager_->ConsumeData(num_bytes_to_consume);
+  MojoResult result = read_buffer_manager_->EndReadData(num_bytes_to_consume);
+  CHECK_EQ(result, MOJO_RESULT_OK);
   // Once data is written to the data pipe, start the commit process.
   MaybeCommitResponse();
   read_buffer_manager_->ArmOrNotify();
diff --git a/content/common/service_worker/race_network_request_url_loader_client.h b/content/common/service_worker/race_network_request_url_loader_client.h
index 4b829e9..931be09 100644
--- a/content/common/service_worker/race_network_request_url_loader_client.h
+++ b/content/common/service_worker/race_network_request_url_loader_client.h
@@ -179,19 +179,14 @@
   void OnDataTransferComplete();
   void TransitionState(State new_state);
 
-  // Reads data from RaceNetworkRequestReadBufferManager. If there is a buffer
-  // to read, notifies the write buffer manager to start write operations.
-  // If no buffer to read, calls |OnDataTransferComplete()| and return nothing.
-  void Read(MojoResult result, const mojo::HandleSignalsState& state);
-  // Writes data in RaceNetworkRequestReadBufferManager into the data
-  // pipe producer that handles for both the race network request and the fetch
-  // handler respectively.
+  // Reads data from |body_|, and writes it into the data pipe producer handles
+  // for both the race network request and the fetch handler respectively.
   //
   // To guarantee the consistent data between the race network request and the
   // fetch handler, this method always writes a same chunk of data into two data
   // pipe handles. If one side fails the data write process for some reason, we
-  // don't consume the buffer, and retry it later. the buffer is consumed only
-  // when the both producer handles successfully write data.
+  // don't consume |body_| data, and retry it later. |body_| data is consumed
+  // only when the both producer handles successfully write data.
   //
   // When the first chunk of data is written to the data pipes, this starts the
   // commit process. And when the data transfer is finished, this complete the
@@ -201,21 +196,30 @@
   // process, and there could be the case if the response is not returned due to
   // the long fetch handler execution. and test case the mechanism to wait for
   // the fetch handler
-  void TwoPhaseWrite(MojoResult result, const mojo::HandleSignalsState& state);
-  // Writes data in RaceNetworkRequestReadBufferManager into the data
-  // pipe producer that handles for both the race network request and the fetch
-  // handler respectively.
+  void ReadAndTwoPhaseWrite(MojoResult result,
+                            const mojo::HandleSignalsState& state);
+  // Reads data from |body_|, and writes it into the data pipe producer handles
+  // for both the race network request and the fetch handler respectively.
   //
-  // Unlike |TwoPhaseWrite()|, this doesn't use two-phase operations to
+  // Unlike |ReadAndTwoPhaseWrite()|, this doesn't use two-phase operations to
   // write data into data pipes. However, the result should be the same as
-  // |TwoPhaseWrite()| because mojo's |WriteData()| is expected to write
+  // |ReadAndTwoPhaseWrite()| because mojo's |WriteData()| is expected to write
   // the same amount of data from the given data pipe consumer handle to read.
-  // also |Write()| has CHECK to guarantee that the actual written sizes
+  // also |ReadAndWrite()| has CHECK to guarantee that the actual written sizes
   // to data pips are exactly same.
-  void Write(MojoResult result, const mojo::HandleSignalsState& state);
+  void ReadAndWrite(MojoResult result, const mojo::HandleSignalsState& state);
 
-  bool IsReadyToHandleReadWrite(MojoResult result);
+  void Write(base::span<const char> read_buffer);
+  void TwoPhaseWrite(base::span<const char> read_buffer);
 
+  // Begins a two-phase read from |body_|, the data pipe consumer. If succeed,
+  // the read buffer is returned. If there are no data to read from the data
+  // pipe, this internally calls |OnDataTransferComplete()| and return nothing.
+  //
+  // Since this starts a two-phase read process, `EndReadData()` in |body_|
+  // has to be called after calling this function.
+  std::optional<base::span<const char>> StartReadData(
+      MojoResult initial_mojo_result);
   void CompleteReadData(uint32_t num_bytes_to_consume);
   void WatchDataUpdate();
 
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc
index 194c919b..1e013ce 100644
--- a/content/public/renderer/content_renderer_client.cc
+++ b/content/public/renderer/content_renderer_client.cc
@@ -282,9 +282,4 @@
 }
 #endif
 
-std::unique_ptr<blink::WebLinkPreviewTriggerer>
-ContentRendererClient::CreateLinkPreviewTriggerer() {
-  return nullptr;
-}
-
 }  // namespace content
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h
index 0b708ec..ff20508 100644
--- a/content/public/renderer/content_renderer_client.h
+++ b/content/public/renderer/content_renderer_client.h
@@ -30,7 +30,6 @@
 #include "third_party/blink/public/platform/url_loader_throttle_provider.h"
 #include "third_party/blink/public/platform/web_content_settings_client.h"
 #include "third_party/blink/public/platform/websocket_handshake_throttle_provider.h"
-#include "third_party/blink/public/web/web_link_preview_triggerer.h"
 #include "third_party/blink/public/web/web_navigation_policy.h"
 #include "third_party/blink/public/web/web_navigation_type.h"
 #include "ui/base/page_transition_types.h"
@@ -439,13 +438,6 @@
   virtual std::unique_ptr<cast_streaming::ResourceProvider>
   CreateCastStreamingResourceProvider();
 #endif
-
-  // Creates a WebLinkPreviewTriggerer if an embedder wants to observe events
-  // and trigger preview. It is allowed to return nullptr.
-  //
-  // See blink::WebLinkPreviewTriggerer for more details.
-  virtual std::unique_ptr<blink::WebLinkPreviewTriggerer>
-  CreateLinkPreviewTriggerer();
 };
 
 }  // namespace content
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 67034e1..9dbf4ba 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -215,7 +215,6 @@
 #include "third_party/blink/public/web/web_frame_serializer.h"
 #include "third_party/blink/public/web/web_frame_widget.h"
 #include "third_party/blink/public/web/web_input_method_controller.h"
-#include "third_party/blink/public/web/web_link_preview_triggerer.h"
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "third_party/blink/public/web/web_navigation_control.h"
 #include "third_party/blink/public/web/web_navigation_policy.h"
@@ -6768,11 +6767,6 @@
   return web_view;
 }
 
-std::unique_ptr<blink::WebLinkPreviewTriggerer>
-RenderFrameImpl::CreateLinkPreviewTriggerer() {
-  return GetContentClient()->renderer()->CreateLinkPreviewTriggerer();
-}
-
 void RenderFrameImpl::ResetMembersUsedForDurationOfCommit() {
   pending_loader_factories_ = nullptr;
   pending_code_cache_host_.reset();
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index f44502d..85da2609 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -107,7 +107,6 @@
 #include "third_party/blink/public/web/web_frame_load_type.h"
 #include "third_party/blink/public/web/web_frame_serializer_client.h"
 #include "third_party/blink/public/web/web_history_commit_type.h"
-#include "third_party/blink/public/web/web_link_preview_triggerer.h"
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "third_party/blink/public/web/web_local_frame_client.h"
 #include "third_party/blink/public/web/web_meaningful_layout.h"
@@ -675,8 +674,6 @@
       const std::optional<blink::Impression>& impression,
       const std::optional<blink::WebPictureInPictureWindowOptions>& pip_options,
       const blink::WebURL& base_url) override;
-  std::unique_ptr<blink::WebLinkPreviewTriggerer> CreateLinkPreviewTriggerer()
-      override;
 
   // Dispatches the current state of selection on the webpage to the browser if
   // it has changed or if the forced flag is passed. The forced flag is used
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
index b5a7a9c..23481a0 100644
--- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -357,9 +357,6 @@
 crbug.com/1230619 [ android-nexus-5x android android-webview-instrumentation ] Pixel_WebGLFloat [ Failure ]
 crbug.com/1230619 [ android-chromium android-pixel-4 android-r angle-disabled no-clang-coverage no-passthrough qualcomm renderer-skia-gl target-cpu-32 ] Pixel_WebGLFloat [ Failure ]
 
-# Failing likely due to protected memory, but cause TBD.
-crbug.com/1420067 [ fuchsia fuchsia-board-astro ] Pixel_Video* [ Failure ]
-crbug.com/1420067 [ fuchsia fuchsia-board-sherlock ] Pixel_Video* [ Failure ]
 
 
 # Pixel 6 failures.
diff --git a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
index ed0f35d4..ca99510e 100644
--- a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
@@ -195,8 +195,6 @@
 # WebGL's accelerated canvas capture is currently only supported on Win, Mac, ChromeOS.
 crbug.com/1201009 [ linux ] WebGLCanvasCaptureTraceTest_VideoStreamFromWebGLCanvas_OneCopy [ Failure ]
 crbug.com/1201009 [ linux ] WebGLCanvasCaptureTraceTest_VideoStreamFromWebGLCanvas_TwoCopy_Accelerated [ Failure ]
-crbug.com/1201009 [ fuchsia ] WebGLCanvasCaptureTraceTest_VideoStreamFromWebGLCanvas_OneCopy [ Failure ]
-crbug.com/1201009 [ fuchsia ] WebGLCanvasCaptureTraceTest_VideoStreamFromWebGLCanvas_TwoCopy_Accelerated [ Failure ]
 
 
 # WebGL drawingBufferStorage does not work on Pixel 4, Samsung A23, nexus-5x or
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
index f33a37f..f793a6d 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -525,7 +525,6 @@
 
 ## SkiaGraphite on AMD/Intel ##
 
-crbug.com/326283382 [ mac angle-metal graphite-enabled ] conformance/context/context-creation-and-destruction.html [ RetryOnFailure ]
 
 ## Metal AMD ##
 
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index 72a1bf2..bc369a3 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -456,12 +456,9 @@
 
 
 # Flaky tests
-crbug.com/1489477 [ fuchsia web-engine-shell ] WebglExtension_EXT_float_blend [ Failure ]
 crbug.com/1489477 [ fuchsia fuchsia-board-astro ] conformance/textures/misc/texture-size-limit.html [ Failure ]
 crbug.com/1489477 [ fuchsia fuchsia-board-sherlock ] conformance/textures/misc/texture-size-limit.html [ Failure ]
 
-# Anti-aliasing disabled on Fuchsia
-[ fuchsia ] conformance/context/context-attributes-alpha-depth-stencil-antialias.html [ Failure ]
 
 
 ####################
@@ -530,7 +527,6 @@
 
 ## SkiaGraphite on AMD/Intel ##
 
-crbug.com/326283382 [ mac angle-metal graphite-enabled ] conformance/context/context-creation-and-destruction.html [ RetryOnFailure ]
 
 ## SkiaGraphite on on SwANGLE ##
 
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h
index 511620a..021e7572 100644
--- a/extensions/browser/extension_function_histogram_value.h
+++ b/extensions/browser/extension_function_histogram_value.h
@@ -1931,6 +1931,7 @@
   AUTOTESTPRIVATE_SETDEVICELANGUAGE = 1869,
   AUTOFILLPRIVATE_SETAUTOFILLSYNCTOGGLEENABLED = 1870,
   ODFSCONFIGPRIVATE_ISFILESYSTEMPROVIDERCLOUDFILESYSTEMENABLED = 1871,
+  PDFVIEWERPRIVATE_SETPDFDOCUMENTTITLE = 1872,
   // Last entry: Add new entries above, then run:
   // tools/metrics/histograms/update_extension_histograms.py
   ENUM_BOUNDARY
diff --git a/gpu/config/gpu_util.cc b/gpu/config/gpu_util.cc
index fe8762a..2746d3d 100644
--- a/gpu/config/gpu_util.cc
+++ b/gpu/config/gpu_util.cc
@@ -351,15 +351,16 @@
       };
 
   gl::GlWorkarounds workarounds = {
-    .disable_d3d11 = is_enabled(DISABLE_D3D11),
-    .disable_metal = is_enabled(DISABLE_METAL),
-    .disable_es3gl_context = is_enabled(DISABLE_ES3_GL_CONTEXT),
-    .disable_es3gl_context_for_testing =
-        is_enabled(DISABLE_ES3_GL_CONTEXT_FOR_TESTING),
+      .disable_d3d11 = is_enabled(DISABLE_D3D11),
+      .disable_metal = is_enabled(DISABLE_METAL),
+      .disable_es3gl_context = is_enabled(DISABLE_ES3_GL_CONTEXT),
+      .disable_es3gl_context_for_testing =
+          is_enabled(DISABLE_ES3_GL_CONTEXT_FOR_TESTING),
 #if BUILDFLAG(IS_WIN)
-    .disable_direct_composition = is_enabled(DISABLE_DIRECT_COMPOSITION),
-    .disable_direct_composition_video_overlays =
-        is_enabled(DISABLE_DIRECT_COMPOSITION_VIDEO_OVERLAYS),
+      .disable_direct_composition = is_enabled(DISABLE_DIRECT_COMPOSITION),
+      .disable_direct_composition_video_overlays =
+          is_enabled(DISABLE_DIRECT_COMPOSITION_VIDEO_OVERLAYS),
+      .disable_vp_auto_hdr = is_enabled(DISABLE_VP_AUTO_HDR),
 #endif
   };
 
diff --git a/infra/config/generated/luci/project.cfg b/infra/config/generated/luci/project.cfg
index 7c31c6b..2dc5849 100644
--- a/infra/config/generated/luci/project.cfg
+++ b/infra/config/generated/luci/project.cfg
@@ -7,7 +7,7 @@
 name: "chromium"
 access: "group:all"
 lucicfg {
-  version: "1.43.4"
+  version: "1.43.5"
   package_dir: "../.."
   config_dir: "generated/luci"
   entry_point: "main.star"
diff --git a/infra/config/generated/testing/variants.pyl b/infra/config/generated/testing/variants.pyl
index 8f96eb02..3e3be86 100644
--- a/infra/config/generated/testing/variants.pyl
+++ b/infra/config/generated/testing/variants.pyl
@@ -307,16 +307,16 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'identifier': 'Lacros version skew testing ash canary',
-    'description': 'Run with ash-chrome version 124.0.6330.0',
+    'description': 'Run with ash-chrome version 124.0.6331.0',
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6330.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6331.0/test_ash_chrome',
     ],
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v124.0.6330.0',
-          'revision': 'version:124.0.6330.0',
+          'location': 'lacros_version_skew_tests_v124.0.6331.0',
+          'revision': 'version:124.0.6331.0',
         },
       ],
     },
diff --git a/infra/config/targets/lacros-version-skew-variants.json b/infra/config/targets/lacros-version-skew-variants.json
index b5438eb..f16c01c 100644
--- a/infra/config/targets/lacros-version-skew-variants.json
+++ b/infra/config/targets/lacros-version-skew-variants.json
@@ -1,16 +1,16 @@
 {
   "LACROS_VERSION_SKEW_CANARY": {
     "args": [
-      "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6330.0/test_ash_chrome"
+      "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6331.0/test_ash_chrome"
     ],
-    "description": "Run with ash-chrome version 124.0.6330.0",
+    "description": "Run with ash-chrome version 124.0.6331.0",
     "identifier": "Lacros version skew testing ash canary",
     "swarming": {
       "cipd_packages": [
         {
           "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-          "location": "lacros_version_skew_tests_v124.0.6330.0",
-          "revision": "version:124.0.6330.0"
+          "location": "lacros_version_skew_tests_v124.0.6331.0",
+          "revision": "version:124.0.6331.0"
         }
       ]
     }
diff --git a/media/gpu/mac/BUILD.gn b/media/gpu/mac/BUILD.gn
index d42ee6fd..3059412 100644
--- a/media/gpu/mac/BUILD.gn
+++ b/media/gpu/mac/BUILD.gn
@@ -10,7 +10,9 @@
 
 assert(is_apple)
 
-import("//build/config/mac/mac_sdk.gni")
+if (is_mac) {
+  import("//build/config/mac/mac_sdk.gni")
+}
 
 source_set("mac") {
   defines = [ "MEDIA_GPU_IMPLEMENTATION" ]
diff --git a/media/gpu/vaapi/vaapi_unittest.cc b/media/gpu/vaapi/vaapi_unittest.cc
index 8d66017..a83914c 100644
--- a/media/gpu/vaapi/vaapi_unittest.cc
+++ b/media/gpu/vaapi/vaapi_unittest.cc
@@ -467,6 +467,31 @@
   }
 }
 
+// Verifies that VaapiWrapper::Create...() fails after the limit of created
+// instances exceeds the threshold.
+TEST_F(VaapiTest, TooManyDecoderInstances) {
+  std::map<VAProfile, std::vector<VAEntrypoint>> configurations =
+      VaapiWrapper::GetSupportedConfigurationsForCodecModeForTesting(
+          VaapiWrapper::kDecode);
+  // H.264 decoding is currently supported everywhere, but leave an ASSERT.
+  constexpr auto kVAProfile = VAProfileH264ConstrainedBaseline;
+  ASSERT_TRUE(base::Contains(configurations, kVAProfile));
+
+  const int kMaxNumOfInstances = VaapiWrapper::GetMaxNumDecoderInstances();
+  std::vector<scoped_refptr<VaapiWrapper>> vaapi_wrappers(kMaxNumOfInstances);
+  for (auto& wrapper : vaapi_wrappers) {
+    wrapper =
+        VaapiWrapper::Create(VaapiWrapper::kDecode, kVAProfile,
+                             EncryptionScheme::kUnencrypted, base::DoNothing());
+    ASSERT_TRUE(wrapper);
+  }
+  // Next one fails
+  scoped_refptr<VaapiWrapper> wrapper =
+      VaapiWrapper::Create(VaapiWrapper::kDecode, kVAProfile,
+                           EncryptionScheme::kUnencrypted, base::DoNothing());
+  ASSERT_FALSE(wrapper);
+}
+
 // Verifies that VaapiWrapper::CreateContext() will queue up a buffer to set the
 // encoder to its lowest quality setting if a given VAProfile and VAEntrypoint
 // claims to support configuring it.
diff --git a/media/gpu/vaapi/vaapi_video_decoder.cc b/media/gpu/vaapi/vaapi_video_decoder.cc
index 7ab55e4f..d23e2dfb6 100644
--- a/media/gpu/vaapi/vaapi_video_decoder.cc
+++ b/media/gpu/vaapi/vaapi_video_decoder.cc
@@ -89,9 +89,6 @@
 
 }  // namespace
 
-// static
-base::AtomicRefCount VaapiVideoDecoder::num_instances_(0);
-
 VaapiVideoDecoder::DecodeTask::DecodeTask(scoped_refptr<DecoderBuffer> buffer,
                                           int32_t buffer_id,
                                           DecodeCB decode_done_cb)
@@ -108,13 +105,6 @@
     std::unique_ptr<MediaLog> media_log,
     scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
     base::WeakPtr<VideoDecoderMixin::Client> client) {
-  const bool can_create_decoder =
-      num_instances_.Increment() < kMaxNumOfInstances ||
-      !base::FeatureList::IsEnabled(media::kLimitConcurrentDecoderInstances);
-  if (!can_create_decoder) {
-    num_instances_.Decrement();
-    return nullptr;
-  }
   return base::WrapUnique<VideoDecoderMixin>(new VaapiVideoDecoder(
       std::move(media_log), std::move(decoder_task_runner), std::move(client)));
 }
@@ -173,8 +163,6 @@
     DCHECK(vaapi_wrapper_->HasOneRef());
     vaapi_wrapper_ = nullptr;
   }
-
-  num_instances_.Decrement();
 }
 
 void VaapiVideoDecoder::Initialize(const VideoDecoderConfig& config,
@@ -275,7 +263,9 @@
 #endif
   }
 
-  // Initialize VAAPI wrapper.
+  // TODO(b/266003084): Consider returning a std::expected or std::optional and
+  // figure out whether there are too many instances, returning kTooManyDecoders
+  // in that case.
   const VideoCodecProfile profile = config.profile();
   vaapi_wrapper_ = VaapiWrapper::CreateForVideoCodec(
 #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/media/gpu/vaapi/vaapi_video_decoder.h b/media/gpu/vaapi/vaapi_video_decoder.h
index 09c69b5..247e270f 100644
--- a/media/gpu/vaapi/vaapi_video_decoder.h
+++ b/media/gpu/vaapi/vaapi_video_decoder.h
@@ -199,16 +199,6 @@
       bool needs_detiling,
       base::TimeDelta timestamp);
 
-  // Having too many decoder instances at once may cause us to run out of FDs
-  // and subsequently crash (b/181264362). To avoid that, we limit the maximum
-  // number of decoder instances that can exist at once. |num_instances_| tracks
-  // that number.
-  //
-  // TODO(andrescj): we can relax this once we extract video decoding into its
-  // own process.
-  static constexpr int kMaxNumOfInstances = 16;
-  static base::AtomicRefCount num_instances_;
-
   // The video decoder's state.
   State state_ = State::kUninitialized;
 
diff --git a/media/gpu/vaapi/vaapi_wrapper.cc b/media/gpu/vaapi/vaapi_wrapper.cc
index 184444f9..dc20b6ca 100644
--- a/media/gpu/vaapi/vaapi_wrapper.cc
+++ b/media/gpu/vaapi/vaapi_wrapper.cc
@@ -25,6 +25,7 @@
 #include "base/containers/fixed_flat_set.h"
 #include "base/cpu.h"
 #include "base/environment.h"
+#include "base/feature_list.h"
 #include "base/files/scoped_file.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
@@ -1638,6 +1639,25 @@
 }
 
 // static
+int VaapiWrapper::GetMaxNumDecoderInstances() {
+  if (!base::FeatureList::IsEnabled(media::kLimitConcurrentDecoderInstances)) {
+    return std::numeric_limits<int>::max();
+  }
+
+  // Chromebook "grunt", with an AMD Radeon R5 (Stoney Ridge) GPU, b/266003084.
+  constexpr int kAMDStoneyRidgeMaxNumOfInstances = 10;
+  auto va_display_state_handle = VADisplayStateSingleton::GetHandle();
+  if (va_display_state_handle &&
+      base::Contains(va_display_state_handle->vendor_string(), "stoney")) {
+    return kAMDStoneyRidgeMaxNumOfInstances;
+  }
+  // TODO(andrescj): we can relax this once we extract video decoding into its
+  // own process.
+  constexpr int kDefaultMaxNumOfInstances = 16;
+  return kDefaultMaxNumOfInstances;
+}
+
+// static
 scoped_refptr<VaapiWrapper> VaapiWrapper::Create(
     CodecMode mode,
     VAProfile va_profile,
@@ -1665,6 +1685,18 @@
     return nullptr;
   }
 
+  if (mode == kDecode) {
+    static const auto decoder_instances_limit =
+        VaapiWrapper::GetMaxNumDecoderInstances();
+    const bool can_create_decoder =
+        num_decoder_instances_.Increment() < decoder_instances_limit ||
+        !base::FeatureList::IsEnabled(media::kLimitConcurrentDecoderInstances);
+    if (!can_create_decoder) {
+      num_decoder_instances_.Decrement();
+      return nullptr;
+    }
+  }
+
   scoped_refptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper(
       std::move(va_display_state_handle), mode, enforce_sequence_affinity));
   if (vaapi_wrapper->VaInitialize(report_error_to_uma_cb)) {
@@ -1677,6 +1709,9 @@
 }
 
 // static
+base::AtomicRefCount VaapiWrapper::num_decoder_instances_(0);
+
+// static
 scoped_refptr<VaapiWrapper> VaapiWrapper::CreateForVideoCodec(
     CodecMode mode,
     VideoCodecProfile profile,
@@ -3144,6 +3179,9 @@
   DestroyPendingBuffers();
   DestroyContext();
   Deinitialize();
+  if (mode_ == kDecode) {
+    num_decoder_instances_.Decrement();
+  }
 }
 
 bool VaapiWrapper::Initialize(VAProfile va_profile,
diff --git a/media/gpu/vaapi/vaapi_wrapper.h b/media/gpu/vaapi/vaapi_wrapper.h
index fb5b6b10..cb0d02d 100644
--- a/media/gpu/vaapi/vaapi_wrapper.h
+++ b/media/gpu/vaapi/vaapi_wrapper.h
@@ -20,6 +20,7 @@
 #include <set>
 #include <vector>
 
+#include "base/atomic_ref_count.h"
 #include "base/files/file.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/raw_ptr.h"
@@ -586,11 +587,19 @@
   friend class VaapiVideoEncodeAcceleratorTest;
 
   FRIEND_TEST_ALL_PREFIXES(VaapiTest, LowQualityEncodingSetting);
+  FRIEND_TEST_ALL_PREFIXES(VaapiTest, TooManyDecoderInstances);
   FRIEND_TEST_ALL_PREFIXES(VaapiUtilsTest, ScopedVAImage);
   FRIEND_TEST_ALL_PREFIXES(VaapiUtilsTest, BadScopedVAImage);
   FRIEND_TEST_ALL_PREFIXES(VaapiUtilsTest, BadScopedVABufferMapping);
   FRIEND_TEST_ALL_PREFIXES(VaapiMinigbmTest, AllocateAndCompareWithMinigbm);
 
+  // There's a limit to the number of simultaneous decoder instances a given SoC
+  // can have, e.g. sometimes the process where VaapiWrapper runs can exhaust
+  // the FDs and subsequently crash (b/181264362). We run into stability
+  // problems for various reasons when that limit is reached; this class method
+  // provides that number to prevent that erroneous behaviour during Create().
+  static int GetMaxNumDecoderInstances();
+
   [[nodiscard]] bool Initialize(VAProfile va_profile,
                                 EncryptionScheme encryption_scheme);
   void Deinitialize();
@@ -658,6 +667,9 @@
   [[nodiscard]] bool MaybeAttachProtectedSession_Locked()
       EXCLUSIVE_LOCKS_REQUIRED(va_lock_);
 
+  // Tracks the number of decoder instances globally in the process.
+  static base::AtomicRefCount num_decoder_instances_;
+
   const CodecMode mode_;
   const bool enforce_sequence_affinity_;
   base::SequenceCheckerImpl sequence_checker_;
diff --git a/net/http/transport_security_state_static.pins b/net/http/transport_security_state_static.pins
index 16e19bd4..605f1176 100644
--- a/net/http/transport_security_state_static.pins
+++ b/net/http/transport_security_state_static.pins
@@ -43,9 +43,9 @@
 #   hash function for preloaded entries again (we have already done so once).
 #
 
-# Last updated: 2024-02-28 12:53 UTC
+# Last updated: 2024-03-01 12:56 UTC
 PinsListTimestamp
-1709124838
+1709297771
 
 TestSPKI
 sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/net/http/transport_security_state_static_pins.json b/net/http/transport_security_state_static_pins.json
index a7906c2..43155e2 100644
--- a/net/http/transport_security_state_static_pins.json
+++ b/net/http/transport_security_state_static_pins.json
@@ -31,7 +31,7 @@
 // the 'static_spki_hashes' and 'bad_static_spki_hashes' fields in 'pinsets'
 // refer to, and the timestamp at which the pins list was last updated.
 //
-// Last updated: 2024-02-28 12:53 UTC
+// Last updated: 2024-03-01 12:56 UTC
 //
 {
   "pinsets": [
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index c4e041c..65c7eaf 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -5377,9 +5377,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6330.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6331.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 124.0.6330.0",
+        "description": "Run with ash-chrome version 124.0.6331.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5389,8 +5389,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v124.0.6330.0",
-              "revision": "version:124.0.6330.0"
+              "location": "lacros_version_skew_tests_v124.0.6331.0",
+              "revision": "version:124.0.6331.0"
             }
           ],
           "dimensions": {
@@ -5533,9 +5533,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6330.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6331.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 124.0.6330.0",
+        "description": "Run with ash-chrome version 124.0.6331.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5545,8 +5545,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v124.0.6330.0",
-              "revision": "version:124.0.6330.0"
+              "location": "lacros_version_skew_tests_v124.0.6331.0",
+              "revision": "version:124.0.6331.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json
index 04cba4c..d0039ba 100644
--- a/testing/buildbot/chromium.coverage.json
+++ b/testing/buildbot/chromium.coverage.json
@@ -20313,9 +20313,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6330.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6331.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 124.0.6330.0",
+        "description": "Run with ash-chrome version 124.0.6331.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -20325,8 +20325,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v124.0.6330.0",
-              "revision": "version:124.0.6330.0"
+              "location": "lacros_version_skew_tests_v124.0.6331.0",
+              "revision": "version:124.0.6331.0"
             }
           ],
           "dimensions": {
@@ -20463,9 +20463,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6330.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6331.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 124.0.6330.0",
+        "description": "Run with ash-chrome version 124.0.6331.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -20475,8 +20475,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v124.0.6330.0",
-              "revision": "version:124.0.6330.0"
+              "location": "lacros_version_skew_tests_v124.0.6331.0",
+              "revision": "version:124.0.6331.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index e8fc9c2..a8d0d16 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -39981,9 +39981,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6330.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6331.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 124.0.6330.0",
+        "description": "Run with ash-chrome version 124.0.6331.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -39992,8 +39992,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v124.0.6330.0",
-              "revision": "version:124.0.6330.0"
+              "location": "lacros_version_skew_tests_v124.0.6331.0",
+              "revision": "version:124.0.6331.0"
             }
           ],
           "dimensions": {
@@ -40131,9 +40131,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6330.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6331.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 124.0.6330.0",
+        "description": "Run with ash-chrome version 124.0.6331.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -40142,8 +40142,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v124.0.6330.0",
-              "revision": "version:124.0.6330.0"
+              "location": "lacros_version_skew_tests_v124.0.6331.0",
+              "revision": "version:124.0.6331.0"
             }
           ],
           "dimensions": {
@@ -41480,9 +41480,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6330.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6331.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 124.0.6330.0",
+        "description": "Run with ash-chrome version 124.0.6331.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -41492,8 +41492,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v124.0.6330.0",
-              "revision": "version:124.0.6330.0"
+              "location": "lacros_version_skew_tests_v124.0.6331.0",
+              "revision": "version:124.0.6331.0"
             }
           ],
           "dimensions": {
@@ -41636,9 +41636,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6330.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6331.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 124.0.6330.0",
+        "description": "Run with ash-chrome version 124.0.6331.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -41648,8 +41648,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v124.0.6330.0",
-              "revision": "version:124.0.6330.0"
+              "location": "lacros_version_skew_tests_v124.0.6331.0",
+              "revision": "version:124.0.6331.0"
             }
           ],
           "dimensions": {
@@ -42961,9 +42961,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6330.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6331.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 124.0.6330.0",
+        "description": "Run with ash-chrome version 124.0.6331.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -42972,8 +42972,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v124.0.6330.0",
-              "revision": "version:124.0.6330.0"
+              "location": "lacros_version_skew_tests_v124.0.6331.0",
+              "revision": "version:124.0.6331.0"
             }
           ],
           "dimensions": {
@@ -43111,9 +43111,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6330.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6331.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 124.0.6330.0",
+        "description": "Run with ash-chrome version 124.0.6331.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -43122,8 +43122,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v124.0.6330.0",
-              "revision": "version:124.0.6330.0"
+              "location": "lacros_version_skew_tests_v124.0.6331.0",
+              "revision": "version:124.0.6331.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 5cb05e5..058d856 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -16343,12 +16343,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6330.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6331.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 124.0.6330.0",
+        "description": "Run with ash-chrome version 124.0.6331.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16358,8 +16358,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v124.0.6330.0",
-              "revision": "version:124.0.6330.0"
+              "location": "lacros_version_skew_tests_v124.0.6331.0",
+              "revision": "version:124.0.6331.0"
             }
           ],
           "dimensions": {
@@ -16519,12 +16519,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6330.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6331.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 124.0.6330.0",
+        "description": "Run with ash-chrome version 124.0.6331.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16534,8 +16534,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v124.0.6330.0",
-              "revision": "version:124.0.6330.0"
+              "location": "lacros_version_skew_tests_v124.0.6331.0",
+              "revision": "version:124.0.6331.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 8f96eb02..3e3be86 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -307,16 +307,16 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'identifier': 'Lacros version skew testing ash canary',
-    'description': 'Run with ash-chrome version 124.0.6330.0',
+    'description': 'Run with ash-chrome version 124.0.6331.0',
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6330.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v124.0.6331.0/test_ash_chrome',
     ],
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v124.0.6330.0',
-          'revision': 'version:124.0.6330.0',
+          'location': 'lacros_version_skew_tests_v124.0.6331.0',
+          'revision': 'version:124.0.6331.0',
         },
       ],
     },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index a4a126d..0ba18b97 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -12471,21 +12471,6 @@
             ]
         }
     ],
-    "OsSettingsRevampWayfindingStudy": [
-        {
-            "platforms": [
-                "chromeos"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "OsSettingsRevampWayfinding"
-                    ]
-                }
-            ]
-        }
-    ],
     "OutOfProcessPrintDriversPrint": [
         {
             "platforms": [
@@ -13498,25 +13483,6 @@
             ]
         }
     ],
-    "PreloadTopChromeWebUI": [
-        {
-            "platforms": [
-                "linux",
-                "mac",
-                "windows",
-                "chromeos",
-                "chromeos_lacros"
-            ],
-            "experiments": [
-                {
-                    "name": "Enable",
-                    "enable_features": [
-                        "PreloadTopChromeWebUI"
-                    ]
-                }
-            ]
-        }
-    ],
     "Prerender2EmbedderBlockedHosts": [
         {
             "platforms": [
diff --git a/third_party/angle b/third_party/angle
index 1ceddbf..21381f5 160000
--- a/third_party/angle
+++ b/third_party/angle
@@ -1 +1 @@
-Subproject commit 1ceddbf6977926d674c0c5a78b398f684d0052b1
+Subproject commit 21381f5e1c4dffe6ce43121e8cd55803647896ca
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index c853bfe..c4abecb 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -1375,15 +1375,6 @@
 
 BASE_FEATURE(kLinkPreview, "LinkPreview", base::FEATURE_DISABLED_BY_DEFAULT);
 
-constexpr base::FeatureParam<LinkPreviewTriggerType>::Option
-    link_preview_trigger_type_options[] = {
-        {LinkPreviewTriggerType::kAltClick, "alt_click"},
-        {LinkPreviewTriggerType::kAltHover, "alt_hover"},
-        {LinkPreviewTriggerType::kLongPress, "long_press"}};
-const base::FeatureParam<LinkPreviewTriggerType> kLinkPreviewTriggerType{
-    &kLinkPreview, "trigger_type", LinkPreviewTriggerType::kAltHover,
-    &link_preview_trigger_type_options};
-
 // A feature to control whether the loading phase should be extended beyond
 // First Meaningful Paint by a configurable buffer.
 BASE_FEATURE(kLoadingPhaseBufferTimeAfterFirstMeaningfulPaint,
@@ -2545,11 +2536,6 @@
          base::FeatureList::IsEnabled(kFetchLaterAPI);
 }
 
-bool IsLinkPreviewTriggerTypeEnabled(LinkPreviewTriggerType type) {
-  return base::FeatureList::IsEnabled(blink::features::kLinkPreview) &&
-         type == blink::features::kLinkPreviewTriggerType.Get();
-}
-
 BASE_FEATURE(kExpandCompositedCullRect,
              "ExpandCompositedCullRect",
              base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn
index 91072938..a6591c2 100644
--- a/third_party/blink/public/BUILD.gn
+++ b/third_party/blink/public/BUILD.gn
@@ -330,7 +330,6 @@
     "web/web_label_element.h",
     "web/web_language_detection_details.h",
     "web/web_lifecycle_update.h",
-    "web/web_link_preview_triggerer.h",
     "web/web_local_frame.h",
     "web/web_local_frame_client.h",
     "web/web_local_frame_observer.h",
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 537c7ef..be0bff2d 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -830,18 +830,6 @@
 // Tracking bug: go/launch/4269184
 BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kLinkPreview);
 
-enum class LinkPreviewTriggerType {
-  // Alt + left click
-  kAltClick,
-  // Alt + mousehover
-  kAltHover,
-  // Long left click down
-  kLongPress,
-};
-
-BLINK_COMMON_EXPORT extern const base::FeatureParam<LinkPreviewTriggerType>
-    kLinkPreviewTriggerType;
-
 BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kLoadingTasksUnfreezable);
 
 BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(
@@ -1632,10 +1620,6 @@
 // specific to one of them should not rely on this function.
 BLINK_COMMON_EXPORT bool IsKeepAliveURLLoaderServiceEnabled();
 
-// Returns true if Link Preview and the given trigger type is enabled.
-BLINK_COMMON_EXPORT bool IsLinkPreviewTriggerTypeEnabled(
-    LinkPreviewTriggerType type);
-
 // Kill-switch for removing Authorization header upon cross origin redirects.
 BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(
     kRemoveAuthroizationOnCrossOriginRedirect);
diff --git a/third_party/blink/public/platform/file_path_conversion.h b/third_party/blink/public/platform/file_path_conversion.h
index 0c1bca7..0693df52 100644
--- a/third_party/blink/public/platform/file_path_conversion.h
+++ b/third_party/blink/public/platform/file_path_conversion.h
@@ -7,14 +7,16 @@
 
 #include "third_party/blink/public/platform/web_common.h"
 
-#if INSIDE_BLINK
-#include "third_party/blink/renderer/platform/wtf/forward.h"  // nogncheck
-#endif
-
 namespace base {
 class FilePath;
 }
 
+#if INSIDE_BLINK
+namespace WTF {
+class String;
+}  // namespace WTF
+#endif
+
 namespace blink {
 
 class WebString;
@@ -24,8 +26,8 @@
 BLINK_PLATFORM_EXPORT WebString FilePathToWebString(const base::FilePath&);
 
 #if INSIDE_BLINK
-BLINK_PLATFORM_EXPORT base::FilePath StringToFilePath(const String& str);
-BLINK_PLATFORM_EXPORT String FilePathToString(const base::FilePath&);
+BLINK_PLATFORM_EXPORT base::FilePath StringToFilePath(const WTF::String& str);
+BLINK_PLATFORM_EXPORT WTF::String FilePathToString(const base::FilePath&);
 #endif
 
 }  // namespace blink
diff --git a/third_party/blink/public/platform/web_string.h b/third_party/blink/public/platform/web_string.h
index e281416..3a06f6b2 100644
--- a/third_party/blink/public/platform/web_string.h
+++ b/third_party/blink/public/platform/web_string.h
@@ -46,6 +46,9 @@
 #endif
 
 namespace WTF {
+#if INSIDE_BLINK
+class String;
+#endif
 class StringImpl;
 }
 
diff --git a/third_party/blink/public/web/web_document.h b/third_party/blink/public/web/web_document.h
index a52f557..b377ae4 100644
--- a/third_party/blink/public/web/web_document.h
+++ b/third_party/blink/public/web/web_document.h
@@ -185,11 +185,6 @@
   // Returns the referrer for this document.
   WebString OutgoingReferrer() const;
 
-  // (Experimental) Initiates Link Preview for `url`.
-  //
-  // It is intended to be used in WebLinkPreviewTriggerer.
-  void InitiatePreview(const WebURL& url);
-
 #if INSIDE_BLINK
   WebDocument(Document*);
   WebDocument& operator=(Document*);
diff --git a/third_party/blink/public/web/web_link_preview_triggerer.h b/third_party/blink/public/web/web_link_preview_triggerer.h
deleted file mode 100644
index 7a8e283..0000000
--- a/third_party/blink/public/web/web_link_preview_triggerer.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_LINK_PREVIEW_TRIGGERER_H_
-#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_LINK_PREVIEW_TRIGGERER_H_
-
-#include "base/functional/callback.h"
-#include "third_party/blink/public/common/input/web_mouse_event.h"
-#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/public/web/web_document.h"
-#include "third_party/blink/public/web/web_element.h"
-
-namespace blink {
-
-// Experimental
-// Observes signals of user actions and determines to trigger Link Preview.
-//
-// It will be instantiated per LocalFrame. Notified events are bare and intended
-// to be filtered by implementations.
-//
-// For concrete triggers, see the implementations.
-class WebLinkPreviewTriggerer {
- public:
-  virtual ~WebLinkPreviewTriggerer() = default;
-
-  // Events to track current modifier state.
-  //
-  // This is called for every key event and mouse leave event. For mouse leave
-  // event, kNoModifier blink::WebInputEvent::kNoModifiers is passed as an
-  // argument.
-  //
-  // The argument `modifiers` is a bit mask consisting of
-  // `blink::WebInputEvent::Modifiers`.
-  //
-  // Note that we don't still have a right way to track modifiers state (But
-  // it's enough for Link Preview because it can trigger preview only if a mouse
-  // is on anchor element.) because
-  // 1. we can't get changes of modifiers outside the window, and 2. we don't
-  // have a reliable way to `KeyobardEventManager::GetCurrentModifierState`
-  // except for macOS. For example, consider the following cases:
-  //
-  // A.  A user presses and holds Alt button, leaves the window, releases Alt,
-  //     enters to the window.
-  // A'. Same for subframe -> parent frame -> subframe.
-  // B.  A user presses and holds Alt button, leaves the window, releases Alt,
-  //     presses Alt, enters to the window.
-  //
-  // In A and A' (resp. B), the ideal `GetCurrentModifierState` should return
-  // `kNoModifiers` (resp `kAltKey`), but we don't know how to correctly get to
-  // know it. So, for safety, mouseleave event emits kNoModifiers.
-  virtual void MaybeChangedKeyEventModifier(int modifiers) {}
-  // Called when the hover element changed.
-  virtual void DidChangeHoverElement(blink::WebElement element) {}
-  // Called when an anchor element with valid link received a mouse event.
-  virtual void DidAnchorElementReceiveMouseEvent(
-      blink::WebElement anchor_element,
-      blink::WebMouseEvent mouse_event) {}
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_LINK_PREVIEW_TRIGGERER_H_
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h
index 1e475f6..58612b9 100644
--- a/third_party/blink/public/web/web_local_frame_client.h
+++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -140,7 +140,6 @@
 class WebURLRequest;
 class WebURLResponse;
 class WebView;
-class WebLinkPreviewTriggerer;
 struct FramePolicy;
 struct Impression;
 struct JavaScriptFrameworkDetectionResult;
@@ -863,11 +862,6 @@
       const WebURL& base_url) {
     return nullptr;
   }
-
-  virtual std::unique_ptr<WebLinkPreviewTriggerer> CreateLinkPreviewTriggerer();
-
-  virtual void SetLinkPreviewTriggererForTesting(
-      std::unique_ptr<WebLinkPreviewTriggerer> trigger);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/bindings/core/v8/async_iterable.cc b/third_party/blink/renderer/bindings/core/v8/async_iterable.cc
index cd064eb5..637014d7 100644
--- a/third_party/blink/renderer/bindings/core/v8/async_iterable.cc
+++ b/third_party/blink/renderer/bindings/core/v8/async_iterable.cc
@@ -196,7 +196,7 @@
 }
 
 // step 8. Let nextSteps be the following steps:
-ScriptPromise AsyncIterationSourceBase::RunNextSteps(
+ScriptPromiseTyped<IDLAny> AsyncIterationSourceBase::RunNextSteps(
     ScriptState* script_state) {
   if (is_finished_) {
     // step 8.2. If object's is finished is true, then:
@@ -204,7 +204,7 @@
     // step 8.2.2. Perform ! Call(nextPromiseCapability.[[Resolve]], undefined,
     //     << result >>).
     // step 8.2.3. Return nextPromiseCapability.[[Promise]].
-    return ScriptPromise::Cast(
+    return ToResolvedPromise<IDLAny>(
         script_state,
         ESCreateIterResultObject(script_state, true,
                                  v8::Undefined(script_state->GetIsolate())));
@@ -217,9 +217,9 @@
   // step 8.10. Return nextPromiseCapability.[[Promise]].
   DCHECK(!pending_promise_resolver_);
   pending_promise_resolver_ =
-      MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+      MakeGarbageCollected<ScriptPromiseResolverTyped<IDLAny>>(script_state);
   pending_promise_resolver_->KeepAliveWhilePending();
-  ScriptPromise promise = pending_promise_resolver_->Promise();
+  auto promise = pending_promise_resolver_->Promise();
   GetNextIterationResult();
   return promise.Then(on_fulfilled_function_, on_rejected_function_);
 }
@@ -275,7 +275,7 @@
 }
 
 // step 8. Let returnSteps be the following steps:
-ScriptPromise AsyncIterationSourceBase::RunReturnSteps(
+ScriptPromiseTyped<IDLAny> AsyncIterationSourceBase::RunReturnSteps(
     ScriptState* script_state,
     ScriptValue value) {
   if (is_finished_) {
@@ -284,7 +284,7 @@
     // step 8.2.2. Perform ! Call(returnPromiseCapability.[[Resolve]],
     //     undefined, << result >>).
     // step 8.2.3. Return returnPromiseCapability.[[Promise]].
-    return ScriptPromise::Cast(
+    return ToResolvedPromise<IDLAny>(
         script_state,
         ESCreateIterResultObject(script_state, true, value.V8Value()));
   }
@@ -296,9 +296,9 @@
   //     algorithm for interface, given object's target, object, and value.
   DCHECK(!pending_promise_resolver_);
   pending_promise_resolver_ =
-      MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+      MakeGarbageCollected<ScriptPromiseResolverTyped<IDLAny>>(script_state);
   pending_promise_resolver_->KeepAliveWhilePending();
-  ScriptPromise promise = pending_promise_resolver_->Promise();
+  auto promise = pending_promise_resolver_->Promise();
   AsyncIteratorReturn(value);
   return promise;
 }
diff --git a/third_party/blink/renderer/bindings/core/v8/async_iterable.h b/third_party/blink/renderer/bindings/core/v8/async_iterable.h
index 8ee48599..115ee53 100644
--- a/third_party/blink/renderer/bindings/core/v8/async_iterable.h
+++ b/third_party/blink/renderer/bindings/core/v8/async_iterable.h
@@ -6,13 +6,12 @@
 #define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_ASYNC_ITERABLE_H_
 
 #include "third_party/blink/renderer/bindings/core/v8/iterable.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/platform/bindings/async_iterator_base.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_deque.h"
 
 namespace blink {
 
-class ScriptPromiseResolver;
-
 namespace bindings {
 
 // Implements Web IDL 3.7.10.2. Asynchronous iterator prototype object
@@ -57,7 +56,7 @@
   }
 
   // Returns the pending promise resolver by removing it from this instance.
-  ScriptPromiseResolver* TakePendingPromiseResolver() {
+  ScriptPromiseResolverTyped<IDLAny>* TakePendingPromiseResolver() {
     DCHECK(pending_promise_resolver_);
     return pending_promise_resolver_.Release();
   }
@@ -76,12 +75,13 @@
   class RunReturnStepsCallable;
   class RunReturnFulfillStepsCallable;
 
-  ScriptPromise RunNextSteps(ScriptState* script_state);
+  ScriptPromiseTyped<IDLAny> RunNextSteps(ScriptState* script_state);
   ScriptValue RunFulfillSteps(ScriptState* script_state,
                               ScriptValue iter_result_object_or_undefined);
   ScriptValue RunRejectSteps(ScriptState* script_state, ScriptValue reason);
 
-  ScriptPromise RunReturnSteps(ScriptState* script_state, ScriptValue value);
+  ScriptPromiseTyped<IDLAny> RunReturnSteps(ScriptState* script_state,
+                                            ScriptValue value);
   ScriptValue RunReturnFulfillSteps(ScriptState* script_state,
                                     ScriptValue value);
 
@@ -93,7 +93,7 @@
   // https://webidl.spec.whatwg.org/#dfn-default-asynchronous-iterator-object
   // its 'ongoing promise', which is a Promise or null,
   // its 'is finished', which is a boolean.
-  ScriptPromise ongoing_promise_;
+  ScriptPromiseTyped<IDLAny> ongoing_promise_;
   bool is_finished_ = false;
 
   // The pending promise resolver. This is basically corresponding to
@@ -102,7 +102,11 @@
   // 'end of iteration' value returned by `MakeEndOfIteration`, otherwise
   // must be rejected. When used for 'returnStepsPromise', the fulfillment
   // value is ignored.
-  Member<ScriptPromiseResolver> pending_promise_resolver_;
+  // NOTE: `pending_promise_resolver_` should probably be typed according to
+  // the iterable result type in the relevant IDL, but everything internal to
+  // our implementation gives the resolver a v8::Value, which doesn't work
+  // well with typing according to the IDL.
+  Member<ScriptPromiseResolverTyped<IDLAny>> pending_promise_resolver_;
 
   template <typename IDLKeyType,
             typename IDLValueType,
diff --git a/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h b/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h
index d1785f95..394b38f 100644
--- a/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h
+++ b/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h
@@ -937,8 +937,8 @@
   static ScriptPromise NativeValue(v8::Isolate* isolate,
                                    v8::Local<v8::Value> value,
                                    ExceptionState& exception_state) {
-    return ScriptPromise::Cast(ScriptState::From(isolate->GetCurrentContext()),
-                               value);
+    return ScriptPromise::FromUntypedValueForBindings(
+        ScriptState::From(isolate->GetCurrentContext()), value);
   }
 };
 
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise.cc b/third_party/blink/renderer/bindings/core/v8/script_promise.cc
index dc43a87..32fcfc6 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_promise.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_promise.cc
@@ -46,9 +46,10 @@
  public:
   static ScriptPromise All(ScriptState* script_state,
                            const HeapVector<ScriptPromise>& promises) {
-    if (promises.empty())
-      return ScriptPromise::Cast(script_state,
-                                 v8::Array::New(script_state->GetIsolate()));
+    if (promises.empty()) {
+      return ScriptPromise::FromUntypedValueForBindings(
+          script_state, v8::Array::New(script_state->GetIsolate()));
+    }
     return (MakeGarbageCollected<PromiseAllHandler>(script_state, promises))
         ->resolver_.Promise();
   }
@@ -229,54 +230,56 @@
   promise_ = other.promise_;
 }
 
-ScriptPromise ScriptPromise::Then(v8::Local<v8::Function> on_fulfilled,
-                                  v8::Local<v8::Function> on_rejected) {
+ScriptPromiseTyped<IDLAny> ScriptPromise::Then(
+    v8::Local<v8::Function> on_fulfilled,
+    v8::Local<v8::Function> on_rejected) {
   if (promise_.IsEmpty())
-    return ScriptPromise();
+    return ScriptPromiseTyped<IDLAny>();
 
   v8::Local<v8::Promise> promise = promise_.V8Value().As<v8::Promise>();
 
   if (on_fulfilled.IsEmpty() && on_rejected.IsEmpty())
-    return *this;
+    return ScriptPromiseTyped<IDLAny>(script_state_, V8Value());
 
   v8::Local<v8::Promise> result_promise;
   if (on_rejected.IsEmpty()) {
     if (!promise->Then(script_state_->GetContext(), on_fulfilled)
              .ToLocal(&result_promise)) {
-      return ScriptPromise();
+      return ScriptPromiseTyped<IDLAny>();
     }
-    return ScriptPromise(script_state_, result_promise);
+    return ScriptPromiseTyped<IDLAny>(script_state_, result_promise);
   }
 
   if (on_fulfilled.IsEmpty()) {
     if (!promise->Catch(script_state_->GetContext(), on_rejected)
              .ToLocal(&result_promise)) {
-      return ScriptPromise();
+      return ScriptPromiseTyped<IDLAny>();
     }
-    return ScriptPromise(script_state_, result_promise);
+    return ScriptPromiseTyped<IDLAny>(script_state_, result_promise);
   }
 
   if (!promise->Then(script_state_->GetContext(), on_fulfilled, on_rejected)
            .ToLocal(&result_promise)) {
-    return ScriptPromise();
+    return ScriptPromiseTyped<IDLAny>();
   }
-  return ScriptPromise(script_state_, result_promise);
+  return ScriptPromiseTyped<IDLAny>(script_state_, result_promise);
 }
 
-ScriptPromise ScriptPromise::Then(ScriptFunction* on_fulfilled,
-                                  ScriptFunction* on_rejected) {
+ScriptPromiseTyped<IDLAny> ScriptPromise::Then(ScriptFunction* on_fulfilled,
+                                               ScriptFunction* on_rejected) {
   const v8::Local<v8::Function> empty;
   return Then(on_fulfilled ? on_fulfilled->V8Function() : empty,
               on_rejected ? on_rejected->V8Function() : empty);
 }
 
 ScriptPromise ScriptPromise::CastUndefined(ScriptState* script_state) {
-  return ScriptPromise::Cast(script_state,
-                             v8::Undefined(script_state->GetIsolate()));
+  return FromUntypedValueForBindings(script_state,
+                                     v8::Undefined(script_state->GetIsolate()));
 }
 
-ScriptPromise ScriptPromise::Cast(ScriptState* script_state,
-                                  v8::Local<v8::Value> value) {
+ScriptPromise ScriptPromise::FromUntypedValueForBindings(
+    ScriptState* script_state,
+    v8::Local<v8::Value> value) {
   if (value.IsEmpty())
     return ScriptPromise();
   if (value->IsPromise()) {
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise.h b/third_party/blink/renderer/bindings/core/v8/script_promise.h
index fe653e3..196bba5 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_promise.h
+++ b/third_party/blink/renderer/bindings/core/v8/script_promise.h
@@ -48,6 +48,9 @@
 class ExceptionState;
 class ScriptFunction;
 
+template <typename IDLResolvedType>
+class ScriptPromiseTyped;
+
 // ScriptPromise is the class for representing Promise values in C++ world.
 // ScriptPromise holds a Promise.
 // So holding a ScriptPromise as a member variable in DOM object causes
@@ -71,10 +74,10 @@
 
   ~ScriptPromise() = default;
 
-  ScriptPromise Then(v8::Local<v8::Function> on_fulfilled,
-                     v8::Local<v8::Function> on_rejected = {});
-  ScriptPromise Then(ScriptFunction* on_fulfilled,
-                     ScriptFunction* on_rejected = nullptr);
+  ScriptPromiseTyped<IDLAny> Then(v8::Local<v8::Function> on_fulfilled,
+                                  v8::Local<v8::Function> on_rejected = {});
+  ScriptPromiseTyped<IDLAny> Then(ScriptFunction* on_fulfilled,
+                                  ScriptFunction* on_rejected = nullptr);
 
   bool IsObject() const { return promise_.IsObject(); }
 
@@ -111,10 +114,14 @@
   }
 
   // Constructs and returns a ScriptPromise from |value|.
-  // if |value| is not a Promise object, returns a Promise object
-  // resolved with |value|.
-  // Returns |value| itself if it is a Promise.
-  static ScriptPromise Cast(ScriptState*, v8::Local<v8::Value> /*value*/);
+  // if `value` is not a Promise object, returns a Promise object
+  // resolved with `value`.
+  // Returns `value` itself if it is a Promise.
+  // This is intended only for cases where we are receiving an arbitrary
+  // `value` of unknown type from script. If constructing a ScriptPromise of
+  // known type, use ToResolvedPromise<>.
+  static ScriptPromise FromUntypedValueForBindings(ScriptState*,
+                                                   v8::Local<v8::Value>);
 
   // Constructs and returns a ScriptPromise resolved with undefined.
   static ScriptPromise CastUndefined(ScriptState*);
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise_test.cc b/third_party/blink/renderer/bindings/core/v8/script_promise_test.cc
index ee635287..bd7732a 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_promise_test.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_promise_test.cc
@@ -445,8 +445,8 @@
   test::TaskEnvironment task_environment;
   V8TestingScope scope;
   ScriptPromise promise = Resolver(scope.GetScriptState()).Promise();
-  ScriptPromise new_promise =
-      ScriptPromise::Cast(scope.GetScriptState(), promise.V8Value());
+  ScriptPromise new_promise = ScriptPromise::FromUntypedValueForBindings(
+      scope.GetScriptState(), promise.V8Value());
 
   ASSERT_FALSE(promise.IsEmpty());
   EXPECT_EQ(promise.V8Value(), new_promise.V8Value());
diff --git a/third_party/blink/renderer/build/scripts/scripts.gni b/third_party/blink/renderer/build/scripts/scripts.gni
index db7a810..51a74de 100644
--- a/third_party/blink/renderer/build/scripts/scripts.gni
+++ b/third_party/blink/renderer/build/scripts/scripts.gni
@@ -6,7 +6,9 @@
 import("//build/toolchain/toolchain.gni")
 import("//third_party/blink/renderer/config.gni")
 
-if (host_os == "mac") {
+if (is_ios) {
+  import("//build/config/ios/ios_sdk.gni")
+} else if (host_os == "mac") {
   import("//build/config/mac/mac_sdk.gni")
 }
 
@@ -73,6 +75,8 @@
 # on Posix we want to run the system one on the path.
 if (host_os == "win") {
   gperf_exe = rebase_path("//third_party/gperf/bin/gperf.exe", root_build_dir)
+} else if (is_ios) {
+  gperf_exe = ios_bin_path + "gperf"
 } else if (host_os == "mac") {
   # TODO(thakis): This should probably run in the host toolchain and check
   # is_mac instead of checking host_os.
diff --git a/third_party/blink/renderer/core/animation/animation_input_helpers.h b/third_party/blink/renderer/core/animation/animation_input_helpers.h
index 9e2b85b..daa2beeb5 100644
--- a/third_party/blink/renderer/core/animation/animation_input_helpers.h
+++ b/third_party/blink/renderer/core/animation/animation_input_helpers.h
@@ -8,7 +8,10 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/css/css_property_names.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -23,17 +26,19 @@
   STATIC_ONLY(AnimationInputHelpers);
 
  public:
-  static CSSPropertyID KeyframeAttributeToCSSProperty(const String&,
+  static CSSPropertyID KeyframeAttributeToCSSProperty(const WTF::String&,
                                                       const Document&);
-  static CSSPropertyID KeyframeAttributeToPresentationAttribute(const String&,
-                                                                const Element*);
-  static const QualifiedName* KeyframeAttributeToSVGAttribute(const String&,
-                                                              Element*);
-  static scoped_refptr<TimingFunction> ParseTimingFunction(const String&,
+  static CSSPropertyID KeyframeAttributeToPresentationAttribute(
+      const WTF::String&,
+      const Element*);
+  static const QualifiedName* KeyframeAttributeToSVGAttribute(
+      const WTF::String&,
+      Element*);
+  static scoped_refptr<TimingFunction> ParseTimingFunction(const WTF::String&,
                                                            Document*,
                                                            ExceptionState&);
 
-  static String PropertyHandleToKeyframeAttribute(PropertyHandle);
+  static WTF::String PropertyHandleToKeyframeAttribute(PropertyHandle);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/clipboard/data_transfer_item_list.h b/third_party/blink/renderer/core/clipboard/data_transfer_item_list.h
index e3ee99b8..56e2065 100644
--- a/third_party/blink/renderer/core/clipboard/data_transfer_item_list.h
+++ b/third_party/blink/renderer/core/clipboard/data_transfer_item_list.h
@@ -35,7 +35,10 @@
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/heap/member.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -56,8 +59,8 @@
   DataTransferItem* item(uint32_t index);
   void deleteItem(uint32_t index, ExceptionState&);
   void clear();
-  DataTransferItem* add(const String& data,
-                        const String& type,
+  DataTransferItem* add(const WTF::String& data,
+                        const WTF::String& type,
                         ExceptionState&);
   DataTransferItem* add(File*);
 
diff --git a/third_party/blink/renderer/core/css/css_markup.h b/third_party/blink/renderer/core/css/css_markup.h
index 2e8da37..f89d317 100644
--- a/third_party/blink/renderer/core/css/css_markup.h
+++ b/third_party/blink/renderer/core/css/css_markup.h
@@ -25,7 +25,11 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_MARKUP_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_MARKUP_H_
 
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+namespace WTF {
+class AtomicString;
+class String;
+class StringBuilder;
+}  // namespace WTF
 
 // Helper functions for converting from CSSValues to text.
 
@@ -33,13 +37,13 @@
 
 // Common serializing methods. See:
 // https://drafts.csswg.org/cssom/#common-serializing-idioms
-void SerializeIdentifier(const String& identifier,
-                         StringBuilder& append_to,
+void SerializeIdentifier(const WTF::String& identifier,
+                         WTF::StringBuilder& append_to,
                          bool skip_start_checks = false);
-void SerializeString(const String&, StringBuilder& append_to);
-String SerializeString(const String&);
-String SerializeURI(const String&);
-String SerializeFontFamily(const AtomicString&);
+void SerializeString(const WTF::String&, WTF::StringBuilder& append_to);
+WTF::String SerializeString(const WTF::String&);
+WTF::String SerializeURI(const WTF::String&);
+WTF::String SerializeFontFamily(const WTF::AtomicString&);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/core/css/css_math_operator.h b/third_party/blink/renderer/core/css/css_math_operator.h
index 575976e..6a989f0 100644
--- a/third_party/blink/renderer/core/css/css_math_operator.h
+++ b/third_party/blink/renderer/core/css/css_math_operator.h
@@ -5,7 +5,9 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_MATH_OPERATOR_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_MATH_OPERATOR_H_
 
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -34,7 +36,7 @@
 };
 
 CSSMathOperator ParseCSSArithmeticOperator(const CSSParserToken& token);
-String ToString(CSSMathOperator);
+WTF::String ToString(CSSMathOperator);
 
 bool IsComparison(CSSMathOperator);
 
diff --git a/third_party/blink/renderer/core/css/css_selector.h b/third_party/blink/renderer/core/css/css_selector.h
index 3b9cdfb3..7015916 100644
--- a/third_party/blink/renderer/core/css/css_selector.h
+++ b/third_party/blink/renderer/core/css/css_selector.h
@@ -37,6 +37,10 @@
 #include "third_party/blink/renderer/platform/heap/visitor.h"
 #include "third_party/blink/renderer/platform/wtf/gc_plugin.h"
 
+namespace WTF {
+class StringBuilder;
+}  // namespace WTF
+
 namespace blink {
 
 class CSSParserContext;
@@ -649,8 +653,8 @@
 
   unsigned SpecificityForOneSelector() const;
   unsigned SpecificityForPage() const;
-  bool SerializeSimpleSelector(StringBuilder& builder) const;
-  const CSSSelector* SerializeCompound(StringBuilder&) const;
+  bool SerializeSimpleSelector(WTF::StringBuilder& builder) const;
+  const CSSSelector* SerializeCompound(WTF::StringBuilder&) const;
 
   struct RareData : public GarbageCollected<RareData> {
     explicit RareData(const AtomicString& value);
diff --git a/third_party/blink/renderer/core/css/css_style_sheet.cc b/third_party/blink/renderer/core/css/css_style_sheet.cc
index 30640f9..e032eb70 100644
--- a/third_party/blink/renderer/core/css/css_style_sheet.cc
+++ b/third_party/blink/renderer/core/css/css_style_sheet.cc
@@ -499,22 +499,22 @@
   return addRule(selector, style, length(), exception_state);
 }
 
-ScriptPromise CSSStyleSheet::replace(ScriptState* script_state,
-                                     const String& text,
-                                     ExceptionState& exception_state) {
+ScriptPromiseTyped<CSSStyleSheet> CSSStyleSheet::replace(
+    ScriptState* script_state,
+    const String& text,
+    ExceptionState& exception_state) {
   if (!IsConstructed()) {
     exception_state.ThrowDOMException(
         DOMExceptionCode::kNotAllowedError,
         "Can't call replace on non-constructed CSSStyleSheets.");
-    return ScriptPromise();
+    return ScriptPromiseTyped<CSSStyleSheet>();
   }
   SetText(text, CSSImportRules::kIgnoreWithWarning);
   probe::DidReplaceStyleSheetText(OwnerDocument(), this, text);
   // We currently parse synchronously, and since @import support was removed,
   // nothing else happens asynchronously. This API is left as-is, so that future
   // async parsing can still be supported here.
-  return ScriptPromise::Cast(
-      script_state, ToV8Traits<CSSStyleSheet>::ToV8(script_state, this));
+  return ToResolvedPromise<CSSStyleSheet>(script_state, this);
 }
 
 void CSSStyleSheet::replaceSync(const String& text,
diff --git a/third_party/blink/renderer/core/css/css_style_sheet.h b/third_party/blink/renderer/core/css/css_style_sheet.h
index bee1e82..2ec51e59 100644
--- a/third_party/blink/renderer/core/css/css_style_sheet.h
+++ b/third_party/blink/renderer/core/css/css_style_sheet.h
@@ -23,6 +23,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_STYLE_SHEET_H_
 
 #include "base/gtest_prod_util.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/css/css_rule.h"
 #include "third_party/blink/renderer/core/css/media_query_evaluator.h"
@@ -50,7 +51,6 @@
 class Element;
 class ExceptionState;
 class MediaQuerySet;
-class ScriptPromise;
 class ScriptState;
 class StyleSheetContents;
 class TreeScope;
@@ -119,9 +119,9 @@
     deleteRule(index, exception_state);
   }
 
-  ScriptPromise replace(ScriptState* script_state,
-                        const String& text,
-                        ExceptionState&);
+  ScriptPromiseTyped<CSSStyleSheet> replace(ScriptState* script_state,
+                                            const String& text,
+                                            ExceptionState&);
   void replaceSync(const String& text, ExceptionState&);
 
   // For CSSRuleList.
diff --git a/third_party/blink/renderer/core/css/css_value.h b/third_party/blink/renderer/core/css/css_value.h
index e371e90..ea1ad3fd 100644
--- a/third_party/blink/renderer/core/css/css_value.h
+++ b/third_party/blink/renderer/core/css/css_value.h
@@ -27,6 +27,12 @@
 #include "third_party/blink/renderer/platform/heap/custom_spaces.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
+using WTF::String;
+
 namespace blink {
 
 class Document;
diff --git a/third_party/blink/renderer/core/css/cssom/css_math_clamp.h b/third_party/blink/renderer/core/css/cssom/css_math_clamp.h
index 0ca6084..acf68ab 100644
--- a/third_party/blink/renderer/core/css/cssom/css_math_clamp.h
+++ b/third_party/blink/renderer/core/css/cssom/css_math_clamp.h
@@ -11,6 +11,10 @@
 #include "third_party/blink/renderer/core/css/cssom/css_math_value.h"
 #include "third_party/blink/renderer/core/css/cssom/css_numeric_array.h"
 
+namespace WTF {
+class StringBuilder;
+}  // namespace WTF
+
 namespace blink {
 
 // Represents the central calculation of three CSSNumericValues.
@@ -87,7 +91,7 @@
   CSSMathExpressionNode* ToCalcExpressionNode() const final;
 
  private:
-  void BuildCSSText(Nested, ParenLess, StringBuilder&) const final;
+  void BuildCSSText(Nested, ParenLess, WTF::StringBuilder&) const final;
 
   std::optional<CSSNumericSumValue> SumValue() const final;
 
diff --git a/third_party/blink/renderer/core/css/cssom/css_math_negate.h b/third_party/blink/renderer/core/css/cssom/css_math_negate.h
index 61a0eaf..b0ca8f97 100644
--- a/third_party/blink/renderer/core/css/cssom/css_math_negate.h
+++ b/third_party/blink/renderer/core/css/cssom/css_math_negate.h
@@ -8,6 +8,10 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/css/cssom/css_math_value.h"
 
+namespace WTF {
+class StringBuilder;
+}  // namespace WTF
+
 namespace blink {
 
 // Represents the negation of a CSSNumericValue.
@@ -62,7 +66,7 @@
   CSSNumericValue* Negate() final { return value_.Get(); }
   std::optional<CSSNumericSumValue> SumValue() const final;
 
-  void BuildCSSText(Nested, ParenLess, StringBuilder&) const final;
+  void BuildCSSText(Nested, ParenLess, WTF::StringBuilder&) const final;
 
   Member<CSSNumericValue> value_;
 };
diff --git a/third_party/blink/renderer/core/css/cssom/css_numeric_value.h b/third_party/blink/renderer/core/css/cssom/css_numeric_value.h
index 95a3ae4..2b1c6171 100644
--- a/third_party/blink/renderer/core/css/cssom/css_numeric_value.h
+++ b/third_party/blink/renderer/core/css/cssom/css_numeric_value.h
@@ -16,6 +16,10 @@
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
+namespace WTF {
+class StringBuilder;
+}  // namespace WTF
+
 namespace blink {
 
 class CSSMathExpressionNode;
@@ -84,7 +88,7 @@
 
   enum class Nested : bool { kYes, kNo };
   enum class ParenLess : bool { kYes, kNo };
-  virtual void BuildCSSText(Nested, ParenLess, StringBuilder&) const = 0;
+  virtual void BuildCSSText(Nested, ParenLess, WTF::StringBuilder&) const = 0;
 
  protected:
   static bool IsValidUnit(CSSPrimitiveValue::UnitType);
diff --git a/third_party/blink/renderer/core/css/cssom/css_unit_value.h b/third_party/blink/renderer/core/css/cssom/css_unit_value.h
index 1d3decd1..57f756d 100644
--- a/third_party/blink/renderer/core/css/cssom/css_unit_value.h
+++ b/third_party/blink/renderer/core/css/cssom/css_unit_value.h
@@ -12,6 +12,10 @@
 #include "third_party/blink/renderer/core/css/cssom/css_numeric_value.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 
+namespace WTF {
+class StringBuilder;
+}  // namespace WTF
+
 namespace blink {
 
 // Represents numeric values that can be expressed as a single number plus a
@@ -63,7 +67,7 @@
   double ConvertFixedLength(CSSPrimitiveValue::UnitType) const;
   double ConvertAngle(CSSPrimitiveValue::UnitType) const;
 
-  void BuildCSSText(Nested, ParenLess, StringBuilder&) const final;
+  void BuildCSSText(Nested, ParenLess, WTF::StringBuilder&) const final;
 
   // From CSSNumericValue
   CSSNumericValue* Negate() final;
diff --git a/third_party/blink/renderer/core/css/dom_window_css.h b/third_party/blink/renderer/core/css/dom_window_css.h
index 570a706..5420851 100644
--- a/third_party/blink/renderer/core/css/dom_window_css.h
+++ b/third_party/blink/renderer/core/css/dom_window_css.h
@@ -32,7 +32,10 @@
 
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -43,10 +46,11 @@
 
  public:
   static bool supports(const ExecutionContext*,
-                       const String& property,
-                       const String& value);
-  static bool supports(const ExecutionContext*, const String& condition_text);
-  static String escape(const String& ident);
+                       const WTF::String& property,
+                       const WTF::String& value);
+  static bool supports(const ExecutionContext*,
+                       const WTF::String& condition_text);
+  static WTF::String escape(const WTF::String& ident);
 
  private:
   DOMWindowCSS() = default;
diff --git a/third_party/blink/renderer/core/css/media_query_exp.h b/third_party/blink/renderer/core/css/media_query_exp.h
index 8fa1027..861802a 100644
--- a/third_party/blink/renderer/core/css/media_query_exp.h
+++ b/third_party/blink/renderer/core/css/media_query_exp.h
@@ -40,6 +40,10 @@
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 
+namespace WTF {
+class StringBuilder;
+}  // namespace WTF
+
 namespace blink {
 
 class CSSParserContext;
@@ -328,7 +332,7 @@
   bool HasUnknown() const { return CollectFeatureFlags() & kFeatureUnknown; }
 
   virtual Type GetType() const = 0;
-  virtual void SerializeTo(StringBuilder&) const = 0;
+  virtual void SerializeTo(WTF::StringBuilder&) const = 0;
   virtual void CollectExpressions(HeapVector<MediaQueryExp>&) const = 0;
   virtual FeatureFlags CollectFeatureFlags() const = 0;
 
@@ -360,7 +364,7 @@
   bool IsBlockSizeDependent() const;
 
   Type GetType() const override { return Type::kFeature; }
-  void SerializeTo(StringBuilder&) const override;
+  void SerializeTo(WTF::StringBuilder&) const override;
   void CollectExpressions(HeapVector<MediaQueryExp>&) const override;
   FeatureFlags CollectFeatureFlags() const override;
 
@@ -390,7 +394,7 @@
       : MediaQueryUnaryExpNode(operand) {}
 
   Type GetType() const override { return Type::kNested; }
-  void SerializeTo(StringBuilder&) const override;
+  void SerializeTo(WTF::StringBuilder&) const override;
 };
 
 class CORE_EXPORT MediaQueryFunctionExpNode : public MediaQueryUnaryExpNode {
@@ -400,7 +404,7 @@
       : MediaQueryUnaryExpNode(operand), name_(name) {}
 
   Type GetType() const override { return Type::kFunction; }
-  void SerializeTo(StringBuilder&) const override;
+  void SerializeTo(WTF::StringBuilder&) const override;
   FeatureFlags CollectFeatureFlags() const override;
 
  private:
@@ -413,7 +417,7 @@
       : MediaQueryUnaryExpNode(operand) {}
 
   Type GetType() const override { return Type::kNot; }
-  void SerializeTo(StringBuilder&) const override;
+  void SerializeTo(WTF::StringBuilder&) const override;
 };
 
 class CORE_EXPORT MediaQueryCompoundExpNode : public MediaQueryExpNode {
@@ -443,7 +447,7 @@
       : MediaQueryCompoundExpNode(left, right) {}
 
   Type GetType() const override { return Type::kAnd; }
-  void SerializeTo(StringBuilder&) const override;
+  void SerializeTo(WTF::StringBuilder&) const override;
 };
 
 class CORE_EXPORT MediaQueryOrExpNode : public MediaQueryCompoundExpNode {
@@ -453,7 +457,7 @@
       : MediaQueryCompoundExpNode(left, right) {}
 
   Type GetType() const override { return Type::kOr; }
-  void SerializeTo(StringBuilder&) const override;
+  void SerializeTo(WTF::StringBuilder&) const override;
 };
 
 class CORE_EXPORT MediaQueryUnknownExpNode : public MediaQueryExpNode {
@@ -461,7 +465,7 @@
   explicit MediaQueryUnknownExpNode(String string) : string_(string) {}
 
   Type GetType() const override { return Type::kUnknown; }
-  void SerializeTo(StringBuilder&) const override;
+  void SerializeTo(WTF::StringBuilder&) const override;
   void CollectExpressions(HeapVector<MediaQueryExp>&) const override;
   FeatureFlags CollectFeatureFlags() const override;
 
diff --git a/third_party/blink/renderer/core/css/style_property_serializer.h b/third_party/blink/renderer/core/css/style_property_serializer.h
index b39eb08..78f464d 100644
--- a/third_party/blink/renderer/core/css/style_property_serializer.h
+++ b/third_party/blink/renderer/core/css/style_property_serializer.h
@@ -29,6 +29,10 @@
 #include "third_party/blink/renderer/core/css/css_property_value_set.h"
 #include "third_party/blink/renderer/core/css/css_value_list.h"
 
+namespace WTF {
+class StringBuilder;
+}  // namespace WTF
+
 namespace blink {
 
 class CSSPropertyName;
@@ -78,7 +82,7 @@
   String FontSynthesisValue() const;
   String FontVariantValue() const;
   bool AppendFontLonghandValueIfNotNormal(const CSSProperty&,
-                                          StringBuilder& result) const;
+                                          WTF::StringBuilder& result) const;
   String OffsetValue() const;
   String TextDecorationValue() const;
   String TextSpacingValue() const;
@@ -94,7 +98,7 @@
   bool IsPropertyShorthandAvailable(const StylePropertyShorthand&) const;
   bool ShorthandHasOnlyInitialOrInheritedValue(
       const StylePropertyShorthand&) const;
-  void AppendBackgroundPropertyAsText(StringBuilder& result,
+  void AppendBackgroundPropertyAsText(WTF::StringBuilder& result,
                                       unsigned& num_decls) const;
 
   // This function does checks common to all shorthands, and returns:
diff --git a/third_party/blink/renderer/core/css/style_sheet.h b/third_party/blink/renderer/core/css/style_sheet.h
index a8374bc..333cf9c 100644
--- a/third_party/blink/renderer/core/css/style_sheet.h
+++ b/third_party/blink/renderer/core/css/style_sheet.h
@@ -23,7 +23,10 @@
 
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -44,10 +47,10 @@
   virtual void setDisabled(bool) = 0;
   virtual Node* ownerNode() const = 0;
   virtual StyleSheet* parentStyleSheet() const { return nullptr; }
-  virtual String href() const = 0;
-  virtual String title() const = 0;
+  virtual WTF::String href() const = 0;
+  virtual WTF::String title() const = 0;
   virtual MediaList* media() { return nullptr; }
-  virtual String type() const = 0;
+  virtual WTF::String type() const = 0;
 
   virtual CSSRule* ownerRule() const { return nullptr; }
   virtual void ClearOwnerNode() = 0;
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index f07d78a..fc65223 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -75,7 +75,6 @@
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/public/platform/web_content_settings_client.h"
 #include "third_party/blink/public/platform/web_theme_engine.h"
-#include "third_party/blink/public/web/web_link_preview_triggerer.h"
 #include "third_party/blink/public/web/web_print_page_description.h"
 #include "third_party/blink/renderer/bindings/core/v8/frozen_array.h"
 #include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h"
@@ -3202,7 +3201,6 @@
 
   GetStyleEngine().DidDetach();
 
-  GetFrame()->DocumentDetached();
   GetFrame()->GetEventHandlerRegistry().DocumentDetached(*this);
 
   // Signal destruction to mutation observers.
@@ -5324,26 +5322,8 @@
   GetStyleEngine().MarkViewportUnitDirty(ViewportUnitFlag::kDynamic);
 }
 
-void EmitDidChangeHoverElement(Document& document, Element* new_hover_element) {
-  LocalFrame* local_frame = document.GetFrame();
-  if (!local_frame) {
-    return;
-  }
-
-  WebLinkPreviewTriggerer* triggerer =
-      local_frame->GetOrCreateLinkPreviewTriggerer();
-  if (!triggerer) {
-    return;
-  }
-
-  WebElement web_element = WebElement(DynamicTo<Element>(new_hover_element));
-  triggerer->DidChangeHoverElement(web_element);
-}
-
 void Document::SetHoverElement(Element* new_hover_element) {
   HTMLElement::HoveredElementChanged(hover_element_, new_hover_element);
-  EmitDidChangeHoverElement(*this, new_hover_element);
-
   hover_element_ = new_hover_element;
 }
 
diff --git a/third_party/blink/renderer/core/dom/document_lifecycle.h b/third_party/blink/renderer/core/dom/document_lifecycle.h
index 5400fc3..05203532 100644
--- a/third_party/blink/renderer/core/dom/document_lifecycle.h
+++ b/third_party/blink/renderer/core/dom/document_lifecycle.h
@@ -38,7 +38,9 @@
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 
 #if DCHECK_IS_ON()
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+namespace WTF {
+class String;
+}  // namespace WTF
 #endif
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index a51b5c3..7af5465 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -5830,7 +5830,7 @@
   }
 
   DCHECK(GetShadowRoot());
-  if (RuntimeEnabledFeatures::DialogNewFocusBehaviorEnabled()) {
+  if (RuntimeEnabledFeatures::NewGetFocusableAreaBehaviorEnabled()) {
     return GetFocusDelegate(in_descendant_traversal);
   } else {
     return FocusController::FindFocusableElementInShadowHost(*this);
diff --git a/third_party/blink/renderer/core/dom/node_rare_data.h b/third_party/blink/renderer/core/dom/node_rare_data.h
index 8f825776..5a6d8a62 100644
--- a/third_party/blink/renderer/core/dom/node_rare_data.h
+++ b/third_party/blink/renderer/core/dom/node_rare_data.h
@@ -132,7 +132,6 @@
     return static_cast<ClassType>(bit_field_.get_concurrently<ClassTypeData>());
   }
 
- protected:
   subtle::UncompressedMember<const ComputedStyle> computed_style_;
   Member<LayoutObject> layout_object_;
   BitField bit_field_;
diff --git a/third_party/blink/renderer/core/dom/shadow_including_tree_order_traversal.h b/third_party/blink/renderer/core/dom/shadow_including_tree_order_traversal.h
index 4b2eb262..9079ee7 100644
--- a/third_party/blink/renderer/core/dom/shadow_including_tree_order_traversal.h
+++ b/third_party/blink/renderer/core/dom/shadow_including_tree_order_traversal.h
@@ -30,6 +30,8 @@
       const Node&);
   static TraversalDescendantRange<ShadowIncludingTreeOrderTraversal>
   DescendantsOf(const Node&);
+  static TraversalInclusiveDescendantRange<ShadowIncludingTreeOrderTraversal>
+  InclusiveDescendantsOf(const Node&);
 
  private:
   static Node* TraverseParent(const Node& current);
@@ -70,6 +72,12 @@
   return TraversalDescendantRange<ShadowIncludingTreeOrderTraversal>(&root);
 }
 
+inline TraversalInclusiveDescendantRange<ShadowIncludingTreeOrderTraversal>
+ShadowIncludingTreeOrderTraversal::InclusiveDescendantsOf(const Node& root) {
+  return TraversalInclusiveDescendantRange<ShadowIncludingTreeOrderTraversal>(
+      &root);
+}
+
 inline Node* ShadowIncludingTreeOrderTraversal::TraverseParent(
     const Node& current) {
   return current.ParentOrShadowHostNode();
diff --git a/third_party/blink/renderer/core/dom/shadow_including_tree_order_traversal_test.cc b/third_party/blink/renderer/core/dom/shadow_including_tree_order_traversal_test.cc
index bcec831..318c43f 100644
--- a/third_party/blink/renderer/core/dom/shadow_including_tree_order_traversal_test.cc
+++ b/third_party/blink/renderer/core/dom/shadow_including_tree_order_traversal_test.cc
@@ -148,12 +148,18 @@
     </div>
     <div id="a2"></div>
   )HTML");
+  GetDocument().body()->SetIdAttribute(AtomicString("body"));
 
   EXPECT_THAT(GatherElementIdsFromTraversalRange(
                   ShadowIncludingTreeOrderTraversal::DescendantsOf(
                       *GetDocument().body())),
               ElementsAre("a0", "a00", "a01", "a1", "shadow", "b0", "b00",
                           "a10", "a2"));
+  EXPECT_THAT(GatherElementIdsFromTraversalRange(
+                  ShadowIncludingTreeOrderTraversal::InclusiveDescendantsOf(
+                      *GetDocument().body())),
+              ElementsAre("body", "a0", "a00", "a01", "a1", "shadow", "b0",
+                          "b00", "a10", "a2"));
 }
 
 TEST_F(ShadowIncludingTreeOrderTraversalTest, ChildrenOf) {
diff --git a/third_party/blink/renderer/core/dom/testing/internals_storage_access.h b/third_party/blink/renderer/core/dom/testing/internals_storage_access.h
index b376a62..da2aa165 100644
--- a/third_party/blink/renderer/core/dom/testing/internals_storage_access.h
+++ b/third_party/blink/renderer/core/dom/testing/internals_storage_access.h
@@ -6,7 +6,10 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TESTING_INTERNALS_STORAGE_ACCESS_H_
 
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -21,8 +24,8 @@
  public:
   static ScriptPromise setStorageAccess(ScriptState*,
                                         Internals&,
-                                        const String& origin,
-                                        const String& embedding_origin,
+                                        const WTF::String& origin,
+                                        const WTF::String& embedding_origin,
                                         const bool blocked,
                                         ExceptionState&);
 };
diff --git a/third_party/blink/renderer/core/dom/text_diff_range.h b/third_party/blink/renderer/core/dom/text_diff_range.h
index e13527f8..1e6376f 100644
--- a/third_party/blink/renderer/core/dom/text_diff_range.h
+++ b/third_party/blink/renderer/core/dom/text_diff_range.h
@@ -7,7 +7,11 @@
 
 #include "base/dcheck_is_on.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -34,7 +38,8 @@
   inline wtf_size_t NewEndOffset() const { return offset + new_size; }
 
   // Check if text outside of the diff are not changed.
-  void CheckValid(const String& old_text, const String& new_text) const;
+  void CheckValid(const WTF::String& old_text,
+                  const WTF::String& new_text) const;
 
   wtf_size_t offset = 0;
   // Indicates a deletion of `old_size` characters at `offset`.
@@ -44,8 +49,8 @@
 };
 
 #if !EXPENSIVE_DCHECKS_ARE_ON()
-inline void TextDiffRange::CheckValid(const String& old_text,
-                                      const String& new_text) const {}
+inline void TextDiffRange::CheckValid(const WTF::String& old_text,
+                                      const WTF::String& new_text) const {}
 #endif  // EXPENSIVE_DCHECKS_ARE_ON()
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/editing/commands/insert_commands.h b/third_party/blink/renderer/core/editing/commands/insert_commands.h
index c1aab56a..d76b839 100644
--- a/third_party/blink/renderer/core/editing/commands/insert_commands.h
+++ b/third_party/blink/renderer/core/editing/commands/insert_commands.h
@@ -33,7 +33,10 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_INSERT_COMMANDS_H_
 
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -53,51 +56,51 @@
   static bool ExecuteInsertBacktab(LocalFrame&,
                                    Event*,
                                    EditorCommandSource,
-                                   const String&);
+                                   const WTF::String&);
   static bool ExecuteInsertHorizontalRule(LocalFrame&,
                                           Event*,
                                           EditorCommandSource,
-                                          const String&);
+                                          const WTF::String&);
   static bool ExecuteInsertHTML(LocalFrame&,
                                 Event*,
                                 EditorCommandSource,
-                                const String&);
+                                const WTF::String&);
   static bool ExecuteInsertImage(LocalFrame&,
                                  Event*,
                                  EditorCommandSource,
-                                 const String&);
+                                 const WTF::String&);
   static bool ExecuteInsertLineBreak(LocalFrame&,
                                      Event*,
                                      EditorCommandSource,
-                                     const String&);
+                                     const WTF::String&);
   static bool ExecuteInsertNewline(LocalFrame&,
                                    Event*,
                                    EditorCommandSource,
-                                   const String&);
+                                   const WTF::String&);
   static bool ExecuteInsertNewlineInQuotedContent(LocalFrame&,
                                                   Event*,
                                                   EditorCommandSource,
-                                                  const String&);
+                                                  const WTF::String&);
   static bool ExecuteInsertOrderedList(LocalFrame&,
                                        Event*,
                                        EditorCommandSource,
-                                       const String&);
+                                       const WTF::String&);
   static bool ExecuteInsertParagraph(LocalFrame&,
                                      Event*,
                                      EditorCommandSource,
-                                     const String&);
+                                     const WTF::String&);
   static bool ExecuteInsertTab(LocalFrame&,
                                Event*,
                                EditorCommandSource,
-                               const String&);
+                               const WTF::String&);
   static bool ExecuteInsertText(LocalFrame&,
                                 Event*,
                                 EditorCommandSource,
-                                const String&);
+                                const WTF::String&);
   static bool ExecuteInsertUnorderedList(LocalFrame&,
                                          Event*,
                                          EditorCommandSource,
-                                         const String&);
+                                         const WTF::String&);
 
  private:
   static bool ExecuteInsertFragment(LocalFrame&, DocumentFragment*);
diff --git a/third_party/blink/renderer/core/editing/commands/move_commands.h b/third_party/blink/renderer/core/editing/commands/move_commands.h
index fd2b789..bc651e09 100644
--- a/third_party/blink/renderer/core/editing/commands/move_commands.h
+++ b/third_party/blink/renderer/core/editing/commands/move_commands.h
@@ -34,7 +34,10 @@
 
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -56,200 +59,200 @@
   static bool ExecuteMoveBackward(LocalFrame&,
                                   Event*,
                                   EditorCommandSource,
-                                  const String&);
+                                  const WTF::String&);
   static bool ExecuteMoveBackwardAndModifySelection(LocalFrame&,
                                                     Event*,
                                                     EditorCommandSource,
-                                                    const String&);
+                                                    const WTF::String&);
   static bool ExecuteMoveDown(LocalFrame&,
                               Event*,
                               EditorCommandSource,
-                              const String&);
+                              const WTF::String&);
   static bool ExecuteMoveDownAndModifySelection(LocalFrame&,
                                                 Event*,
                                                 EditorCommandSource,
-                                                const String&);
+                                                const WTF::String&);
   static bool ExecuteMoveForward(LocalFrame&,
                                  Event*,
                                  EditorCommandSource,
-                                 const String&);
+                                 const WTF::String&);
   static bool ExecuteMoveForwardAndModifySelection(LocalFrame&,
                                                    Event*,
                                                    EditorCommandSource,
-                                                   const String&);
+                                                   const WTF::String&);
   static bool ExecuteMoveLeft(LocalFrame&,
                               Event*,
                               EditorCommandSource,
-                              const String&);
+                              const WTF::String&);
   static bool ExecuteMoveLeftAndModifySelection(LocalFrame&,
                                                 Event*,
                                                 EditorCommandSource,
-                                                const String&);
+                                                const WTF::String&);
   static bool ExecuteMovePageDown(LocalFrame&,
                                   Event*,
                                   EditorCommandSource,
-                                  const String&);
+                                  const WTF::String&);
   static bool ExecuteMovePageDownAndModifySelection(LocalFrame&,
                                                     Event*,
                                                     EditorCommandSource,
-                                                    const String&);
+                                                    const WTF::String&);
   static bool ExecuteMovePageUp(LocalFrame&,
                                 Event*,
                                 EditorCommandSource,
-                                const String&);
+                                const WTF::String&);
   static bool ExecuteMovePageUpAndModifySelection(LocalFrame&,
                                                   Event*,
                                                   EditorCommandSource,
-                                                  const String&);
+                                                  const WTF::String&);
   static bool ExecuteMoveParagraphBackward(LocalFrame&,
                                            Event*,
                                            EditorCommandSource,
-                                           const String&);
+                                           const WTF::String&);
   static bool ExecuteMoveParagraphBackwardAndModifySelection(
       LocalFrame&,
       Event*,
       EditorCommandSource,
-      const String&);
+      const WTF::String&);
   static bool ExecuteMoveParagraphForward(LocalFrame&,
                                           Event*,
                                           EditorCommandSource,
-                                          const String&);
+                                          const WTF::String&);
   static bool ExecuteMoveParagraphForwardAndModifySelection(LocalFrame&,
                                                             Event*,
                                                             EditorCommandSource,
-                                                            const String&);
+                                                            const WTF::String&);
   static bool ExecuteMoveRight(LocalFrame&,
                                Event*,
                                EditorCommandSource,
-                               const String&);
+                               const WTF::String&);
   static bool ExecuteMoveRightAndModifySelection(LocalFrame&,
                                                  Event*,
                                                  EditorCommandSource,
-                                                 const String&);
+                                                 const WTF::String&);
   static bool ExecuteMoveToBeginningOfDocument(LocalFrame&,
                                                Event*,
                                                EditorCommandSource,
-                                               const String&);
+                                               const WTF::String&);
   static bool ExecuteMoveToBeginningOfDocumentAndModifySelection(
       LocalFrame&,
       Event*,
       EditorCommandSource,
-      const String&);
+      const WTF::String&);
   static bool ExecuteMoveToBeginningOfLine(LocalFrame&,
                                            Event*,
                                            EditorCommandSource,
-                                           const String&);
+                                           const WTF::String&);
   static bool ExecuteMoveToBeginningOfLineAndModifySelection(
       LocalFrame&,
       Event*,
       EditorCommandSource,
-      const String&);
+      const WTF::String&);
   static bool ExecuteMoveToBeginningOfParagraph(LocalFrame&,
                                                 Event*,
                                                 EditorCommandSource,
-                                                const String&);
+                                                const WTF::String&);
   static bool ExecuteMoveToBeginningOfParagraphAndModifySelection(
       LocalFrame&,
       Event*,
       EditorCommandSource,
-      const String&);
+      const WTF::String&);
   static bool ExecuteMoveToBeginningOfSentence(LocalFrame&,
                                                Event*,
                                                EditorCommandSource,
-                                               const String&);
+                                               const WTF::String&);
   static bool ExecuteMoveToBeginningOfSentenceAndModifySelection(
       LocalFrame&,
       Event*,
       EditorCommandSource,
-      const String&);
+      const WTF::String&);
   static bool ExecuteMoveToEndOfDocument(LocalFrame&,
                                          Event*,
                                          EditorCommandSource,
-                                         const String&);
+                                         const WTF::String&);
   static bool ExecuteMoveToEndOfDocumentAndModifySelection(LocalFrame&,
                                                            Event*,
                                                            EditorCommandSource,
-                                                           const String&);
+                                                           const WTF::String&);
   static bool ExecuteMoveToEndOfLine(LocalFrame&,
                                      Event*,
                                      EditorCommandSource,
-                                     const String&);
+                                     const WTF::String&);
   static bool ExecuteMoveToEndOfLineAndModifySelection(LocalFrame&,
                                                        Event*,
                                                        EditorCommandSource,
-                                                       const String&);
+                                                       const WTF::String&);
   static bool ExecuteMoveToEndOfParagraph(LocalFrame&,
                                           Event*,
                                           EditorCommandSource,
-                                          const String&);
+                                          const WTF::String&);
   static bool ExecuteMoveToEndOfParagraphAndModifySelection(LocalFrame&,
                                                             Event*,
                                                             EditorCommandSource,
-                                                            const String&);
+                                                            const WTF::String&);
   static bool ExecuteMoveToEndOfSentence(LocalFrame&,
                                          Event*,
                                          EditorCommandSource,
-                                         const String&);
+                                         const WTF::String&);
   static bool ExecuteMoveToEndOfSentenceAndModifySelection(LocalFrame&,
                                                            Event*,
                                                            EditorCommandSource,
-                                                           const String&);
+                                                           const WTF::String&);
   static bool ExecuteMoveToLeftEndOfLine(LocalFrame&,
                                          Event*,
                                          EditorCommandSource,
-                                         const String&);
+                                         const WTF::String&);
   static bool ExecuteMoveToLeftEndOfLineAndModifySelection(LocalFrame&,
                                                            Event*,
                                                            EditorCommandSource,
-                                                           const String&);
+                                                           const WTF::String&);
   static bool ExecuteMoveToRightEndOfLine(LocalFrame&,
                                           Event*,
                                           EditorCommandSource,
-                                          const String&);
+                                          const WTF::String&);
   static bool ExecuteMoveToRightEndOfLineAndModifySelection(LocalFrame&,
                                                             Event*,
                                                             EditorCommandSource,
-                                                            const String&);
+                                                            const WTF::String&);
   static bool ExecuteMoveUp(LocalFrame&,
                             Event*,
                             EditorCommandSource,
-                            const String&);
+                            const WTF::String&);
   static bool ExecuteMoveUpAndModifySelection(LocalFrame&,
                                               Event*,
                                               EditorCommandSource,
-                                              const String&);
+                                              const WTF::String&);
   static bool ExecuteMoveWordBackward(LocalFrame&,
                                       Event*,
                                       EditorCommandSource,
-                                      const String&);
+                                      const WTF::String&);
   static bool ExecuteMoveWordBackwardAndModifySelection(LocalFrame&,
                                                         Event*,
                                                         EditorCommandSource,
-                                                        const String&);
+                                                        const WTF::String&);
   static bool ExecuteMoveWordForward(LocalFrame&,
                                      Event*,
                                      EditorCommandSource,
-                                     const String&);
+                                     const WTF::String&);
   static bool ExecuteMoveWordForwardAndModifySelection(LocalFrame&,
                                                        Event*,
                                                        EditorCommandSource,
-                                                       const String&);
+                                                       const WTF::String&);
   static bool ExecuteMoveWordLeft(LocalFrame&,
                                   Event*,
                                   EditorCommandSource,
-                                  const String&);
+                                  const WTF::String&);
   static bool ExecuteMoveWordLeftAndModifySelection(LocalFrame&,
                                                     Event*,
                                                     EditorCommandSource,
-                                                    const String&);
+                                                    const WTF::String&);
   static bool ExecuteMoveWordRight(LocalFrame&,
                                    Event*,
                                    EditorCommandSource,
-                                   const String&);
+                                   const WTF::String&);
   static bool ExecuteMoveWordRightAndModifySelection(LocalFrame&,
                                                      Event*,
                                                      EditorCommandSource,
-                                                     const String&);
+                                                     const WTF::String&);
 
  private:
   static unsigned VerticalScrollDistance(LocalFrame&);
diff --git a/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h b/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h
index 0a5c2ab6..dd4f0f9 100644
--- a/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h
+++ b/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h
@@ -33,6 +33,10 @@
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
+namespace WTF {
+class StringBuilder;
+}  // namespace WTF
+
 namespace blink {
 
 class ContainerNode;
@@ -53,7 +57,7 @@
   UChar CharacterAt(unsigned index) const;
   // TODO(xiaochengh): Rename to |GetText()| as it's used in production code.
   String GetTextForTesting() const;
-  void AppendTextToStringBuilder(StringBuilder&,
+  void AppendTextToStringBuilder(WTF::StringBuilder&,
                                  unsigned position = 0,
                                  unsigned max_length = UINT_MAX) const;
 
diff --git a/third_party/blink/renderer/core/editing/serializers/html_interchange.h b/third_party/blink/renderer/core/editing/serializers/html_interchange.h
index fbc5702..e45fa611 100644
--- a/third_party/blink/renderer/core/editing/serializers/html_interchange.h
+++ b/third_party/blink/renderer/core/editing/serializers/html_interchange.h
@@ -26,7 +26,9 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SERIALIZERS_HTML_INTERCHANGE_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SERIALIZERS_HTML_INTERCHANGE_H_
 
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -34,7 +36,7 @@
 
 #define AppleInterchangeNewline "Apple-interchange-newline"
 
-String ConvertHTMLTextToInterchangeFormat(const String&, const Text&);
+WTF::String ConvertHTMLTextToInterchangeFormat(const WTF::String&, const Text&);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/core/editing/text_segments.h b/third_party/blink/renderer/core/editing/text_segments.h
index d5864e7..2ce02416 100644
--- a/third_party/blink/renderer/core/editing/text_segments.h
+++ b/third_party/blink/renderer/core/editing/text_segments.h
@@ -7,7 +7,10 @@
 
 #include "third_party/blink/renderer/core/editing/forward.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -47,7 +50,7 @@
     // Note: |text| must contains character 16.
     // Note: Since implementations can have state, |Find()| function isn't
     // marked |const| intentionally.
-    virtual Position Find(const String text, unsigned offset) = 0;
+    virtual Position Find(const WTF::String text, unsigned offset) = 0;
   };
 
   // Returns a boundary position found by |finder| followed by |position|
diff --git a/third_party/blink/renderer/core/exported/build.gni b/third_party/blink/renderer/core/exported/build.gni
index c3fb023..745c1e9 100644
--- a/third_party/blink/renderer/core/exported/build.gni
+++ b/third_party/blink/renderer/core/exported/build.gni
@@ -86,7 +86,6 @@
   "web_frame_serializer_test_helper.h",
   "web_image_test.cc",
   "web_meaningful_layouts_test.cc",
-  "web_link_preview_triggerer_test.cc",
   "web_node_test.cc",
   "web_plugin_container_test.cc",
   "web_range_test.cc",
diff --git a/third_party/blink/renderer/core/exported/web_document.cc b/third_party/blink/renderer/core/exported/web_document.cc
index c063db4..cc236fea 100644
--- a/third_party/blink/renderer/core/exported/web_document.cc
+++ b/third_party/blink/renderer/core/exported/web_document.cc
@@ -67,7 +67,6 @@
 #include "third_party/blink/renderer/core/html/plugin_document.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/page/page.h"
-#include "third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
@@ -369,18 +368,4 @@
   return WebString(ConstUnwrap<Document>()->domWindow()->OutgoingReferrer());
 }
 
-void WebDocument::InitiatePreview(const WebURL& url) {
-  if (!url.IsValid()) {
-    return;
-  }
-
-  Document* document = blink::To<Document>(private_.Get());
-  if (!document) {
-    return;
-  }
-
-  KURL kurl(url);
-  DocumentSpeculationRules::From(*document).InitiatePreview(kurl);
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/exported/web_link_preview_triggerer_test.cc b/third_party/blink/renderer/core/exported/web_link_preview_triggerer_test.cc
deleted file mode 100644
index b77531de..0000000
--- a/third_party/blink/renderer/core/exported/web_link_preview_triggerer_test.cc
+++ /dev/null
@@ -1,203 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/web/web_link_preview_triggerer.h"
-
-#include <memory>
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/input/web_keyboard_event.h"
-#include "third_party/blink/public/web/web_element.h"
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/exported/web_view_impl.h"
-#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/core/input/event_handler.h"
-#include "third_party/blink/renderer/core/page/page.h"
-#include "third_party/blink/renderer/core/testing/page_test_base.h"
-#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
-#include "ui/events/keycodes/dom/dom_code.h"
-
-namespace blink {
-
-class MockWebLinkPreviewTriggerer : public WebLinkPreviewTriggerer {
- public:
-  MockWebLinkPreviewTriggerer() = default;
-  ~MockWebLinkPreviewTriggerer() override = default;
-
-  int LastKeyEventModifiers() const { return last_key_event_modifiers_; }
-
-  const WebElement& HoverElement() const { return hover_element_; }
-
-  const WebElement& Element() const { return element_; }
-
-  const std::optional<WebMouseEvent>& MouseEvent() const {
-    return mouse_event_;
-  }
-
-  void MaybeChangedKeyEventModifier(int modifiers) override {
-    last_key_event_modifiers_ = modifiers;
-  }
-
-  void DidChangeHoverElement(blink::WebElement element) override {
-    hover_element_ = element;
-  }
-
-  void DidAnchorElementReceiveMouseEvent(
-      blink::WebElement anchor_element,
-      blink::WebMouseEvent mouse_event) override {
-    element_ = anchor_element;
-    mouse_event_ = mouse_event;
-  }
-
- private:
-  int last_key_event_modifiers_ = blink::WebInputEvent::kNoModifiers;
-  WebElement hover_element_;
-  WebElement element_;
-  std::optional<WebMouseEvent> mouse_event_ = std::nullopt;
-};
-
-class WebLinkPreviewTriggererTest : public PageTestBase {
- protected:
-  void Initialize() {
-    LocalFrame* local_frame = GetDocument().GetFrame();
-    CHECK(local_frame);
-
-    local_frame->SetLinkPreviewTriggererForTesting(
-        std::make_unique<MockWebLinkPreviewTriggerer>());
-  }
-
-  void SetInnerHTML(const String& html) {
-    GetDocument().documentElement()->setInnerHTML(html);
-  }
-};
-
-TEST_F(WebLinkPreviewTriggererTest, MaybeChangedKeyEventModifierCalled) {
-  Initialize();
-  SetHtmlInnerHTML("<div></div>");
-  MockWebLinkPreviewTriggerer* triggerer =
-      static_cast<MockWebLinkPreviewTriggerer*>(
-          GetDocument().GetFrame()->GetOrCreateLinkPreviewTriggerer());
-
-  EXPECT_EQ(WebInputEvent::kNoModifiers, triggerer->LastKeyEventModifiers());
-
-  WebKeyboardEvent e0{WebInputEvent::Type::kRawKeyDown, WebInputEvent::kAltKey,
-                      WebInputEvent::GetStaticTimeStampForTests()};
-  e0.dom_code = static_cast<int>(ui::DomCode::ALT_LEFT);
-  GetDocument().GetFrame()->GetEventHandler().KeyEvent(e0);
-
-  EXPECT_EQ(WebInputEvent::kAltKey, triggerer->LastKeyEventModifiers());
-
-  WebKeyboardEvent e1{WebInputEvent::Type::kKeyUp, WebInputEvent::kNoModifiers,
-                      WebInputEvent::GetStaticTimeStampForTests()};
-  e1.dom_code = static_cast<int>(ui::DomCode::ALT_LEFT);
-  GetDocument().GetFrame()->GetEventHandler().KeyEvent(e1);
-
-  EXPECT_EQ(WebInputEvent::kNoModifiers, triggerer->LastKeyEventModifiers());
-}
-
-TEST_F(WebLinkPreviewTriggererTest,
-       MaybeChangedKeyEventModifierCalledWithNoModifiersOnMouseLeave) {
-  Initialize();
-  SetHtmlInnerHTML("<div></div>");
-  MockWebLinkPreviewTriggerer* triggerer =
-      static_cast<MockWebLinkPreviewTriggerer*>(
-          GetDocument().GetFrame()->GetOrCreateLinkPreviewTriggerer());
-
-  EXPECT_EQ(WebInputEvent::kNoModifiers, triggerer->LastKeyEventModifiers());
-
-  WebKeyboardEvent e0{WebInputEvent::Type::kRawKeyDown, WebInputEvent::kAltKey,
-                      WebInputEvent::GetStaticTimeStampForTests()};
-  e0.dom_code = static_cast<int>(ui::DomCode::ALT_LEFT);
-  GetDocument().GetFrame()->GetEventHandler().KeyEvent(e0);
-
-  EXPECT_EQ(WebInputEvent::kAltKey, triggerer->LastKeyEventModifiers());
-
-  WebMouseEvent e1(WebMouseEvent::Type::kMouseLeave, gfx::PointF(262, 29),
-                   gfx::PointF(329, 67),
-                   WebPointerProperties::Button::kNoButton, 1,
-                   WebInputEvent::Modifiers::kNoModifiers,
-                   WebInputEvent::GetStaticTimeStampForTests());
-  GetDocument().GetFrame()->GetEventHandler().HandleMouseLeaveEvent(e1);
-
-  EXPECT_EQ(WebInputEvent::kNoModifiers, triggerer->LastKeyEventModifiers());
-}
-
-TEST_F(WebLinkPreviewTriggererTest, DidChangeHoverElementCalledOnHoverChanged) {
-  Initialize();
-  SetHtmlInnerHTML(
-      "<style>"
-      "  body { margin:0px; }"
-      "  a { display:block; width:100px; height:100px; }"
-      "</style>"
-      "<body>"
-      "  <a href=\"https://example.com\">anchor</a>"
-      "</body>");
-  MockWebLinkPreviewTriggerer* triggerer =
-      static_cast<MockWebLinkPreviewTriggerer*>(
-          GetDocument().GetFrame()->GetOrCreateLinkPreviewTriggerer());
-
-  {
-    gfx::PointF point(50, 50);
-    WebMouseEvent mouse_move_event(WebInputEvent::Type::kMouseMove, point,
-                                   point,
-                                   WebPointerProperties::Button::kNoButton, 0,
-                                   WebInputEvent::Modifiers::kNoModifiers,
-                                   WebInputEvent::GetStaticTimeStampForTests());
-
-    GetDocument().GetFrame()->GetEventHandler().HandleMouseMoveEvent(
-        mouse_move_event, Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
-
-    EXPECT_FALSE(triggerer->HoverElement().IsNull());
-    EXPECT_EQ("A", triggerer->HoverElement().TagName());
-    EXPECT_EQ("https://example.com",
-              triggerer->HoverElement().GetAttribute("href"));
-  }
-
-  {
-    gfx::PointF point(200, 200);
-    WebMouseEvent mouse_move_event(WebInputEvent::Type::kMouseMove, point,
-                                   point,
-                                   WebPointerProperties::Button::kNoButton, 0,
-                                   WebInputEvent::Modifiers::kNoModifiers,
-                                   WebInputEvent::GetStaticTimeStampForTests());
-
-    GetDocument().GetFrame()->GetEventHandler().HandleMouseMoveEvent(
-        mouse_move_event, Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
-
-    EXPECT_FALSE(triggerer->Element().IsNull());
-    EXPECT_EQ("HTML", triggerer->HoverElement().TagName());
-  }
-}
-
-TEST_F(WebLinkPreviewTriggererTest,
-       DidAnchorElementReceiveMouseEventCalledOnMousePress) {
-  Initialize();
-  SetHtmlInnerHTML(
-      "<style>"
-      "  body { margin:0px; }"
-      "  a { display:block; width:100px; height:100px; }"
-      "</style>"
-      "<body>"
-      "  <a href=\"https://example.com\">anchor</a>"
-      "</body>");
-  MockWebLinkPreviewTriggerer* triggerer =
-      static_cast<MockWebLinkPreviewTriggerer*>(
-          GetDocument().GetFrame()->GetOrCreateLinkPreviewTriggerer());
-
-  gfx::PointF point(50, 50);
-  WebMouseEvent mouse_down_event(WebInputEvent::Type::kMouseDown, point, point,
-                                 WebPointerProperties::Button::kLeft, 1,
-                                 WebInputEvent::Modifiers::kNoModifiers,
-                                 WebInputEvent::GetStaticTimeStampForTests());
-
-  GetDocument().GetFrame()->GetEventHandler().HandleMousePressEvent(
-      mouse_down_event);
-
-  EXPECT_FALSE(triggerer->Element().IsNull());
-  EXPECT_EQ("https://example.com", triggerer->Element().GetAttribute("href"));
-  EXPECT_TRUE(triggerer->MouseEvent());
-  EXPECT_EQ(WebInputEvent::Type::kMouseDown,
-            triggerer->MouseEvent()->GetType());
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/fileapi/file_reader_data.h b/third_party/blink/renderer/core/fileapi/file_reader_data.h
index e0e68b31..bf1446e2 100644
--- a/third_party/blink/renderer/core/fileapi/file_reader_data.h
+++ b/third_party/blink/renderer/core/fileapi/file_reader_data.h
@@ -10,6 +10,10 @@
 #include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 // FileReaderData is a convenience class to help users convert the data
@@ -41,18 +45,18 @@
   DOMArrayBuffer* AsDOMArrayBuffer() &&;
   // AsBinaryString converts the underlying ArrayBufferContents to a binary
   // string representation.
-  String AsBinaryString() &&;
+  WTF::String AsBinaryString() &&;
   // AsText converts the underlying ArrayBufferContents to text.
-  String AsText(const String& encoding) &&;
+  WTF::String AsText(const WTF::String& encoding) &&;
   // AsDataURL converts the underlying ArrayBufferContents to a data URL
   // representation.
-  String AsDataURL(const String& data_type) &&;
+  WTF::String AsDataURL(const WTF::String& data_type) &&;
   // AsString is a convenience method that calls either AsBinaryString, AsText
   // or AsDataURL depending on the passed FileReadType. Depending on that type,
   // encoding or data_type must be set accordingly.
-  String AsString(FileReadType read_type,
-                  const String& encoding,
-                  const String& data_type) &&;
+  WTF::String AsString(FileReadType read_type,
+                       const WTF::String& encoding,
+                       const WTF::String& data_type) &&;
 
  private:
   ArrayBufferContents raw_data_;
diff --git a/third_party/blink/renderer/core/fileapi/url_file_api.h b/third_party/blink/renderer/core/fileapi/url_file_api.h
index a003024..2e6b7f9 100644
--- a/third_party/blink/renderer/core/fileapi/url_file_api.h
+++ b/third_party/blink/renderer/core/fileapi/url_file_api.h
@@ -7,7 +7,10 @@
 
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -20,9 +23,9 @@
   STATIC_ONLY(URLFileAPI);
 
  public:
-  static String createObjectURL(ScriptState*, Blob*, ExceptionState&);
-  static void revokeObjectURL(ScriptState*, const String&);
-  static void revokeObjectURL(ExecutionContext*, const String&);
+  static WTF::String createObjectURL(ScriptState*, Blob*, ExceptionState&);
+  static void revokeObjectURL(ScriptState*, const WTF::String&);
+  static void revokeObjectURL(ExecutionContext*, const WTF::String&);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/frame_content_as_text.h b/third_party/blink/renderer/core/frame/frame_content_as_text.h
index 132459d..9d15a18a 100644
--- a/third_party/blink/renderer/core/frame/frame_content_as_text.h
+++ b/third_party/blink/renderer/core/frame/frame_content_as_text.h
@@ -8,7 +8,11 @@
 #include <stdint.h>
 
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
+
+namespace WTF {
+class StringBuilder;
+}  // namespace WTF
 
 namespace blink {
 
@@ -18,7 +22,7 @@
 // |output|, up to the length of |max_chars|.
 CORE_EXPORT void FrameContentAsText(wtf_size_t max_chars,
                                     LocalFrame* frame,
-                                    StringBuilder& output);
+                                    WTF::StringBuilder& output);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index d7fc8c4b..4f33aff 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -82,7 +82,6 @@
 #include "third_party/blink/public/platform/web_vector.h"
 #include "third_party/blink/public/web/web_content_capture_client.h"
 #include "third_party/blink/public/web/web_frame.h"
-#include "third_party/blink/public/web/web_link_preview_triggerer.h"
 #include "third_party/blink/public/web/web_local_frame_client.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
@@ -1016,13 +1015,6 @@
   return DomWindow() ? DomWindow()->document() : nullptr;
 }
 
-void LocalFrame::DocumentDetached() {
-  // Resets WebLinkPreviewTrigerer when the document detached as
-  // WebLinkPreviewInitiator depends on document.
-  is_link_preivew_triggerer_initialized_ = false;
-  link_preview_triggerer_.reset();
-}
-
 void LocalFrame::SetPagePopupOwner(Element& owner) {
   page_popup_owner_ = &owner;
 }
@@ -3892,32 +3884,4 @@
   return print_params_;
 }
 
-WebLinkPreviewTriggerer* LocalFrame::GetOrCreateLinkPreviewTriggerer() {
-  EnsureLinkPreviewTriggererInitialized();
-  return link_preview_triggerer_.get();
-}
-
-void LocalFrame::EnsureLinkPreviewTriggererInitialized() {
-  if (is_link_preivew_triggerer_initialized_) {
-    return;
-  }
-
-  CHECK(!link_preview_triggerer_);
-
-  WebLocalFrameImpl* web_local_frame = WebLocalFrameImpl::FromFrame(this);
-  if (!web_local_frame) {
-    return;
-  }
-
-  link_preview_triggerer_ =
-      web_local_frame->Client()->CreateLinkPreviewTriggerer();
-  is_link_preivew_triggerer_initialized_ = true;
-}
-
-void LocalFrame::SetLinkPreviewTriggererForTesting(
-    std::unique_ptr<WebLinkPreviewTriggerer> trigger) {
-  link_preview_triggerer_ = std::move(trigger);
-  is_link_preivew_triggerer_initialized_ = true;
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h
index 1f659eb..d3faff9 100644
--- a/third_party/blink/renderer/core/frame/local_frame.h
+++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -149,7 +149,6 @@
 class Node;
 class NodeTraversal;
 class PerformanceMonitor;
-class WebLinkPreviewTriggerer;
 class PluginData;
 class PolicyContainer;
 class ScrollSnapshotClient;
@@ -290,7 +289,6 @@
   void SetDOMWindow(LocalDOMWindow*);
   LocalFrameView* View() const override;
   Document* GetDocument() const;
-  void DocumentDetached();
   void SetPagePopupOwner(Element&);
   Element* PagePopupOwner() const { return page_popup_owner_.Get(); }
   bool HasPagePopupOwner() const { return page_popup_owner_ != nullptr; }
@@ -934,10 +932,6 @@
 
   const WebPrintParams& GetPrintParams() const;
 
-  WebLinkPreviewTriggerer* GetOrCreateLinkPreviewTriggerer();
-  void SetLinkPreviewTriggererForTesting(
-      std::unique_ptr<WebLinkPreviewTriggerer> trigger);
-
  private:
   friend class FrameNavigationDisabler;
   // LocalFrameMojoHandler is a part of LocalFrame.
@@ -1021,8 +1015,6 @@
   void MaybeUpdateWindowControlsOverlayWithNewZoomLevel();
 #endif
 
-  void EnsureLinkPreviewTriggererInitialized();
-
   std::unique_ptr<FrameScheduler> frame_scheduler_;
 
   // Holds all PauseSubresourceLoadingHandles allowing either |this| to delete
@@ -1205,12 +1197,6 @@
       feature_handle_for_scheduler_;
 
   WebPrintParams print_params_;
-
-  // Holds WebLinkPreviewTriggerer instance if content renderer client wants to
-  // inject it. Note that `link_preview_triggerer_` may be nullptr after
-  // initialization.
-  bool is_link_preivew_triggerer_initialized_ = false;
-  std::unique_ptr<WebLinkPreviewTriggerer> link_preview_triggerer_;
 };
 
 inline FrameLoader& LocalFrame::Loader() const {
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
index 3d57ede..999f3f7 100644
--- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
@@ -912,7 +912,8 @@
     case ScriptEvaluationResult::ResultType::kSuccess: {
       v8::Local<v8::Value> value = result.GetSuccessValue();
       if (resolve_promises && !value.IsEmpty() && value->IsPromise()) {
-        ScriptPromise promise = ScriptPromise::Cast(script_state, value);
+        ScriptPromise promise =
+            ScriptPromise::FromUntypedValueForBindings(script_state, value);
         promise.Then(handler->CreateResolveCallback(script_state, frame_),
                      handler->CreateRejectCallback(script_state, frame_));
       } else {
diff --git a/third_party/blink/renderer/core/frame/pausable_script_executor.cc b/third_party/blink/renderer/core/frame/pausable_script_executor.cc
index a319d128..3b31917c7 100644
--- a/third_party/blink/renderer/core/frame/pausable_script_executor.cc
+++ b/third_party/blink/renderer/core/frame/pausable_script_executor.cc
@@ -119,11 +119,12 @@
       continue;
 
     ++outstanding_;
-    // ScriptPromise::Cast() will turn any non-promise into a promise that
-    // resolves to the value. Calling ScriptPromise::Cast().Then() will either
-    // wait for the promise (or then-able) to settle, or will immediately finish
-    // with the value. Thus, it's safe to just do this for every value.
-    ScriptPromise::Cast(script_state, values[i])
+    // ScriptPromise::FromUntypedValueForBindings() will turn any non-promise
+    // into a promise that resolves to the value. Calling
+    // ScriptPromise::FromUntypedValueForBindings().Then() will either  wait for
+    // the promise (or then-able) to settle, or will immediately finish  with
+    // the value. Thus, it's safe to just do this for every value.
+    ScriptPromise::FromUntypedValueForBindings(script_state, values[i])
         .Then(OnSettled::New(script_state, this, i, /*was_fulfilled=*/true),
               OnSettled::New(script_state, this, i, /*was_fulfilled=*/false));
   }
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_client.cc b/third_party/blink/renderer/core/frame/web_local_frame_client.cc
index bae55d3..3adcd7c 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_client.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_client.cc
@@ -7,7 +7,6 @@
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
-#include "third_party/blink/public/web/web_link_preview_triggerer.h"
 #include "third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader.h"
 
 namespace blink {
@@ -32,12 +31,4 @@
   return nullptr;
 }
 
-std::unique_ptr<WebLinkPreviewTriggerer>
-WebLocalFrameClient::CreateLinkPreviewTriggerer() {
-  return nullptr;
-}
-
-void WebLocalFrameClient::SetLinkPreviewTriggererForTesting(
-    std::unique_ptr<WebLinkPreviewTriggerer> trigger) {}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc
index f7d1677..3ed168c 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc
@@ -299,8 +299,8 @@
   ScriptEvaluationResult script_result =
       script->RunScriptOnScriptStateAndReturnValue(script_state);
 
-  ScriptPromise promise =
-      ScriptPromise::Cast(script_state, script_result.GetSuccessValue());
+  auto promise =
+      ToResolvedPromise<IDLAny>(script_state, script_result.GetSuccessValue());
   promise.Then(fn, fn);
 
   // Avoid the NOTREACHED in CanvasPerformanceMonitor::WillProcessTask().
diff --git a/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.h b/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.h
index b754d832..4bb2af7 100644
--- a/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.h
+++ b/third_party/blink/renderer/core/html/custom/custom_element_reaction_factory.h
@@ -9,6 +9,10 @@
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class CustomElementDefinition;
@@ -47,7 +51,7 @@
   static CustomElementReaction& CreateFormStateRestore(
       CustomElementDefinition& definition,
       const V8ControlValue* value,
-      const String& mode);
+      const WTF::String& mode);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/forms/date_time_chooser_client.h b/third_party/blink/renderer/core/html/forms/date_time_chooser_client.h
index 066fa4e..b80413b 100644
--- a/third_party/blink/renderer/core/html/forms/date_time_chooser_client.h
+++ b/third_party/blink/renderer/core/html/forms/date_time_chooser_client.h
@@ -33,7 +33,10 @@
 
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -46,7 +49,7 @@
 
   virtual Element& OwnerElement() const = 0;
   // Called when user picked a value.
-  virtual void DidChooseValue(const String&) = 0;
+  virtual void DidChooseValue(const WTF::String&) = 0;
   // Called when user picked a value.
   virtual void DidChooseValue(double) = 0;
   // Called when chooser has ended.
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 753fabb6..2a27f49f 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
@@ -765,8 +765,17 @@
     ListedElement::List* elements_including_shadow_trees,
     bool in_shadow_tree) const {
   DCHECK(!in_shadow_tree || elements_including_shadow_trees);
-  if (!in_shadow_tree)
+  HeapVector<Member<HTMLFormElement>> nested_forms;
+  if (!in_shadow_tree) {
     elements.clear();
+    if (base::FeatureList::IsEnabled(
+            features::kAutofillIncludeFormElementsInShadowDom)) {
+      for (HTMLFormElement& nested_form :
+           Traversal<HTMLFormElement>::DescendantsOf(*this)) {
+        nested_forms.push_back(nested_form);
+      }
+    }
+  }
   for (HTMLElement& element : Traversal<HTMLElement>::StartsAfter(root)) {
     if (ListedElement* listed_element = ListedElement::From(element)) {
       // There are two scenarios:
@@ -793,6 +802,10 @@
         elements.push_back(listed_element);
         if (elements_including_shadow_trees)
           elements_including_shadow_trees->push_back(listed_element);
+      } else if (base::Contains(nested_forms, listed_element->Form())) {
+        if (elements_including_shadow_trees) {
+          elements_including_shadow_trees->push_back(listed_element);
+        }
       }
     }
     if (elements_including_shadow_trees && element.AuthorShadowRoot() &&
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 8611988..13cf3941 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
@@ -120,6 +120,15 @@
     return radio_button_group_scope_;
   }
 
+  // Returns the listed elements associated with `this`. If
+  // `include_shadow_trees` is `true`, then the list will also contain
+  // descendants of `this` that are form control elements and inside Shadow DOM.
+  // Note that if `kAutofillIncludeFormElementsInShadowDom` is enabled and
+  // `include_shadow_trees` is true, then, additionally, the result will contain
+  // the form control elements of <form>s nested inside `this`. In principle,
+  // form nesting is prohibited by the HTML standard, but in practice it can
+  // still occur - e.g., by dynamically appending <form> children to (a
+  // descendant of) `this`.
   const ListedElement::List& ListedElements(
       bool include_shadow_trees = false) const;
   const HeapVector<Member<HTMLImageElement>>& ImageElements();
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 e5e4078..0937205 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
@@ -52,6 +52,9 @@
 //     <form id=form2>
 //       <input>
 TEST_F(HTMLFormElementTest, ListedElementsNestedForms) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndDisableFeature(
+      features::kAutofillIncludeFormElementsInShadowDom);
   HTMLBodyElement* body = GetDocument().FirstBodyElement();
 
   HTMLFormElement* form1 = MakeGarbageCollected<HTMLFormElement>(GetDocument());
@@ -106,6 +109,9 @@
 // in this tree, and each step of the way, ListedElements is checked on all
 // forms.
 TEST_F(HTMLFormElementTest, ListedElementsIncludeShadowTrees) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndDisableFeature(
+      features::kAutofillIncludeFormElementsInShadowDom);
   HTMLBodyElement* body = GetDocument().FirstBodyElement();
 
   HTMLFormElement* form1 = MakeGarbageCollected<HTMLFormElement>(GetDocument());
@@ -348,8 +354,8 @@
                           GetListedElement("i3", shadow_root)));
 }
 
-// Tests that dynamic addition and removal of an element properly invalidates
-// the caches of all ancestors.
+// Tests that dynamic addition and removal of an element inside Shadow DOM
+// properly invalidates the caches of all ancestors.
 TEST_F(HTMLFormElementTest, ListedElementsInDeepNestedForms) {
   base::test::ScopedFeatureList feature_list{
       features::kAutofillIncludeFormElementsInShadowDom};
@@ -405,4 +411,51 @@
                           GetListedElement("i2", shadow_root2)));
 }
 
+// Tests that changes inside nested forms inside light DOM properly invalidate
+// the cache for listed elements.
+TEST_F(HTMLFormElementTest, ListedElementsInDeepNestedFormsLightDom) {
+  base::test::ScopedFeatureList feature_list{
+      features::kAutofillIncludeFormElementsInShadowDom};
+
+  HTMLBodyElement* body = GetDocument().FirstBodyElement();
+  HTMLFormElement* f1 = MakeGarbageCollected<HTMLFormElement>(GetDocument());
+  body->AppendChild(f1);
+  HTMLFormElement* f2 = MakeGarbageCollected<HTMLFormElement>(GetDocument());
+  f1->AppendChild(f2);
+  HTMLFormElement* f3 = MakeGarbageCollected<HTMLFormElement>(GetDocument());
+  f2->AppendChild(f3);
+  HTMLInputElement* input =
+      MakeGarbageCollected<HTMLInputElement>(GetDocument());
+
+  // Prior to attaching `input`, no form has a listed element.
+  EXPECT_THAT(f1->ListedElements(/*include_shadow_trees=*/true), IsEmpty());
+  EXPECT_THAT(f2->ListedElements(/*include_shadow_trees=*/true), IsEmpty());
+  EXPECT_THAT(f3->ListedElements(/*include_shadow_trees=*/true), IsEmpty());
+
+  // If input is attached to a form, all parent forms should also have this
+  // element.
+  f1->AppendChild(input);
+  EXPECT_THAT(f1->ListedElements(/*include_shadow_trees=*/true),
+              ElementsAre(input));
+  EXPECT_THAT(f2->ListedElements(/*include_shadow_trees=*/true), IsEmpty());
+  EXPECT_THAT(f3->ListedElements(/*include_shadow_trees=*/true), IsEmpty());
+
+  input->remove();
+  f2->AppendChild(input);
+  EXPECT_THAT(f1->ListedElements(/*include_shadow_trees=*/true),
+              ElementsAre(input));
+  EXPECT_THAT(f2->ListedElements(/*include_shadow_trees=*/true),
+              ElementsAre(input));
+  EXPECT_THAT(f3->ListedElements(/*include_shadow_trees=*/true), IsEmpty());
+
+  input->remove();
+  f3->AppendChild(input);
+  EXPECT_THAT(f1->ListedElements(/*include_shadow_trees=*/true),
+              ElementsAre(input));
+  EXPECT_THAT(f2->ListedElements(/*include_shadow_trees=*/true),
+              ElementsAre(input));
+  EXPECT_THAT(f3->ListedElements(/*include_shadow_trees=*/true),
+              ElementsAre(input));
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/forms/input_type_view.h b/third_party/blink/renderer/core/html/forms/input_type_view.h
index 38a111f..87031de 100644
--- a/third_party/blink/renderer/core/html/forms/input_type_view.h
+++ b/third_party/blink/renderer/core/html/forms/input_type_view.h
@@ -43,7 +43,10 @@
 #include "third_party/blink/renderer/platform/text/text_direction.h"
 #include "third_party/blink/renderer/platform/theme_types.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -136,7 +139,7 @@
   virtual bool NeedsShadowSubtree() const;
   virtual void DestroyShadowSubtree();
   virtual HTMLInputElement* UploadButton() const;
-  virtual String FileStatusText() const;
+  virtual WTF::String FileStatusText() const;
 
   virtual void MinOrMaxAttributeChanged();
   virtual void StepAttributeChanged();
@@ -148,7 +151,7 @@
   virtual void ReadonlyAttributeChanged();
   virtual void RequiredAttributeChanged();
   virtual void ValueAttributeChanged();
-  virtual void DidSetValue(const String&, bool value_changed);
+  virtual void DidSetValue(const WTF::String&, bool value_changed);
   virtual void ListAttributeTargetChanged();
   virtual void CapsLockStateMayHaveChanged();
   virtual bool ShouldDrawCapsLockIndicator() const;
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 34435e1..1014561 100644
--- a/third_party/blink/renderer/core/html/forms/listed_element.cc
+++ b/third_party/blink/renderer/core/html/forms/listed_element.cc
@@ -24,6 +24,7 @@
 
 #include "third_party/blink/renderer/core/html/forms/listed_element.h"
 
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/renderer/core/dom/element_traversal.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/dom/focus_params.h"
@@ -56,10 +57,18 @@
 
 void InvalidateShadowIncludingAncestorForms(ContainerNode& insertion_point) {
   // 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;
+  // ListedElement has changed. If `kAutofillIncludeFormElementsInShadowDom` is
+  // disabled, forms inside the same `TreeScope` do not need to be included
+  // because their listed elements track their association elsewhere.
+  // If `kAutofillIncludeFormElementsInShadowDom` is enabled, we also cache
+  // listed elements inside (descendant) nested forms in and therefore need to
+  // invalidate the caches also inside the same `TreeScope`.
+  ContainerNode* starting_node =
+      base::FeatureList::IsEnabled(
+          features::kAutofillIncludeFormElementsInShadowDom)
+          ? insertion_point.ParentOrShadowHostNode()
+          : insertion_point.OwnerShadowHost();
+  for (ContainerNode* parent = starting_node; parent;
        parent = parent->ParentOrShadowHostNode()) {
     if (HTMLFormElement* form = DynamicTo<HTMLFormElement>(parent)) {
       form->InvalidateListedElementsIncludingShadowTrees();
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third_party/blink/renderer/core/html/html_anchor_element.cc
index bee4233..e69d12b 100644
--- a/third_party/blink/renderer/core/html/html_anchor_element.cc
+++ b/third_party/blink/renderer/core/html/html_anchor_element.cc
@@ -35,12 +35,10 @@
 #include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-blink.h"
 #include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/web/web_link_preview_triggerer.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/events/keyboard_event.h"
 #include "third_party/blink/renderer/core/events/mouse_event.h"
 #include "third_party/blink/renderer/core/events/pointer_event.h"
-#include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
 #include "third_party/blink/renderer/core/frame/ad_tracker.h"
 #include "third_party/blink/renderer/core/frame/attribution_src_loader.h"
 #include "third_party/blink/renderer/core/frame/deprecation/deprecation.h"
@@ -211,33 +209,8 @@
   url.AppendNumber(clamped_point.y());
 }
 
-void EmitDidAnchorElementReceiveMouseEvent(HTMLAnchorElement& anchor_element,
-                                           Event& event) {
-  LocalFrame* local_frame = anchor_element.GetDocument().GetFrame();
-  if (!local_frame) {
-    return;
-  }
-
-  WebLinkPreviewTriggerer* triggerer =
-      local_frame->GetOrCreateLinkPreviewTriggerer();
-  if (!triggerer) {
-    return;
-  }
-
-  auto* mev = DynamicTo<MouseEvent>(event);
-  if (!mev) {
-    return;
-  }
-
-  WebElement web_element = WebElement(DynamicTo<Element>(&anchor_element));
-  WebMouseEventBuilder web_mouse_event(anchor_element.GetLayoutObject(), *mev);
-  triggerer->DidAnchorElementReceiveMouseEvent(web_element, web_mouse_event);
-}
-
 void HTMLAnchorElement::DefaultEventHandler(Event& event) {
   if (IsLink()) {
-    EmitDidAnchorElementReceiveMouseEvent(*this, event);
-
     if (isConnected() && base::FeatureList::IsEnabled(
                              features::kSpeculativeServiceWorkerWarmUp)) {
       Document& top_document = GetDocument().TopDocument();
diff --git a/third_party/blink/renderer/core/html/html_dimension.h b/third_party/blink/renderer/core/html/html_dimension.h
index 2a3bf96..b04d6c37 100644
--- a/third_party/blink/renderer/core/html/html_dimension.h
+++ b/third_party/blink/renderer/core/html/html_dimension.h
@@ -33,9 +33,12 @@
 
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 // This class corresponds to a dimension as described in HTML5 by the
@@ -71,8 +74,8 @@
   double value_;
 };
 
-CORE_EXPORT Vector<HTMLDimension> ParseListOfDimensions(const String&);
-CORE_EXPORT bool ParseDimensionValue(const String&, HTMLDimension&);
+CORE_EXPORT Vector<HTMLDimension> ParseListOfDimensions(const WTF::String&);
+CORE_EXPORT bool ParseDimensionValue(const WTF::String&, HTMLDimension&);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/core/html/media/autoplay_policy.h b/third_party/blink/renderer/core/html/media/autoplay_policy.h
index 05f5c44e..de7134c 100644
--- a/third_party/blink/renderer/core/html/media/autoplay_policy.h
+++ b/third_party/blink/renderer/core/html/media/autoplay_policy.h
@@ -12,6 +12,10 @@
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class AutoplayUmaHelper;
@@ -101,7 +105,7 @@
 
   // Returns an error string to be used by the HTMLMediaElement when the play()
   // method fails because of autoplay restrictions.
-  String GetPlayErrorMessage() const;
+  WTF::String GetPlayErrorMessage() const;
 
   // Returns whether the media element was initiated via autoplay.
   // In this context, autoplay means that it was initiated before any user
diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser_fastpath.h b/third_party/blink/renderer/core/html/parser/html_document_parser_fastpath.h
index 483131f78..46333c2 100644
--- a/third_party/blink/renderer/core/html/parser/html_document_parser_fastpath.h
+++ b/third_party/blink/renderer/core/html/parser/html_document_parser_fastpath.h
@@ -8,7 +8,10 @@
 #include "base/containers/enum_set.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/parser_content_policy.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -38,7 +41,7 @@
 // If this fails because of an unsupported tag and
 // `failed_because_unsupported_tag` is non-null, then it is set to true.
 CORE_EXPORT bool TryParsingHTMLFragment(
-    const String& source,
+    const WTF::String& source,
     Document& document,
     ContainerNode& root_node,
     Element& context_element,
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
index 9af2ec2..9d52df8 100644
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
@@ -926,7 +926,7 @@
 }
 
 void ImageBitmap::ResolvePromiseOnOriginalThread(
-    ScriptPromiseResolver* resolver,
+    ScriptPromiseResolverTyped<ImageBitmap>* resolver,
     bool origin_clean,
     std::unique_ptr<ParsedOptions> parsed_options,
     sk_sp<SkImage> skia_image,
@@ -979,7 +979,7 @@
                           ImageOrientationEnum::kDefault));
 }
 
-ScriptPromise ImageBitmap::CreateAsync(
+ScriptPromiseTyped<ImageBitmap> ImageBitmap::CreateAsync(
     ImageElementBase* image,
     std::optional<gfx::Rect> crop_rect,
     ScriptState* script_state,
@@ -993,7 +993,7 @@
     exception_state.ThrowDOMException(
         DOMExceptionCode::kInvalidStateError,
         "The ImageBitmap could not be allocated.");
-    return ScriptPromise();
+    return ScriptPromiseTyped<ImageBitmap>();
   }
 
   scoped_refptr<Image> input = image->CachedImage()->GetImage();
@@ -1008,13 +1008,12 @@
         MakeGarbageCollected<ImageBitmap>(MakeBlankImage(parsed_options));
     if (bitmap->BitmapImage()) {
       bitmap->BitmapImage()->SetOriginClean(!image->WouldTaintOrigin());
-      return ScriptPromise::Cast(
-          script_state, ToV8Traits<ImageBitmap>::ToV8(script_state, bitmap));
+      return ToResolvedPromise<ImageBitmap>(script_state, bitmap);
     } else {
       exception_state.ThrowDOMException(
           DOMExceptionCode::kInvalidStateError,
           "The ImageBitmap could not be allocated.");
-      return ScriptPromise();
+      return ScriptPromiseTyped<ImageBitmap>();
     }
   }
 
@@ -1050,9 +1049,10 @@
 
   std::unique_ptr<ParsedOptions> passed_parsed_options =
       std::make_unique<ParsedOptions>(parsed_options);
-  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(
-      script_state, exception_state.GetContext());
-  ScriptPromise promise = resolver->Promise();
+  auto* resolver =
+      MakeGarbageCollected<ScriptPromiseResolverTyped<ImageBitmap>>(
+          script_state, exception_state.GetContext());
+  auto promise = resolver->Promise();
 
   worker_pool::PostTask(
       FROM_HERE,
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap.h b/third_party/blink/renderer/core/imagebitmap/image_bitmap.h
index d80b16d..e2d235e 100644
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap.h
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap.h
@@ -9,6 +9,8 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/task/sequenced_task_runner.h"
 #include "third_party/blink/public/mojom/css/preferred_color_scheme.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_image_bitmap_options.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/html/canvas/canvas_image_source.h"
@@ -29,7 +31,6 @@
 class ImageElementBase;
 class ImageDecoder;
 class OffscreenCanvas;
-class ScriptPromiseResolver;
 
 class CORE_EXPORT ImageBitmap final : public ScriptWrappable,
                                       public CanvasImageSource,
@@ -38,7 +39,7 @@
 
  public:
   // Expects the ImageElementBase to return/have an SVGImage.
-  static ScriptPromise CreateAsync(
+  static ScriptPromiseTyped<ImageBitmap> CreateAsync(
       ImageElementBase*,
       std::optional<gfx::Rect>,
       ScriptState*,
@@ -143,11 +144,12 @@
 
  private:
   void UpdateImageBitmapMemoryUsage();
-  static void ResolvePromiseOnOriginalThread(ScriptPromiseResolver*,
-                                             bool origin_clean,
-                                             std::unique_ptr<ParsedOptions>,
-                                             sk_sp<SkImage>,
-                                             const ImageOrientationEnum);
+  static void ResolvePromiseOnOriginalThread(
+      ScriptPromiseResolverTyped<ImageBitmap>*,
+      bool origin_clean,
+      std::unique_ptr<ParsedOptions>,
+      sk_sp<SkImage>,
+      const ImageOrientationEnum);
   static void RasterizeImageOnBackgroundThread(
       PaintRecord,
       const gfx::Rect&,
diff --git a/third_party/blink/renderer/core/input/event_handler.cc b/third_party/blink/renderer/core/input/event_handler.cc
index 4fdb000f..d29f7f63 100644
--- a/third_party/blink/renderer/core/input/event_handler.cc
+++ b/third_party/blink/renderer/core/input/event_handler.cc
@@ -38,7 +38,6 @@
 #include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h"
 #include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom-blink.h"
 #include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/public/web/web_link_preview_triggerer.h"
 #include "third_party/blink/renderer/core/clipboard/data_transfer.h"
 #include "third_party/blink/renderer/core/css/style_engine.h"
 #include "third_party/blink/renderer/core/dom/document.h"
@@ -1059,13 +1058,6 @@
   Page* page = frame_->GetPage();
   if (page)
     page->GetChromeClient().ClearToolTip(*frame_);
-
-  WebLinkPreviewTriggerer* triggerer =
-      frame_->GetOrCreateLinkPreviewTriggerer();
-  if (triggerer) {
-    triggerer->MaybeChangedKeyEventModifier(WebInputEvent::kNoModifiers);
-  }
-
   HandleMouseMoveOrLeaveEvent(event, Vector<WebMouseEvent>(),
                               Vector<WebMouseEvent>());
   pointer_event_manager_->RemoveLastMousePosition();
diff --git a/third_party/blink/renderer/core/input/keyboard_event_manager.cc b/third_party/blink/renderer/core/input/keyboard_event_manager.cc
index 7d92e590..e4709d1 100644
--- a/third_party/blink/renderer/core/input/keyboard_event_manager.cc
+++ b/third_party/blink/renderer/core/input/keyboard_event_manager.cc
@@ -13,7 +13,6 @@
 #include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h"
 #include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
 #include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/web/web_link_preview_triggerer.h"
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/dom/events/simulated_click_options.h"
 #include "third_party/blink/renderer/core/dom/focus_params.h"
@@ -210,8 +209,6 @@
   if (initial_key_event.windows_key_code == VK_CAPITAL)
     CapsLockStateMayHaveChanged();
 
-  KeyEventModifierMayHaveChanged(initial_key_event.GetModifiers());
-
   if (scroll_manager_->MiddleClickAutoscrollInProgress()) {
     DCHECK(RuntimeEnabledFeatures::MiddleClickAutoscrollEnabled());
     // If a key is pressed while the middleClickAutoscroll is in progress then
@@ -408,16 +405,6 @@
   }
 }
 
-void KeyboardEventManager::KeyEventModifierMayHaveChanged(int modifiers) {
-  WebLinkPreviewTriggerer* triggerer =
-      frame_->GetOrCreateLinkPreviewTriggerer();
-  if (!triggerer) {
-    return;
-  }
-
-  triggerer->MaybeChangedKeyEventModifier(modifiers);
-}
-
 void KeyboardEventManager::DefaultKeyboardEventHandler(
     KeyboardEvent* event,
     Node* possible_focused_node) {
diff --git a/third_party/blink/renderer/core/input/keyboard_event_manager.h b/third_party/blink/renderer/core/input/keyboard_event_manager.h
index cb10de5..15d7f8e4 100644
--- a/third_party/blink/renderer/core/input/keyboard_event_manager.h
+++ b/third_party/blink/renderer/core/input/keyboard_event_manager.h
@@ -58,8 +58,6 @@
   bool is_handling_key_event() const { return is_handling_key_event_; }
 
  private:
-  void KeyEventModifierMayHaveChanged(int modifiers);
-
   friend class Internals;
   // Allows overriding the current caps lock state for testing purposes.
   static void SetCurrentCapsLockState(OverrideCapsLockState);
diff --git a/third_party/blink/renderer/core/inspector/main_thread_debugger.h b/third_party/blink/renderer/core/inspector/main_thread_debugger.h
index 8d0499ca..5fa8758 100644
--- a/third_party/blink/renderer/core/inspector/main_thread_debugger.h
+++ b/third_party/blink/renderer/core/inspector/main_thread_debugger.h
@@ -38,6 +38,10 @@
 #include "v8/include/v8-inspector.h"
 #include "v8/include/v8.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class ErrorEvent;
@@ -86,7 +90,7 @@
   void ReportConsoleMessage(ExecutionContext*,
                             mojom::ConsoleMessageSource,
                             mojom::ConsoleMessageLevel,
-                            const String& message,
+                            const WTF::String& message,
                             SourceLocation*) override;
   int ContextGroupId(ExecutionContext*) override;
 
diff --git a/third_party/blink/renderer/core/inspector/thread_debugger_common_impl.h b/third_party/blink/renderer/core/inspector/thread_debugger_common_impl.h
index 40125e1b..dc5dbef 100644
--- a/third_party/blink/renderer/core/inspector/thread_debugger_common_impl.h
+++ b/third_party/blink/renderer/core/inspector/thread_debugger_common_impl.h
@@ -11,6 +11,10 @@
 #include "third_party/blink/renderer/platform/timer.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class ExecutionContext;
@@ -34,7 +38,7 @@
   void AsyncTaskStarted(void* task) override;
   void AsyncTaskFinished(void* task) override;
   unsigned PromiseRejected(v8::Local<v8::Context>,
-                           const String& error_message,
+                           const WTF::String& error_message,
                            v8::Local<v8::Value> exception,
                            std::unique_ptr<SourceLocation>) override;
   void PromiseRejectionRevoked(v8::Local<v8::Context>,
@@ -52,7 +56,7 @@
   virtual void ReportConsoleMessage(ExecutionContext*,
                                     mojom::ConsoleMessageSource,
                                     mojom::ConsoleMessageLevel,
-                                    const String& message,
+                                    const WTF::String& message,
                                     SourceLocation*) = 0;
   void installAdditionalCommandLineAPI(v8::Local<v8::Context>,
                                        v8::Local<v8::Object>) override;
diff --git a/third_party/blink/renderer/core/inspector/worker_thread_debugger.h b/third_party/blink/renderer/core/inspector/worker_thread_debugger.h
index 2afa133..3652310b 100644
--- a/third_party/blink/renderer/core/inspector/worker_thread_debugger.h
+++ b/third_party/blink/renderer/core/inspector/worker_thread_debugger.h
@@ -35,6 +35,10 @@
 #include "third_party/blink/renderer/core/inspector/thread_debugger_common_impl.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class ErrorEvent;
@@ -67,7 +71,7 @@
   void ReportConsoleMessage(ExecutionContext*,
                             mojom::ConsoleMessageSource,
                             mojom::ConsoleMessageLevel,
-                            const String& message,
+                            const WTF::String& message,
                             SourceLocation*) override;
 
   // V8InspectorClient implementation.
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_geometry.h b/third_party/blink/renderer/core/intersection_observer/intersection_geometry.h
index a5e855a..66552177 100644
--- a/third_party/blink/renderer/core/intersection_observer/intersection_geometry.h
+++ b/third_party/blink/renderer/core/intersection_observer/intersection_geometry.h
@@ -13,6 +13,10 @@
 #include "ui/gfx/geometry/transform.h"
 #include "ui/gfx/geometry/vector2d_f.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class Element;
@@ -101,7 +105,7 @@
     int relationship = 0;
     bool root_scrolls_target = false;
 
-    String ToString() const;
+    WTF::String ToString() const;
 #endif
   };
 
diff --git a/third_party/blink/renderer/core/layout/geometry/bfc_offset.h b/third_party/blink/renderer/core/layout/geometry/bfc_offset.h
index 720f53f5c..a01e0e3e 100644
--- a/third_party/blink/renderer/core/layout/geometry/bfc_offset.h
+++ b/third_party/blink/renderer/core/layout/geometry/bfc_offset.h
@@ -10,6 +10,10 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/geometry/layout_unit.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 struct CORE_EXPORT BfcDelta {
@@ -53,7 +57,7 @@
 
   bool operator!=(const BfcOffset& other) const { return !operator==(other); }
 
-  String ToString() const;
+  WTF::String ToString() const;
 };
 
 CORE_EXPORT std::ostream& operator<<(std::ostream&, const BfcOffset&);
diff --git a/third_party/blink/renderer/core/layout/geometry/bfc_rect.h b/third_party/blink/renderer/core/layout/geometry/bfc_rect.h
index ee20ea58..8293c12 100644
--- a/third_party/blink/renderer/core/layout/geometry/bfc_rect.h
+++ b/third_party/blink/renderer/core/layout/geometry/bfc_rect.h
@@ -11,6 +11,10 @@
 #include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
 #include "third_party/blink/renderer/platform/geometry/layout_unit.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 // BfcRect is the position and size of a rect (typically a fragment)
@@ -48,7 +52,7 @@
 
   bool operator!=(const BfcRect& other) const { return !(*this == other); }
 
-  String ToString() const;
+  WTF::String ToString() const;
 
   BfcOffset start_offset;
   BfcOffset end_offset;
diff --git a/third_party/blink/renderer/core/layout/geometry/box_strut.h b/third_party/blink/renderer/core/layout/geometry/box_strut.h
index 57702e7f..d2a03595 100644
--- a/third_party/blink/renderer/core/layout/geometry/box_strut.h
+++ b/third_party/blink/renderer/core/layout/geometry/box_strut.h
@@ -17,6 +17,10 @@
 #include "third_party/blink/renderer/platform/text/writing_mode.h"
 #include "ui/gfx/geometry/outsets_f.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 struct LineBoxStrut;
@@ -89,7 +93,7 @@
   }
   bool operator!=(const BoxStrut& other) const { return !(*this == other); }
 
-  String ToString() const;
+  WTF::String ToString() const;
 
   LayoutUnit inline_start;
   LayoutUnit inline_end;
diff --git a/third_party/blink/renderer/core/layout/geometry/flex_offset.h b/third_party/blink/renderer/core/layout/geometry/flex_offset.h
index dbea122d..1d1fcd8 100644
--- a/third_party/blink/renderer/core/layout/geometry/flex_offset.h
+++ b/third_party/blink/renderer/core/layout/geometry/flex_offset.h
@@ -8,6 +8,10 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/geometry/layout_unit.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 struct LogicalOffset;
@@ -55,7 +59,7 @@
 
   LogicalOffset ToLogicalOffset(bool is_column_flex_container) const;
 
-  String ToString() const;
+  WTF::String ToString() const;
 };
 
 CORE_EXPORT std::ostream& operator<<(std::ostream&, const FlexOffset&);
diff --git a/third_party/blink/renderer/core/layout/geometry/logical_offset.h b/third_party/blink/renderer/core/layout/geometry/logical_offset.h
index be02a51..d5201296 100644
--- a/third_party/blink/renderer/core/layout/geometry/logical_offset.h
+++ b/third_party/blink/renderer/core/layout/geometry/logical_offset.h
@@ -11,6 +11,10 @@
 #include "third_party/blink/renderer/platform/geometry/layout_unit.h"
 #include "third_party/blink/renderer/platform/text/writing_direction_mode.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 struct LogicalDelta;
@@ -93,7 +97,7 @@
            block_offset <= other.block_offset;
   }
 
-  String ToString() const;
+  WTF::String ToString() const;
 };
 
 CORE_EXPORT std::ostream& operator<<(std::ostream&, const LogicalOffset&);
diff --git a/third_party/blink/renderer/core/layout/geometry/logical_rect.h b/third_party/blink/renderer/core/layout/geometry/logical_rect.h
index 4a9de2b..7662a669 100644
--- a/third_party/blink/renderer/core/layout/geometry/logical_rect.h
+++ b/third_party/blink/renderer/core/layout/geometry/logical_rect.h
@@ -11,6 +11,10 @@
 #include "third_party/blink/renderer/platform/geometry/layout_rect.h"
 #include "ui/gfx/geometry/rect_f.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 // LogicalRect is the position and size of a rect (typically a fragment)
@@ -135,7 +139,7 @@
       : offset(LayoutUnit(r.x()), LayoutUnit(r.y())),
         size(LayoutUnit(r.width()), LayoutUnit(r.height())) {}
 
-  String ToString() const;
+  WTF::String ToString() const;
 };
 
 CORE_EXPORT std::ostream& operator<<(std::ostream&, const LogicalRect&);
diff --git a/third_party/blink/renderer/core/layout/geometry/physical_offset.h b/third_party/blink/renderer/core/layout/geometry/physical_offset.h
index 4d6cef9..d1257e6c 100644
--- a/third_party/blink/renderer/core/layout/geometry/physical_offset.h
+++ b/third_party/blink/renderer/core/layout/geometry/physical_offset.h
@@ -15,6 +15,10 @@
 #include "ui/gfx/geometry/vector2d.h"
 #include "ui/gfx/geometry/vector2d_f.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class LayoutPoint;
@@ -129,7 +133,7 @@
   constexpr explicit operator gfx::PointF() const { return {left, top}; }
   constexpr explicit operator gfx::Vector2dF() const { return {left, top}; }
 
-  String ToString() const;
+  WTF::String ToString() const;
 };
 
 // TODO(crbug.com/962299): These functions should upgraded to force correct
diff --git a/third_party/blink/renderer/core/layout/geometry/physical_rect.h b/third_party/blink/renderer/core/layout/geometry/physical_rect.h
index 7facd42..25c4e94 100644
--- a/third_party/blink/renderer/core/layout/geometry/physical_rect.h
+++ b/third_party/blink/renderer/core/layout/geometry/physical_rect.h
@@ -14,8 +14,9 @@
 #include "ui/gfx/geometry/rect_f.h"
 
 namespace WTF {
+class String;
 class TextStream;
-}
+}  // namespace WTF
 
 namespace blink {
 
@@ -211,7 +212,7 @@
     size.Scale(s);
   }
 
-  String ToString() const;
+  WTF::String ToString() const;
 };
 
 inline PhysicalRect UnionRect(const PhysicalRect& a, const PhysicalRect& b) {
diff --git a/third_party/blink/renderer/core/layout/geometry/physical_size.h b/third_party/blink/renderer/core/layout/geometry/physical_size.h
index f4b49e83..c1b8726 100644
--- a/third_party/blink/renderer/core/layout/geometry/physical_size.h
+++ b/third_party/blink/renderer/core/layout/geometry/physical_size.h
@@ -13,6 +13,10 @@
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/geometry/size_f.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 enum AspectRatioFit { kAspectRatioFitShrink, kAspectRatioFitGrow };
@@ -140,7 +144,7 @@
   explicit PhysicalSize(const gfx::Size& size)
       : width(size.width()), height(size.height()) {}
 
-  String ToString() const;
+  WTF::String ToString() const;
 };
 
 CORE_EXPORT std::ostream& operator<<(std::ostream&, const PhysicalSize&);
diff --git a/third_party/blink/renderer/core/loader/navigation_policy.cc b/third_party/blink/renderer/core/loader/navigation_policy.cc
index 90f6f32..01e86be 100644
--- a/third_party/blink/renderer/core/loader/navigation_policy.cc
+++ b/third_party/blink/renderer/core/loader/navigation_policy.cc
@@ -140,8 +140,8 @@
 
 NavigationPolicy NavigationPolicyFromEvent(const Event* event) {
   // TODO(b:298160400): Add a setting to disable Link Preview.
-  bool is_link_preview_enabled = IsLinkPreviewTriggerTypeEnabled(
-      features::LinkPreviewTriggerType::kAltClick);
+  bool is_link_preview_enabled =
+      base::FeatureList::IsEnabled(features::kLinkPreview);
 
   NavigationPolicy event_policy =
       NavigationPolicyFromEventInternal(event, is_link_preview_enabled);
diff --git a/third_party/blink/renderer/core/loader/navigation_policy_test.cc b/third_party/blink/renderer/core/loader/navigation_policy_test.cc
index 5cf24b39..ffff6dbc 100644
--- a/third_party/blink/renderer/core/loader/navigation_policy_test.cc
+++ b/third_party/blink/renderer/core/loader/navigation_policy_test.cc
@@ -104,8 +104,7 @@
 class NavigationPolicyWithLinkPreviewEnabledTest : public NavigationPolicyTest {
  protected:
   void SetUp() override {
-    scoped_feature_list_.InitAndEnableFeatureWithParameters(
-        features::kLinkPreview, {{"trigger_type", "alt_click"}});
+    scoped_feature_list_.InitAndEnableFeature(features::kLinkPreview);
   }
 };
 
diff --git a/third_party/blink/renderer/core/loader/ping_loader.h b/third_party/blink/renderer/core/loader/ping_loader.h
index 8fab6e6..ad6c016 100644
--- a/third_party/blink/renderer/core/loader/ping_loader.h
+++ b/third_party/blink/renderer/core/loader/ping_loader.h
@@ -36,7 +36,10 @@
 #include "third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader_client.h"
 #include "third_party/blink/renderer/platform/timer.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -79,7 +82,7 @@
   static bool SendBeacon(const ScriptState&,
                          LocalFrame*,
                          const KURL&,
-                         const String&);
+                         const WTF::String&);
   static bool SendBeacon(const ScriptState&,
                          LocalFrame*,
                          const KURL&,
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_observer.h b/third_party/blink/renderer/core/loader/resource/image_resource_observer.h
index b212f17..0bb3240e 100644
--- a/third_party/blink/renderer/core/loader/resource/image_resource_observer.h
+++ b/third_party/blink/renderer/core/loader/resource/image_resource_observer.h
@@ -27,7 +27,10 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/style/style_image.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_priority.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -85,7 +88,7 @@
   }
 
   // Name for debugging, e.g. shown in memory-infra.
-  virtual String DebugName() const = 0;
+  virtual WTF::String DebugName() const = 0;
 
   static bool IsExpectedType(ImageResourceObserver*) { return true; }
 
diff --git a/third_party/blink/renderer/core/navigation_api/navigation_api.cc b/third_party/blink/renderer/core/navigation_api/navigation_api.cc
index 56bd2b0..0ca49e6 100644
--- a/third_party/blink/renderer/core/navigation_api/navigation_api.cc
+++ b/third_party/blink/renderer/core/navigation_api/navigation_api.cc
@@ -78,9 +78,10 @@
 NavigationResult* EarlySuccessResult(ScriptState* script_state,
                                      NavigationHistoryEntry* entry) {
   auto* result = NavigationResult::Create();
-  auto v8_entry = ToV8Traits<NavigationHistoryEntry>::ToV8(script_state, entry);
-  result->setCommitted(ScriptPromise::Cast(script_state, v8_entry));
-  result->setFinished(ScriptPromise::Cast(script_state, v8_entry));
+  result->setCommitted(
+      ToResolvedPromise<NavigationHistoryEntry>(script_state, entry));
+  result->setFinished(
+      ToResolvedPromise<NavigationHistoryEntry>(script_state, entry));
   return result;
 }
 
diff --git a/third_party/blink/renderer/core/page/drag_data.h b/third_party/blink/renderer/core/page/drag_data.h
index 386644e..7d083eb 100644
--- a/third_party/blink/renderer/core/page/drag_data.h
+++ b/third_party/blink/renderer/core/page/drag_data.h
@@ -30,10 +30,13 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/page/drag_actions.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 #include "ui/gfx/geometry/point_f.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class DataObject;
@@ -63,10 +66,11 @@
       FilenameConversionPolicy filename_policy = kConvertFilenames) const;
   bool ContainsPlainText() const;
   bool ContainsCompatibleContent() const;
-  String AsURL(FilenameConversionPolicy filename_policy = kConvertFilenames,
-               String* title = nullptr) const;
-  String AsPlainText() const;
-  void AsFilePaths(Vector<String>&) const;
+  WTF::String AsURL(
+      FilenameConversionPolicy filename_policy = kConvertFilenames,
+      WTF::String* title = nullptr) const;
+  WTF::String AsPlainText() const;
+  void AsFilePaths(Vector<WTF::String>&) const;
   unsigned NumberOfFiles() const;
   DocumentFragment* AsFragment(LocalFrame*) const;
   bool CanSmartReplace() const;
@@ -74,7 +78,7 @@
   bool ForceDefaultAction() const;
   int GetModifiers() const;
 
-  String DroppedFileSystemId() const;
+  WTF::String DroppedFileSystemId() const;
 
  private:
   const gfx::PointF client_position_;
diff --git a/third_party/blink/renderer/core/page/focus_controller.cc b/third_party/blink/renderer/core/page/focus_controller.cc
index b0912183..f1b27fe7 100644
--- a/third_party/blink/renderer/core/page/focus_controller.cc
+++ b/third_party/blink/renderer/core/page/focus_controller.cc
@@ -68,6 +68,7 @@
 #include "third_party/blink/renderer/core/page/frame_tree.h"
 #include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/core/page/spatial_navigation.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 
 namespace blink {
 
@@ -1371,6 +1372,7 @@
 // https://html.spec.whatwg.org/C/#get-the-focusable-area
 Element* FocusController::FindFocusableElementInShadowHost(
     const Element& shadow_host) {
+  CHECK(!RuntimeEnabledFeatures::NewGetFocusableAreaBehaviorEnabled());
   // We have no behavior difference by focus trigger. Skip step 2.1.
 
   // 2.2. Otherwise, let possible focus delegates be the list of all
diff --git a/third_party/blink/renderer/core/page/page_popup_controller.h b/third_party/blink/renderer/core/page/page_popup_controller.h
index d663d7a..5d3a7a98 100644
--- a/third_party/blink/renderer/core/page/page_popup_controller.h
+++ b/third_party/blink/renderer/core/page/page_popup_controller.h
@@ -35,9 +35,12 @@
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/supplementable.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "ui/gfx/geometry/rect.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class CSSFontSelector;
@@ -56,15 +59,15 @@
 
   static PagePopupController* From(Page&);
 
-  void setValueAndClosePopup(int num_value, const String& string_value);
-  void setValue(const String&);
+  void setValueAndClosePopup(int num_value, const WTF::String& string_value);
+  void setValue(const WTF::String&);
   void closePopup();
-  String localizeNumberString(const String&);
-  String formatMonth(int year, int zero_base_month);
-  String formatShortMonth(int year, int zero_base_month);
-  String formatWeek(int year,
-                    int week_number,
-                    const String& localized_start_date);
+  WTF::String localizeNumberString(const WTF::String&);
+  WTF::String formatMonth(int year, int zero_base_month);
+  WTF::String formatShortMonth(int year, int zero_base_month);
+  WTF::String formatWeek(int year,
+                         int week_number,
+                         const WTF::String& localized_start_date);
   void ClearPagePopupClient();
   void setWindowRect(int x, int y, int width, int height);
 
diff --git a/third_party/blink/renderer/core/paint/clip_rect.h b/third_party/blink/renderer/core/paint/clip_rect.h
index 67ab7283..85e3a2b 100644
--- a/third_party/blink/renderer/core/paint/clip_rect.h
+++ b/third_party/blink/renderer/core/paint/clip_rect.h
@@ -30,6 +30,10 @@
 #include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class FloatClipRect;
@@ -81,7 +85,7 @@
 
   void Reset();
 
-  String ToString() const;
+  WTF::String ToString() const;
 
  private:
   void SetRectInternal(const FloatClipRect&);
diff --git a/third_party/blink/renderer/core/paint/document_marker_painter.cc b/third_party/blink/renderer/core/paint/document_marker_painter.cc
index 521e812f..38f2ffac 100644
--- a/third_party/blink/renderer/core/paint/document_marker_painter.cc
+++ b/third_party/blink/renderer/core/paint/document_marker_painter.cc
@@ -4,18 +4,12 @@
 
 #include "third_party/blink/renderer/core/paint/document_marker_painter.h"
 
-#include <algorithm>
-
 #include "build/build_config.h"
-#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
-#include "third_party/blink/renderer/core/highlight/highlight_style_utils.h"
+#include "third_party/blink/renderer/core/editing/markers/styleable_marker.h"
 #include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
-#include "third_party/blink/renderer/core/layout/layout_theme.h"
 #include "third_party/blink/renderer/core/paint/decoration_line_painter.h"
 #include "third_party/blink/renderer/core/paint/line_relative_rect.h"
 #include "third_party/blink/renderer/core/paint/paint_auto_dark_mode.h"
-#include "third_party/blink/renderer/core/paint/paint_info.h"
-#include "third_party/blink/renderer/core/paint/text_paint_style.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
 #include "third_party/blink/renderer/platform/geometry/layout_unit.h"
@@ -225,34 +219,4 @@
   }
 }
 
-TextPaintStyle DocumentMarkerPainter::ComputeTextPaintStyleFrom(
-    const Document& document,
-    Node* node,
-    const ComputedStyle& style,
-    const DocumentMarker& marker,
-    const PaintInfo& paint_info) {
-  Color text_color = style.VisitedDependentColor(GetCSSPropertyColor());
-  if (marker.GetType() == DocumentMarker::kTextMatch) {
-    const Color platform_text_color =
-        LayoutTheme::GetTheme().PlatformTextSearchColor(
-            To<TextMatchMarker>(marker).IsActiveMatch(),
-            style.UsedColorScheme(),
-            document.GetColorProviderForPainting(style.UsedColorScheme()));
-    if (platform_text_color == text_color)
-      return {};
-    text_color = platform_text_color;
-  }
-
-  TextPaintStyle text_style;
-  text_style.current_color = text_style.fill_color = text_style.stroke_color =
-      text_style.emphasis_mark_color = text_color;
-  text_style.stroke_width = style.TextStrokeWidth();
-  text_style.color_scheme = style.UsedColorScheme();
-  text_style.shadow = nullptr;
-  text_style.paint_order = style.PaintOrder();
-  if (marker.GetType() == DocumentMarker::kTextMatch)
-    return text_style;
-  return HighlightStyleUtils::HighlightPaintingStyle(
-      document, style, node, kPseudoIdTargetText, text_style, paint_info);
-}
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/document_marker_painter.h b/third_party/blink/renderer/core/paint/document_marker_painter.h
index 82767ef7..ec4afc0 100644
--- a/third_party/blink/renderer/core/paint/document_marker_painter.h
+++ b/third_party/blink/renderer/core/paint/document_marker_painter.h
@@ -5,8 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_DOCUMENT_MARKER_PAINTER_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_DOCUMENT_MARKER_PAINTER_H_
 
-#include "third_party/blink/renderer/core/editing/markers/document_marker.h"
-#include "third_party/blink/renderer/platform/graphics/color.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 
 namespace blink {
@@ -15,12 +13,9 @@
 class Document;
 class GraphicsContext;
 class LayoutUnit;
-class Node;
 class StyleableMarker;
 struct LineRelativeRect;
-struct PaintInfo;
 struct PhysicalOffset;
-struct TextPaintStyle;
 
 // Document marker painter for both LayoutNG and legacy layout.
 // This paints text decorations for spell/grammer check, find-in-page, and
@@ -37,11 +32,6 @@
                                             const LineRelativeRect& marker_rect,
                                             LayoutUnit logical_height,
                                             bool in_dark_mode);
-  static TextPaintStyle ComputeTextPaintStyleFrom(const Document& document,
-                                                  Node* node,
-                                                  const ComputedStyle& style,
-                                                  const DocumentMarker& marker,
-                                                  const PaintInfo& paint_info);
   static bool ShouldPaintMarkerUnderline(const StyleableMarker& marker);
 };
 
diff --git a/third_party/blink/renderer/core/paint/highlight_painter.cc b/third_party/blink/renderer/core/paint/highlight_painter.cc
index fce3da4..c8ca1af0 100644
--- a/third_party/blink/renderer/core/paint/highlight_painter.cc
+++ b/third_party/blink/renderer/core/paint/highlight_painter.cc
@@ -191,6 +191,34 @@
   return false;
 }
 
+TextPaintStyle TextPaintStyleForTextMatch(const TextMatchMarker& marker,
+                                          const ComputedStyle& style,
+                                          const Document& document,
+                                          bool ignore_current_color) {
+  const mojom::blink::ColorScheme color_scheme = style.UsedColorScheme();
+  const Color platform_text_color =
+      LayoutTheme::GetTheme().PlatformTextSearchColor(
+          marker.IsActiveMatch(), color_scheme,
+          document.GetColorProviderForPainting(color_scheme));
+  // Comparing against the value of the 'color' property doesn't always make
+  // sense (for example for SVG <text> which paints using 'fill' and 'stroke').
+  if (!ignore_current_color) {
+    const Color text_color = style.VisitedDependentColor(GetCSSPropertyColor());
+    if (platform_text_color == text_color) {
+      return {};
+    }
+  }
+
+  TextPaintStyle text_style;
+  text_style.current_color = text_style.fill_color = text_style.stroke_color =
+      text_style.emphasis_mark_color = platform_text_color;
+  text_style.stroke_width = style.TextStrokeWidth();
+  text_style.color_scheme = color_scheme;
+  text_style.shadow = nullptr;
+  text_style.paint_order = style.PaintOrder();
+  return text_style;
+}
+
 }  // namespace
 
 HighlightPainter::SelectionPaintState::SelectionPaintState(
@@ -482,27 +510,13 @@
           break;
         }
 
-        TextPaintStyle text_style;
+        const TextPaintStyle text_style =
+            TextPaintStyleForTextMatch(text_match_marker, originating_style_,
+                                       document, fragment_item_->IsSvgText());
         if (fragment_item_->IsSvgText()) {
-          // DocumentMarkerPainter::ComputeTextPaintStyleFrom() doesn't work
-          // well with SVG <text>, which doesn't apply 'color' CSS property.
-          const Color platform_matched_color =
-              LayoutTheme::GetTheme().PlatformTextSearchColor(
-                  text_match_marker.IsActiveMatch(),
-                  originating_style_.UsedColorScheme(),
-                  document.GetColorProviderForPainting(
-                      originating_style_.UsedColorScheme()));
           text_painter_.SetSvgState(
               *To<LayoutSVGInlineText>(fragment_item_->GetLayoutObject()),
-              originating_style_, platform_matched_color);
-          text_style.current_color = platform_matched_color;
-          text_style.stroke_width = originating_style_.TextStrokeWidth();
-          text_style.color_scheme = originating_style_.UsedColorScheme();
-          text_style.paint_order = originating_style_.PaintOrder();
-        } else {
-          text_style = DocumentMarkerPainter::ComputeTextPaintStyleFrom(
-              document, node_, originating_style_, text_match_marker,
-              paint_info_);
+              originating_style_, text_style.fill_color);
         }
         text_painter_.Paint(
             fragment_paint_info_.Slice(paint_start_offset, paint_end_offset),
diff --git a/third_party/blink/renderer/core/speech/speech_synthesis_base.h b/third_party/blink/renderer/core/speech/speech_synthesis_base.h
index 5aa18c5..ef36c5a 100644
--- a/third_party/blink/renderer/core/speech/speech_synthesis_base.h
+++ b/third_party/blink/renderer/core/speech/speech_synthesis_base.h
@@ -8,7 +8,10 @@
 #include "base/functional/callback.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -44,7 +47,7 @@
   static SpeechSynthesisBase* Create(LocalDOMWindow& window);
 
   // Overridden in speech_synthesis.cc.
-  virtual void Speak(const String& text, const String& lang) = 0;
+  virtual void Speak(const WTF::String& text, const WTF::String& lang) = 0;
   virtual void Cancel() = 0;
   virtual void Pause() = 0;
   virtual void Resume() = 0;
diff --git a/third_party/blink/renderer/core/style/style_crossfade_image.h b/third_party/blink/renderer/core/style/style_crossfade_image.h
index 21405949..771d02685 100644
--- a/third_party/blink/renderer/core/style/style_crossfade_image.h
+++ b/third_party/blink/renderer/core/style/style_crossfade_image.h
@@ -11,6 +11,10 @@
 #include "third_party/blink/renderer/platform/heap/member.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 namespace cssvalue {
@@ -32,7 +36,7 @@
   bool IsLoading() const override;
   bool IsLoaded() const override;
   bool ErrorOccurred() const override;
-  bool IsAccessAllowed(String&) const override;
+  bool IsAccessAllowed(WTF::String&) const override;
 
   IntrinsicSizingInfo GetNaturalSizingInfo(
       float multiplier,
diff --git a/third_party/blink/renderer/core/style/style_image.h b/third_party/blink/renderer/core/style/style_image.h
index 499afa9c..16f7fb99 100644
--- a/third_party/blink/renderer/core/style/style_image.h
+++ b/third_party/blink/renderer/core/style/style_image.h
@@ -34,6 +34,10 @@
 class SizeF;
 }  // namespace gfx
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class CSSValue;
@@ -86,7 +90,7 @@
   // Is the <image> considered same-origin? Can only be called if IsLoaded()
   // returns true. |failing_url| is set to the (potentially formatted) URL of
   // the first non-same-origin <image>.
-  virtual bool IsAccessAllowed(String& failing_url) const = 0;
+  virtual bool IsAccessAllowed(WTF::String& failing_url) const = 0;
 
   // Determine the natural dimensions (width, height, aspect ratio) of this
   // <image>, scaled by `multiplier`.
diff --git a/third_party/blink/renderer/core/style/style_mask_source_image.h b/third_party/blink/renderer/core/style/style_mask_source_image.h
index 4b1575d..052c7605 100644
--- a/third_party/blink/renderer/core/style/style_mask_source_image.h
+++ b/third_party/blink/renderer/core/style/style_mask_source_image.h
@@ -10,6 +10,10 @@
 #include "third_party/blink/renderer/platform/heap/member.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class CSSImageValue;
@@ -43,7 +47,7 @@
   bool IsLoaded() const override;
   bool IsLoading() const override;
   bool ErrorOccurred() const override;
-  bool IsAccessAllowed(String& failing_url) const override;
+  bool IsAccessAllowed(WTF::String& failing_url) const override;
 
   IntrinsicSizingInfo GetNaturalSizingInfo(
       float multiplier,
diff --git a/third_party/blink/renderer/core/svg/properties/svg_list_property.h b/third_party/blink/renderer/core/svg/properties/svg_list_property.h
index cae9813..38a5081 100644
--- a/third_party/blink/renderer/core/svg/properties/svg_list_property.h
+++ b/third_party/blink/renderer/core/svg/properties/svg_list_property.h
@@ -38,6 +38,10 @@
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 // Base class for properties that represent lists of other properties. Used to
@@ -71,7 +75,7 @@
   void Replace(uint32_t index, SVGListablePropertyBase* new_item);
 
  public:
-  String ValueAsString() const final;
+  WTF::String ValueAsString() const final;
 
   void Trace(Visitor* visitor) const final {
     visitor->Trace(values_);
diff --git a/third_party/blink/renderer/core/svg/properties/svg_list_property_helper.h b/third_party/blink/renderer/core/svg/properties/svg_list_property_helper.h
index 6241e92..dddb991 100644
--- a/third_party/blink/renderer/core/svg/properties/svg_list_property_helper.h
+++ b/third_party/blink/renderer/core/svg/properties/svg_list_property_helper.h
@@ -34,6 +34,10 @@
 #include "third_party/blink/renderer/core/svg/properties/svg_list_property.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 // Typed wrapper for SVG*List properties that adds type-dependent operations.
@@ -106,7 +110,7 @@
     return svg_list;
   }
 
-  SVGPropertyBase* CloneForAnimation(const String& value) const override {
+  SVGPropertyBase* CloneForAnimation(const WTF::String& value) const override {
     auto* property = MakeGarbageCollected<Derived>();
     property->SetValueAsString(value);
     return property;
diff --git a/third_party/blink/renderer/core/svg/properties/svg_property.h b/third_party/blink/renderer/core/svg/properties/svg_property.h
index 7a7955a0..4fd7a25 100644
--- a/third_party/blink/renderer/core/svg/properties/svg_property.h
+++ b/third_party/blink/renderer/core/svg/properties/svg_property.h
@@ -33,7 +33,10 @@
 
 #include "third_party/blink/renderer/core/svg/properties/svg_property_info.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -53,9 +56,9 @@
   // FIXME: remove this in WebAnimations transition.
   // This is used from SVGAnimatedNewPropertyAnimator for its animate-by-string
   // implementation.
-  virtual SVGPropertyBase* CloneForAnimation(const String&) const = 0;
+  virtual SVGPropertyBase* CloneForAnimation(const WTF::String&) const = 0;
 
-  virtual String ValueAsString() const = 0;
+  virtual WTF::String ValueAsString() const = 0;
 
   // Set the initial value based on a per-type defined (encoded) value. Overload
   // this in the specific subclass to handle initial values, and set
diff --git a/third_party/blink/renderer/core/svg/properties/svg_property_helper.h b/third_party/blink/renderer/core/svg/properties/svg_property_helper.h
index 0b9231e..6bf8ced 100644
--- a/third_party/blink/renderer/core/svg/properties/svg_property_helper.h
+++ b/third_party/blink/renderer/core/svg/properties/svg_property_helper.h
@@ -8,12 +8,16 @@
 #include "third_party/blink/renderer/core/svg/properties/svg_property.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 template <typename Derived>
 class SVGPropertyHelper : public SVGPropertyBase {
  public:
-  SVGPropertyBase* CloneForAnimation(const String& value) const override {
+  SVGPropertyBase* CloneForAnimation(const WTF::String& value) const override {
     auto* property = MakeGarbageCollected<Derived>();
     property->SetValueAsString(value);
     return property;
diff --git a/third_party/blink/renderer/core/svg/svg_enumeration_map.h b/third_party/blink/renderer/core/svg/svg_enumeration_map.h
index 3d918d1..ec040b17 100644
--- a/third_party/blink/renderer/core/svg/svg_enumeration_map.h
+++ b/third_party/blink/renderer/core/svg/svg_enumeration_map.h
@@ -8,7 +8,10 @@
 #include "base/check.h"
 #include "base/check_op.h"
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -44,7 +47,7 @@
     DCHECK_EQ(entries_[value - 1].value, value);
     return entries_[value - 1].name;
   }
-  uint16_t ValueFromName(const String&) const;
+  uint16_t ValueFromName(const WTF::String&) const;
 
   uint16_t ValueOfLast() const { return entries_[num_entries_ - 1].value; }
   uint16_t MaxExposedValue() const { return max_exposed_value_; }
diff --git a/third_party/blink/renderer/core/svg/svg_point.h b/third_party/blink/renderer/core/svg/svg_point.h
index 7c4c1963..edc419c 100644
--- a/third_party/blink/renderer/core/svg/svg_point.h
+++ b/third_party/blink/renderer/core/svg/svg_point.h
@@ -35,6 +35,10 @@
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 #include "ui/gfx/geometry/point_f.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class SVGPointTearOff;
@@ -47,7 +51,7 @@
   explicit SVGPoint(const gfx::PointF&);
 
   SVGPoint* Clone() const;
-  SVGPropertyBase* CloneForAnimation(const String&) const override;
+  SVGPropertyBase* CloneForAnimation(const WTF::String&) const override;
 
   const gfx::PointF& Value() const { return value_; }
   void SetValue(const gfx::PointF& value) { value_ = value; }
@@ -57,7 +61,7 @@
   void SetX(float f) { value_.set_x(f); }
   void SetY(float f) { value_.set_y(f); }
 
-  String ValueAsString() const override;
+  WTF::String ValueAsString() const override;
 
   void Add(const SVGPropertyBase*, const SVGElement*) override;
   void CalculateAnimatedValue(
diff --git a/third_party/blink/renderer/core/svg/svg_point_list.h b/third_party/blink/renderer/core/svg/svg_point_list.h
index dd5fd52..d691cfe9 100644
--- a/third_party/blink/renderer/core/svg/svg_point_list.h
+++ b/third_party/blink/renderer/core/svg/svg_point_list.h
@@ -36,6 +36,10 @@
 #include "third_party/blink/renderer/core/svg/svg_point.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class SVGPointListTearOff;
@@ -48,7 +52,7 @@
   SVGPointList();
   ~SVGPointList() override;
 
-  SVGParsingError SetValueAsString(const String&);
+  SVGParsingError SetValueAsString(const WTF::String&);
 
   // SVGPropertyBase:
   void Add(const SVGPropertyBase*, const SVGElement*) override;
diff --git a/third_party/blink/renderer/core/svg/svg_resource.h b/third_party/blink/renderer/core/svg/svg_resource.h
index 2b9a7d8..5555876 100644
--- a/third_party/blink/renderer/core/svg/svg_resource.h
+++ b/third_party/blink/renderer/core/svg/svg_resource.h
@@ -12,6 +12,10 @@
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class Document;
@@ -158,7 +162,7 @@
 
   // ResourceClient implementation
   void NotifyFinished(Resource*) override;
-  String DebugName() const override;
+  WTF::String DebugName() const override;
 
   Member<SVGResourceDocumentContent> document_content_;
   KURL url_;
@@ -183,7 +187,7 @@
 
   // ImageResourceObserver overrides
   void ImageNotifyFinished(ImageResourceContent*) override;
-  String DebugName() const override;
+  WTF::String DebugName() const override;
 
   Member<ImageResourceContent> image_content_;
   AtomicString fragment_;
diff --git a/third_party/blink/renderer/core/testing/internals.cc b/third_party/blink/renderer/core/testing/internals.cc
index 308ad08..66e54bb 100644
--- a/third_party/blink/renderer/core/testing/internals.cc
+++ b/third_party/blink/renderer/core/testing/internals.cc
@@ -3463,54 +3463,60 @@
       script_state, MakeGarbageCollected<AddOneFunction>()));
 }
 
-ScriptPromise Internals::promiseCheck(ScriptState* script_state,
-                                      int32_t arg1,
-                                      bool arg2,
-                                      const ScriptValue& arg3,
-                                      const String& arg4,
-                                      const Vector<String>& arg5,
-                                      ExceptionState& exception_state) {
-  if (arg2)
-    return ScriptPromise::Cast(script_state,
-                               V8String(script_state->GetIsolate(), "done"));
+ScriptPromiseTyped<IDLAny> Internals::promiseCheck(
+    ScriptState* script_state,
+    int32_t arg1,
+    bool arg2,
+    const ScriptValue& arg3,
+    const String& arg4,
+    const Vector<String>& arg5,
+    ExceptionState& exception_state) {
+  if (arg2) {
+    return ToResolvedPromise<IDLAny>(
+        script_state, V8String(script_state->GetIsolate(), "done"));
+  }
   exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
                                     "Thrown from the native implementation.");
-  return ScriptPromise();
+  return ScriptPromiseTyped<IDLAny>();
 }
 
-ScriptPromise Internals::promiseCheckWithoutExceptionState(
+ScriptPromiseTyped<IDLAny> Internals::promiseCheckWithoutExceptionState(
     ScriptState* script_state,
     const ScriptValue& arg1,
     const String& arg2,
     const Vector<String>& arg3) {
-  return ScriptPromise::Cast(script_state,
-                             V8String(script_state->GetIsolate(), "done"));
+  return ToResolvedPromise<IDLAny>(
+      script_state, V8String(script_state->GetIsolate(), "done"));
 }
 
-ScriptPromise Internals::promiseCheckRange(ScriptState* script_state,
-                                           int32_t arg1) {
-  return ScriptPromise::Cast(script_state,
-                             V8String(script_state->GetIsolate(), "done"));
+ScriptPromiseTyped<IDLAny> Internals::promiseCheckRange(
+    ScriptState* script_state,
+    int32_t arg1) {
+  return ToResolvedPromise<IDLAny>(
+      script_state, V8String(script_state->GetIsolate(), "done"));
 }
 
-ScriptPromise Internals::promiseCheckOverload(ScriptState* script_state,
-                                              Location*) {
-  return ScriptPromise::Cast(script_state,
-                             V8String(script_state->GetIsolate(), "done"));
+ScriptPromiseTyped<IDLAny> Internals::promiseCheckOverload(
+    ScriptState* script_state,
+    Location*) {
+  return ToResolvedPromise<IDLAny>(
+      script_state, V8String(script_state->GetIsolate(), "done"));
 }
 
-ScriptPromise Internals::promiseCheckOverload(ScriptState* script_state,
-                                              Document*) {
-  return ScriptPromise::Cast(script_state,
-                             V8String(script_state->GetIsolate(), "done"));
+ScriptPromiseTyped<IDLAny> Internals::promiseCheckOverload(
+    ScriptState* script_state,
+    Document*) {
+  return ToResolvedPromise<IDLAny>(
+      script_state, V8String(script_state->GetIsolate(), "done"));
 }
 
-ScriptPromise Internals::promiseCheckOverload(ScriptState* script_state,
-                                              Location*,
-                                              int32_t,
-                                              int32_t) {
-  return ScriptPromise::Cast(script_state,
-                             V8String(script_state->GetIsolate(), "done"));
+ScriptPromiseTyped<IDLAny> Internals::promiseCheckOverload(
+    ScriptState* script_state,
+    Location*,
+    int32_t,
+    int32_t) {
+  return ToResolvedPromise<IDLAny>(
+      script_state, V8String(script_state->GetIsolate(), "done"));
 }
 
 void Internals::Trace(Visitor* visitor) const {
diff --git a/third_party/blink/renderer/core/testing/internals.h b/third_party/blink/renderer/core/testing/internals.h
index a4eaf1db..f1b0205 100644
--- a/third_party/blink/renderer/core/testing/internals.h
+++ b/third_party/blink/renderer/core/testing/internals.h
@@ -481,21 +481,25 @@
   ScriptPromiseTyped<IDLAny> createResolvedPromise(ScriptState*, ScriptValue);
   ScriptPromise createRejectedPromise(ScriptState*, ScriptValue);
   ScriptPromise addOneToPromise(ScriptState*, ScriptPromise);
-  ScriptPromise promiseCheck(ScriptState*,
-                             int32_t,
-                             bool,
-                             const ScriptValue&,
-                             const String&,
-                             const Vector<String>&,
-                             ExceptionState&);
-  ScriptPromise promiseCheckWithoutExceptionState(ScriptState*,
-                                                  const ScriptValue&,
-                                                  const String&,
-                                                  const Vector<String>&);
-  ScriptPromise promiseCheckRange(ScriptState*, int32_t);
-  ScriptPromise promiseCheckOverload(ScriptState*, Location*);
-  ScriptPromise promiseCheckOverload(ScriptState*, Document*);
-  ScriptPromise promiseCheckOverload(ScriptState*, Location*, int32_t, int32_t);
+  ScriptPromiseTyped<IDLAny> promiseCheck(ScriptState*,
+                                          int32_t,
+                                          bool,
+                                          const ScriptValue&,
+                                          const String&,
+                                          const Vector<String>&,
+                                          ExceptionState&);
+  ScriptPromiseTyped<IDLAny> promiseCheckWithoutExceptionState(
+      ScriptState*,
+      const ScriptValue&,
+      const String&,
+      const Vector<String>&);
+  ScriptPromiseTyped<IDLAny> promiseCheckRange(ScriptState*, int32_t);
+  ScriptPromiseTyped<IDLAny> promiseCheckOverload(ScriptState*, Location*);
+  ScriptPromiseTyped<IDLAny> promiseCheckOverload(ScriptState*, Document*);
+  ScriptPromiseTyped<IDLAny> promiseCheckOverload(ScriptState*,
+                                                  Location*,
+                                                  int32_t,
+                                                  int32_t);
 
   void Trace(Visitor*) const override;
 
diff --git a/third_party/blink/renderer/core/testing/internals_get_named_cookie.h b/third_party/blink/renderer/core/testing/internals_get_named_cookie.h
index 3928a8d..6e34ea7 100644
--- a/third_party/blink/renderer/core/testing/internals_get_named_cookie.h
+++ b/third_party/blink/renderer/core/testing/internals_get_named_cookie.h
@@ -6,7 +6,10 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_INTERNALS_GET_NAMED_COOKIE_H_
 
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -20,7 +23,7 @@
  public:
   static ScriptPromise getNamedCookie(ScriptState* script_state,
                                       Internals& internals,
-                                      const String& name);
+                                      const WTF::String& name);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/xml/dom_parser.h b/third_party/blink/renderer/core/xml/dom_parser.h
index 7c4c4f0..c75378c 100644
--- a/third_party/blink/renderer/core/xml/dom_parser.h
+++ b/third_party/blink/renderer/core/xml/dom_parser.h
@@ -24,7 +24,10 @@
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/heap/member.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -43,8 +46,8 @@
 
   explicit DOMParser(ScriptState*);
 
-  Document* parseFromString(const String&,
-                            const String& type,
+  Document* parseFromString(const WTF::String&,
+                            const WTF::String& type,
                             const ParseFromStringOptions* options);
 
   void Trace(Visitor*) const override;
diff --git a/third_party/blink/renderer/core/xml/xml_serializer.h b/third_party/blink/renderer/core/xml/xml_serializer.h
index 1cdda9c..89f2811 100644
--- a/third_party/blink/renderer/core/xml/xml_serializer.h
+++ b/third_party/blink/renderer/core/xml/xml_serializer.h
@@ -24,6 +24,10 @@
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class Node;
@@ -38,7 +42,7 @@
 
   XMLSerializer() = default;
 
-  String serializeToString(Node*);
+  WTF::String serializeToString(Node*);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/xml/xpath_evaluator.h b/third_party/blink/renderer/core/xml/xpath_evaluator.h
index 2838779..10486cc 100644
--- a/third_party/blink/renderer/core/xml/xpath_evaluator.h
+++ b/third_party/blink/renderer/core/xml/xpath_evaluator.h
@@ -30,6 +30,10 @@
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class ExceptionState;
@@ -51,12 +55,12 @@
   XPathEvaluator() = default;
 
   XPathExpression* createExpression(ExecutionContext* execution_context,
-                                    const String& expression,
+                                    const WTF::String& expression,
                                     V8XPathNSResolver*,
                                     ExceptionState&);
   Node* createNSResolver(Node* node_resolver);
   XPathResult* evaluate(ExecutionContext* execustin_context,
-                        const String& expression,
+                        const WTF::String& expression,
                         Node* context_node,
                         V8XPathNSResolver*,
                         uint16_t type,
diff --git a/third_party/blink/renderer/core/xml/xpath_expression.h b/third_party/blink/renderer/core/xml/xpath_expression.h
index 2a76439..53138c9c 100644
--- a/third_party/blink/renderer/core/xml/xpath_expression.h
+++ b/third_party/blink/renderer/core/xml/xpath_expression.h
@@ -29,7 +29,10 @@
 
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/member.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -48,7 +51,7 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static XPathExpression* CreateExpression(const String& expression,
+  static XPathExpression* CreateExpression(const WTF::String& expression,
                                            V8XPathNSResolver*,
                                            ExecutionContext* execution_context,
                                            ExceptionState&);
diff --git a/third_party/blink/renderer/core/xml/xpath_util.h b/third_party/blink/renderer/core/xml/xpath_util.h
index 1f553af0..c8ba219 100644
--- a/third_party/blink/renderer/core/xml/xpath_util.h
+++ b/third_party/blink/renderer/core/xml/xpath_util.h
@@ -27,9 +27,12 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_XML_XPATH_UTIL_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_XML_XPATH_UTIL_H_
 
-#include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class Node;
@@ -41,7 +44,7 @@
 
 // @return the 'string-value' of the given node as specified by
 // http://www.w3.org/TR/xpath
-String StringValue(Node*);
+WTF::String StringValue(Node*);
 
 // @return whether the given node is a valid context node
 bool IsValidContextNode(Node*);
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h
index 6e3a33b..a10b104 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -68,7 +68,6 @@
 
 namespace ui {
 struct AXActionData;
-class AXNode;
 struct AXNodeData;
 struct AXRelativeBounds;
 }
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.h b/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.h
index 3309674..03c5fa4 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.h
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.h
@@ -9,6 +9,10 @@
 #include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class ExceptionState;
@@ -20,20 +24,21 @@
 
  public:
   // IDL exposed interface:
-  static String getService(const V8BluetoothServiceUUID* name,
-                           ExceptionState& exception_state);
-  static String getCharacteristic(const V8BluetoothCharacteristicUUID* name,
-                                  ExceptionState& exception_state);
-  static String getDescriptor(const V8BluetoothDescriptorUUID* name,
-                              ExceptionState& exception_state);
-  static String canonicalUUID(unsigned alias);
+  static WTF::String getService(const V8BluetoothServiceUUID* name,
+                                ExceptionState& exception_state);
+  static WTF::String getCharacteristic(
+      const V8BluetoothCharacteristicUUID* name,
+      ExceptionState& exception_state);
+  static WTF::String getDescriptor(const V8BluetoothDescriptorUUID* name,
+                                   ExceptionState& exception_state);
+  static WTF::String canonicalUUID(unsigned alias);
 };
 
 // Helper function to retrieve the UUID (as a string) from the V8 value.
 // The value may be a string or 16-bit unsigned integer. If the value cannot
 // be interpreted as a valid UUID then an empty string will be returned.
-BLINK_EXPORT String
-GetBluetoothUUIDFromV8Value(const V8UnionStringOrUnsignedLong* value);
+BLINK_EXPORT WTF::String GetBluetoothUUIDFromV8Value(
+    const V8UnionStringOrUnsignedLong* value);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/modules/cache_storage/cache_storage_trace_utils.h b/third_party/blink/renderer/modules/cache_storage/cache_storage_trace_utils.h
index cfdcef3..1a89714 100644
--- a/third_party/blink/renderer/modules/cache_storage/cache_storage_trace_utils.h
+++ b/third_party/blink/renderer/modules/cache_storage/cache_storage_trace_utils.h
@@ -13,6 +13,10 @@
 #include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom-blink-forward.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class TracedValue;
@@ -21,11 +25,11 @@
 // related value into something that can be passed to the TRACE_EVENT*
 // macros.
 //
-// Note, these are designed to use WTF::String, blink mojo types, and
+// Note, these are designed to use WTF::WTF::String, blink mojo types, and
 // blink::TracedValue.  Unforfortunately these types are not usable in
 // content, so these routines must be duplicated there as well.
 
-std::unique_ptr<TracedValue> CacheStorageTracedValue(const String& string);
+std::unique_ptr<TracedValue> CacheStorageTracedValue(const WTF::String& string);
 
 std::unique_ptr<TracedValue> CacheStorageTracedValue(
     const mojom::blink::FetchAPIRequestPtr& request);
@@ -51,7 +55,7 @@
     const mojom::blink::BatchOperationPtr& op);
 
 std::unique_ptr<TracedValue> CacheStorageTracedValue(
-    const WTF::Vector<String>& string_list);
+    const WTF::Vector<WTF::String>& string_list);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.h b/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.h
index c377b90..13bfc319 100644
--- a/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.h
+++ b/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.h
@@ -8,7 +8,10 @@
 #include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -26,7 +29,7 @@
  public:
   static V8RenderingContext* getContext(
       HTMLCanvasElement& canvas,
-      const String& context_id,
+      const WTF::String& context_id,
       const CanvasContextCreationAttributesModule* attributes,
       ExceptionState& exception_state);
   static OffscreenCanvas* transferControlToOffscreen(ScriptState*,
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc b/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc
index fd66e03..13e6ab07 100644
--- a/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc
+++ b/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc
@@ -384,9 +384,8 @@
   items.ReserveInitialCapacity(clipboard_item_data_.size());
 
   for (const auto& item : clipboard_item_data_) {
-    ScriptPromise promise = ScriptPromise::Cast(
-        script_state,
-        ToV8Traits<IDLNullable<Blob>>::ToV8(script_state, item.second));
+    ScriptPromise promise =
+        ToResolvedPromise<IDLNullable<Blob>>(script_state, item.second);
     items.emplace_back(item.first, promise);
   }
   HeapVector<Member<ClipboardItem>> clipboard_items = {
diff --git a/third_party/blink/renderer/modules/contacts_picker/contacts_manager.cc b/third_party/blink/renderer/modules/contacts_picker/contacts_manager.cc
index e4d781a5..d0d2a52 100644
--- a/third_party/blink/renderer/modules/contacts_picker/contacts_manager.cc
+++ b/third_party/blink/renderer/modules/contacts_picker/contacts_manager.cc
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_contact_info.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_contact_property.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/fileapi/blob.h"
@@ -90,16 +91,6 @@
 }  // namespace mojo
 
 namespace blink {
-namespace {
-
-// ContactProperty enum strings.
-constexpr char kAddress[] = "address";
-constexpr char kEmail[] = "email";
-constexpr char kName[] = "name";
-constexpr char kTel[] = "tel";
-constexpr char kIcon[] = "icon";
-
-}  // namespace
 
 // static
 const char ContactsManager::kSupplementName[] = "ContactsManager";
@@ -132,15 +123,18 @@
   return contacts_manager_.get();
 }
 
-const Vector<String>& ContactsManager::GetProperties(
+const Vector<V8ContactProperty>& ContactsManager::GetProperties(
     ScriptState* script_state) {
   if (properties_.empty()) {
-    properties_ = {kEmail, kName, kTel};
+    properties_ = {V8ContactProperty(V8ContactProperty::Enum::kEmail),
+                   V8ContactProperty(V8ContactProperty::Enum::kName),
+                   V8ContactProperty(V8ContactProperty::Enum::kTel)};
 
     if (RuntimeEnabledFeatures::ContactsManagerExtraPropertiesEnabled(
             ExecutionContext::From(script_state))) {
-      properties_.push_back(kAddress);
-      properties_.push_back(kIcon);
+      properties_.push_back(
+          V8ContactProperty(V8ContactProperty::Enum::kAddress));
+      properties_.push_back(V8ContactProperty(V8ContactProperty::Enum::kIcon));
     }
   }
   return properties_;
@@ -259,10 +253,10 @@
   resolver->Resolve(contacts_list);
 }
 
-ScriptPromise ContactsManager::getProperties(ScriptState* script_state) {
-  return ScriptPromise::Cast(script_state,
-                             ToV8Traits<IDLSequence<IDLString>>::ToV8(
-                                 script_state, GetProperties(script_state)));
+ScriptPromiseTyped<IDLSequence<V8ContactProperty>>
+ContactsManager::getProperties(ScriptState* script_state) {
+  return ToResolvedPromise<IDLSequence<V8ContactProperty>>(
+      script_state, GetProperties(script_state));
 }
 
 void ContactsManager::Trace(Visitor* visitor) const {
diff --git a/third_party/blink/renderer/modules/contacts_picker/contacts_manager.h b/third_party/blink/renderer/modules/contacts_picker/contacts_manager.h
index 3255b58..635c357f 100644
--- a/third_party/blink/renderer/modules/contacts_picker/contacts_manager.h
+++ b/third_party/blink/renderer/modules/contacts_picker/contacts_manager.h
@@ -22,6 +22,7 @@
 class ExceptionState;
 class Navigator;
 class ScriptState;
+class V8ContactProperty;
 
 // Represents an the ContactManager, providing access to Contacts.
 class ContactsManager final : public ScriptWrappable,
@@ -42,7 +43,8 @@
       const Vector<V8ContactProperty>& properties,
       ContactsSelectOptions* options,
       ExceptionState& exception_state);
-  ScriptPromise getProperties(ScriptState* script_state);
+  ScriptPromiseTyped<IDLSequence<V8ContactProperty>> getProperties(
+      ScriptState* script_state);
 
   void Trace(Visitor*) const override;
 
@@ -53,12 +55,12 @@
       ScriptPromiseResolverTyped<IDLSequence<ContactInfo>>* resolver,
       std::optional<Vector<mojom::blink::ContactInfoPtr>> contacts);
 
-  const Vector<String>& GetProperties(ScriptState* script_state);
+  const Vector<V8ContactProperty>& GetProperties(ScriptState* script_state);
 
   // Created lazily.
   HeapMojoRemote<mojom::blink::ContactsManager> contacts_manager_;
   bool contact_picker_in_use_ = false;
-  Vector<String> properties_;
+  Vector<V8ContactProperty> properties_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/cookie_deprecation_label/cookie_deprecation_label.cc b/third_party/blink/renderer/modules/cookie_deprecation_label/cookie_deprecation_label.cc
index a269685..f9ac74f 100644
--- a/third_party/blink/renderer/modules/cookie_deprecation_label/cookie_deprecation_label.cc
+++ b/third_party/blink/renderer/modules/cookie_deprecation_label/cookie_deprecation_label.cc
@@ -39,15 +39,15 @@
 
 CookieDeprecationLabel::~CookieDeprecationLabel() = default;
 
-ScriptPromise CookieDeprecationLabel::getValue(ScriptState* script_state) {
+ScriptPromiseTyped<IDLString> CookieDeprecationLabel::getValue(
+    ScriptState* script_state) {
   String label;
 
   if (auto* dom_window = GetSupplementable()->DomWindow()) {
     label = dom_window->document()->Loader()->GetCookieDeprecationLabel();
   }
 
-  return ScriptPromise::Cast(script_state,
-                             V8String(script_state->GetIsolate(), label));
+  return ToResolvedPromise<IDLString>(script_state, label);
 }
 
 void CookieDeprecationLabel::Trace(Visitor* visitor) const {
diff --git a/third_party/blink/renderer/modules/cookie_deprecation_label/cookie_deprecation_label.h b/third_party/blink/renderer/modules/cookie_deprecation_label/cookie_deprecation_label.h
index a186e945f..8cae1326 100644
--- a/third_party/blink/renderer/modules/cookie_deprecation_label/cookie_deprecation_label.h
+++ b/third_party/blink/renderer/modules/cookie_deprecation_label/cookie_deprecation_label.h
@@ -28,7 +28,7 @@
   ~CookieDeprecationLabel() override;
 
   // Web exposed function defined in the IDL file.
-  ScriptPromise getValue(ScriptState* script_state);
+  ScriptPromiseTyped<IDLString> getValue(ScriptState* script_state);
 
   void Trace(Visitor*) const override;
 };
diff --git a/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc b/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc
index f39e68ca..e4a37c7 100644
--- a/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc
+++ b/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc
@@ -186,9 +186,7 @@
   MediaCapabilitiesDecodingInfo* info = CreateDecodingInfoWith(value);
   media_capabilities_identifiability_metrics::ReportDecodingInfoResult(
       ExecutionContext::From(script_state), config, info);
-  return ScriptPromise::Cast(
-      script_state,
-      ToV8Traits<MediaCapabilitiesDecodingInfo>::ToV8(script_state, info));
+  return ToResolvedPromise<MediaCapabilitiesDecodingInfo>(script_state, info);
 }
 
 MediaCapabilitiesDecodingInfo* CreateEncryptedDecodingInfoWith(
@@ -946,9 +944,8 @@
           CreateEncryptedDecodingInfoWith(false, nullptr);
       media_capabilities_identifiability_metrics::ReportDecodingInfoResult(
           ExecutionContext::From(script_state), config, info);
-      return ScriptPromise::Cast(
-          script_state,
-          ToV8Traits<MediaCapabilitiesDecodingInfo>::ToV8(script_state, info));
+      return ToResolvedPromise<MediaCapabilitiesDecodingInfo>(script_state,
+                                                              info);
     }
   }
 
diff --git a/third_party/blink/renderer/modules/mediarecorder/track_recorder.h b/third_party/blink/renderer/modules/mediarecorder/track_recorder.h
index c1bbc866..0325823 100644
--- a/third_party/blink/renderer/modules/mediarecorder/track_recorder.h
+++ b/third_party/blink/renderer/modules/mediarecorder/track_recorder.h
@@ -9,6 +9,10 @@
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 // This class exists to give MediaRecorder support for behavior related to
@@ -52,7 +56,7 @@
 };
 
 MODULES_EXPORT MediaTrackContainerType
-GetMediaContainerTypeFromString(const String& type);
+GetMediaContainerTypeFromString(const WTF::String& type);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/modules/mediasource/url_media_source.h b/third_party/blink/renderer/modules/mediasource/url_media_source.h
index 02c6a69..5e333074 100644
--- a/third_party/blink/renderer/modules/mediasource/url_media_source.h
+++ b/third_party/blink/renderer/modules/mediasource/url_media_source.h
@@ -32,7 +32,10 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASOURCE_URL_MEDIA_SOURCE_H_
 
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -43,7 +46,7 @@
   STATIC_ONLY(URLMediaSource);
 
  public:
-  static String createObjectURL(ScriptState*, MediaSource*);
+  static WTF::String createObjectURL(ScriptState*, MediaSource*);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/permissions/testing/internals_permission.h b/third_party/blink/renderer/modules/permissions/testing/internals_permission.h
index 0c47d19e..4b1ed87 100644
--- a/third_party/blink/renderer/modules/permissions/testing/internals_permission.h
+++ b/third_party/blink/renderer/modules/permissions/testing/internals_permission.h
@@ -6,7 +6,10 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_PERMISSIONS_TESTING_INTERNALS_PERMISSION_H_
 
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -23,7 +26,7 @@
   static ScriptPromise setPermission(ScriptState*,
                                      Internals&,
                                      const ScriptValue&,
-                                     const String& state,
+                                     const WTF::String& state,
                                      ExceptionState&);
 };
 
diff --git a/third_party/blink/renderer/modules/private_attribution/private_attribution.h b/third_party/blink/renderer/modules/private_attribution/private_attribution.h
index 75f0af3..11d5f679 100644
--- a/third_party/blink/renderer/modules/private_attribution/private_attribution.h
+++ b/third_party/blink/renderer/modules/private_attribution/private_attribution.h
@@ -7,6 +7,10 @@
 
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class ExceptionState;
@@ -36,7 +40,7 @@
   ~PrivateAttribution() final = default;
 
   static ScriptPromise getEncryptedMatchKey(ScriptState*,
-                                            String report_collector,
+                                            WTF::String report_collector,
                                             PrivateAttributionOptions* options,
                                             ExceptionState& exception_state);
 
diff --git a/third_party/blink/renderer/modules/scheduler/dom_timer.h b/third_party/blink/renderer/modules/scheduler/dom_timer.h
index c730544..c2c5a030 100644
--- a/third_party/blink/renderer/modules/scheduler/dom_timer.h
+++ b/third_party/blink/renderer/modules/scheduler/dom_timer.h
@@ -38,6 +38,10 @@
 #include "third_party/blink/renderer/platform/timer.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class ExecutionContext;
@@ -60,7 +64,7 @@
                         const HeapVector<ScriptValue>& arguments);
   static int setTimeout(ScriptState*,
                         ExecutionContext&,
-                        const String& handler,
+                        const WTF::String& handler,
                         int timeout,
                         const HeapVector<ScriptValue>&);
   static int setInterval(ScriptState*,
@@ -70,7 +74,7 @@
                          const HeapVector<ScriptValue>&);
   static int setInterval(ScriptState*,
                          ExecutionContext&,
-                         const String& handler,
+                         const WTF::String& handler,
                          int timeout,
                          const HeapVector<ScriptValue>&);
   static void clearTimeout(ExecutionContext&, int timeout_id);
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_decoder.cc b/third_party/blink/renderer/modules/webcodecs/audio_decoder.cc
index d301828..94442bd 100644
--- a/third_party/blink/renderer/modules/webcodecs/audio_decoder.cc
+++ b/third_party/blink/renderer/modules/webcodecs/audio_decoder.cc
@@ -108,25 +108,23 @@
 }
 
 // static
-ScriptPromise AudioDecoder::isConfigSupported(ScriptState* script_state,
-                                              const AudioDecoderConfig* config,
-                                              ExceptionState& exception_state) {
+ScriptPromiseTyped<AudioDecoderSupport> AudioDecoder::isConfigSupported(
+    ScriptState* script_state,
+    const AudioDecoderConfig* config,
+    ExceptionState& exception_state) {
   String js_error_message;
   std::optional<media::AudioType> audio_type =
       IsValidAudioDecoderConfig(*config, &js_error_message);
 
   if (!audio_type) {
     exception_state.ThrowTypeError(js_error_message);
-    return ScriptPromise();
+    return ScriptPromiseTyped<AudioDecoderSupport>();
   }
 
   AudioDecoderSupport* support = AudioDecoderSupport::Create();
   support->setSupported(media::IsSupportedAudioType(*audio_type));
   support->setConfig(CopyConfig(*config));
-
-  return ScriptPromise::Cast(
-      script_state,
-      ToV8Traits<AudioDecoderSupport>::ToV8(script_state, support));
+  return ToResolvedPromise<AudioDecoderSupport>(script_state, support);
 }
 
 // static
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_decoder.h b/third_party/blink/renderer/modules/webcodecs/audio_decoder.h
index bc15950..7be2869 100644
--- a/third_party/blink/renderer/modules/webcodecs/audio_decoder.h
+++ b/third_party/blink/renderer/modules/webcodecs/audio_decoder.h
@@ -32,10 +32,10 @@
 
 class AudioData;
 class AudioDecoderConfig;
+class AudioDecoderSupport;
 class EncodedAudioChunk;
 class ExceptionState;
 class AudioDecoderInit;
-class ScriptPromise;
 class V8AudioDataOutputCallback;
 
 class MODULES_EXPORT AudioDecoderTraits {
@@ -75,9 +75,8 @@
                               const AudioDecoderInit*,
                               ExceptionState&);
 
-  static ScriptPromise isConfigSupported(ScriptState*,
-                                         const AudioDecoderConfig*,
-                                         ExceptionState&);
+  static ScriptPromiseTyped<AudioDecoderSupport>
+  isConfigSupported(ScriptState*, const AudioDecoderConfig*, ExceptionState&);
 
   // Returns parsed AudioType if the configuration is valid.
   static std::optional<media::AudioType> IsValidAudioDecoderConfig(
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc b/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc
index 3b3b20d..9e068516 100644
--- a/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc
+++ b/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc
@@ -612,13 +612,14 @@
 }
 
 // static
-ScriptPromise AudioEncoder::isConfigSupported(ScriptState* script_state,
-                                              const AudioEncoderConfig* config,
-                                              ExceptionState& exception_state) {
+ScriptPromiseTyped<AudioEncoderSupport> AudioEncoder::isConfigSupported(
+    ScriptState* script_state,
+    const AudioEncoderConfig* config,
+    ExceptionState& exception_state) {
   auto* parsed_config = ParseConfigStatic(config, exception_state);
   if (!parsed_config) {
     DCHECK(exception_state.HadException());
-    return ScriptPromise();
+    return ScriptPromiseTyped<AudioEncoderSupport>();
   }
 
   String unused_js_error_message;
@@ -626,10 +627,7 @@
   support->setSupported(
       VerifyCodecSupportStatic(parsed_config, &unused_js_error_message));
   support->setConfig(CopyConfig(*config));
-
-  return ScriptPromise::Cast(
-      script_state,
-      ToV8Traits<AudioEncoderSupport>::ToV8(script_state, support));
+  return ToResolvedPromise<AudioEncoderSupport>(script_state, support);
 }
 
 const AtomicString& AudioEncoder::InterfaceName() const {
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_encoder.h b/third_party/blink/renderer/modules/webcodecs/audio_encoder.h
index 91200a7..2d29fda 100644
--- a/third_party/blink/renderer/modules/webcodecs/audio_encoder.h
+++ b/third_party/blink/renderer/modules/webcodecs/audio_encoder.h
@@ -8,6 +8,7 @@
 #include "media/base/audio_codecs.h"
 #include "media/base/audio_encoder.h"
 #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_codec_state.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_audio_chunk_output_callback.h"
@@ -22,6 +23,7 @@
 class ExceptionState;
 class AudioEncoderConfig;
 class AudioEncoderInit;
+class AudioEncoderSupport;
 
 class MODULES_EXPORT AudioEncoderTraits {
  public:
@@ -68,9 +70,8 @@
   // EventTarget interface
   const AtomicString& InterfaceName() const override;
 
-  static ScriptPromise isConfigSupported(ScriptState*,
-                                         const AudioEncoderConfig*,
-                                         ExceptionState&);
+  static ScriptPromiseTyped<AudioEncoderSupport>
+  isConfigSupported(ScriptState*, const AudioEncoderConfig*, ExceptionState&);
 
  private:
   using Base = EncoderBase<AudioEncoderTraits>;
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder.cc b/third_party/blink/renderer/modules/webcodecs/video_decoder.cc
index 95d3c9d..788c4a3 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_decoder.cc
+++ b/third_party/blink/renderer/modules/webcodecs/video_decoder.cc
@@ -74,7 +74,7 @@
 void DecoderSupport_OnKnown(
     VideoDecoderSupport* support,
     std::unique_ptr<VideoDecoder::MediaConfigType> media_config,
-    ScriptPromiseResolver* resolver,
+    ScriptPromiseResolverTyped<VideoDecoderSupport>* resolver,
     media::GpuVideoAcceleratorFactories* gpu_factories) {
   if (!gpu_factories) {
     support->setSupported(false);
@@ -282,16 +282,17 @@
 }
 
 // static
-ScriptPromise VideoDecoder::isConfigSupported(ScriptState* script_state,
-                                              const VideoDecoderConfig* config,
-                                              ExceptionState& exception_state) {
+ScriptPromiseTyped<VideoDecoderSupport> VideoDecoder::isConfigSupported(
+    ScriptState* script_state,
+    const VideoDecoderConfig* config,
+    ExceptionState& exception_state) {
   // Run the "check if a config is a valid VideoDecoderConfig" algorithm.
   String js_error_message;
   std::optional<media::VideoType> video_type =
       IsValidVideoDecoderConfig(*config, &js_error_message /* out */);
   if (!video_type) {
     exception_state.ThrowTypeError(js_error_message);
-    return ScriptPromise();
+    return ScriptPromiseTyped<VideoDecoderSupport>();
   }
 
   // Run the "Clone Configuration" algorithm.
@@ -306,9 +307,7 @@
        !media::IsBuiltInVideoCodec(video_type->codec)) ||
       !media::IsSupportedVideoType(*video_type)) {
     support->setSupported(false);
-    return ScriptPromise::Cast(
-        script_state,
-        ToV8Traits<VideoDecoderSupport>::ToV8(script_state, support));
+    return ToResolvedPromise<VideoDecoderSupport>(script_state, support);
   }
 
   // Check that we can make a media::VideoDecoderConfig. The |js_error_message|
@@ -317,16 +316,15 @@
   media_config = MakeMediaVideoDecoderConfig(*config_copy, &js_error_message);
   if (!media_config) {
     support->setSupported(false);
-    return ScriptPromise::Cast(
-        script_state,
-        ToV8Traits<VideoDecoderSupport>::ToV8(script_state, support));
+    return ToResolvedPromise<VideoDecoderSupport>(script_state, support);
   }
 
   // If hardware is preferred, asynchronously check for a hardware decoder.
   if (hw_pref == HardwarePreference::kPreferHardware) {
-    auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(
-        script_state, exception_state.GetContext());
-    ScriptPromise promise = resolver->Promise();
+    auto* resolver =
+        MakeGarbageCollected<ScriptPromiseResolverTyped<VideoDecoderSupport>>(
+            script_state, exception_state.GetContext());
+    auto promise = resolver->Promise();
     RetrieveGpuFactoriesWithKnownDecoderSupport(CrossThreadBindOnce(
         &DecoderSupport_OnKnown, MakeUnwrappingCrossThreadHandle(support),
         std::make_unique<MediaConfigType>(*media_config),
@@ -336,9 +334,7 @@
 
   // Otherwise, the config is supported.
   support->setSupported(true);
-  return ScriptPromise::Cast(
-      script_state,
-      ToV8Traits<VideoDecoderSupport>::ToV8(script_state, support));
+  return ToResolvedPromise<VideoDecoderSupport>(script_state, support);
 }
 
 HardwarePreference VideoDecoder::GetHardwarePreference(
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder.h b/third_party/blink/renderer/modules/webcodecs/video_decoder.h
index 4cfd2a7..6284742 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_decoder.h
+++ b/third_party/blink/renderer/modules/webcodecs/video_decoder.h
@@ -40,9 +40,9 @@
 class ExceptionState;
 class VideoDecoderConfig;
 class VideoDecoderInit;
+class VideoDecoderSupport;
 class VideoFrame;
 class V8VideoFrameOutputCallback;
-class ScriptPromise;
 
 class MODULES_EXPORT VideoDecoderTraits {
  public:
@@ -81,9 +81,8 @@
                               const VideoDecoderInit*,
                               ExceptionState&);
 
-  static ScriptPromise isConfigSupported(ScriptState*,
-                                         const VideoDecoderConfig*,
-                                         ExceptionState&);
+  static ScriptPromiseTyped<VideoDecoderSupport>
+  isConfigSupported(ScriptState*, const VideoDecoderConfig*, ExceptionState&);
 
   static HardwarePreference GetHardwareAccelerationPreference(
       const ConfigType& config);
diff --git a/third_party/blink/renderer/modules/webdatabase/database_manager.h b/third_party/blink/renderer/modules/webdatabase/database_manager.h
index 0764e8f..56e84682 100644
--- a/third_party/blink/renderer/modules/webdatabase/database_manager.h
+++ b/third_party/blink/renderer/modules/webdatabase/database_manager.h
@@ -31,7 +31,10 @@
 #include "third_party/blink/renderer/modules/webdatabase/database_error.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -65,20 +68,20 @@
 #endif
 
   static void ThrowExceptionForDatabaseError(DatabaseError,
-                                             const String& error_message,
+                                             const WTF::String& error_message,
                                              ExceptionState&);
 
   Database* OpenDatabase(ExecutionContext*,
-                         const String& name,
-                         const String& expected_version,
-                         const String& display_name,
+                         const WTF::String& name,
+                         const WTF::String& expected_version,
+                         const WTF::String& display_name,
                          V8DatabaseCallback*,
                          DatabaseError&,
-                         String& error_message);
+                         WTF::String& error_message);
 
-  String FullPathForDatabase(const SecurityOrigin*,
-                             const String& name,
-                             bool create_if_does_not_exist = true);
+  WTF::String FullPathForDatabase(const SecurityOrigin*,
+                                  const WTF::String& name,
+                                  bool create_if_does_not_exist = true);
 
  private:
   DatabaseManager();
@@ -92,15 +95,15 @@
   DatabaseContext* ExistingDatabaseContextFor(ExecutionContext*);
 
   Database* OpenDatabaseInternal(ExecutionContext*,
-                                 const String& name,
-                                 const String& expected_version,
-                                 const String& display_name,
+                                 const WTF::String& name,
+                                 const WTF::String& expected_version,
+                                 const WTF::String& display_name,
                                  V8DatabaseCallback*,
                                  bool set_version_in_new_database,
                                  DatabaseError&,
-                                 String& error_message);
+                                 WTF::String& error_message);
 
-  static void LogErrorMessage(ExecutionContext*, const String& message);
+  static void LogErrorMessage(ExecutionContext*, const WTF::String& message);
 
   // context_map_ can have two or more entries even though we don't support
   // Web SQL on workers because single Blink process can have multiple main
diff --git a/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.h b/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.h
index e76bac3..84f9189 100644
--- a/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.h
+++ b/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.h
@@ -29,7 +29,10 @@
 
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -43,15 +46,15 @@
 
  public:
   static Database* openDatabase(LocalDOMWindow&,
-                                const String& name,
-                                const String& version,
-                                const String& display_name,
+                                const WTF::String& name,
+                                const WTF::String& version,
+                                const WTF::String& display_name,
                                 uint32_t estimated_size,
                                 ExceptionState&);
   static Database* openDatabase(LocalDOMWindow&,
-                                const String& name,
-                                const String& version,
-                                const String& display_name,
+                                const WTF::String& name,
+                                const WTF::String& version,
+                                const WTF::String& display_name,
                                 uint32_t estimated_size,
                                 V8DatabaseCallback* creation_callback,
                                 ExceptionState&);
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
index 0afa6b75..b32ea17 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
@@ -99,8 +99,6 @@
   };                                             \
   GetCurrentUnpackState(params)
 
-using WTF::String;
-
 namespace blink {
 
 namespace {
diff --git a/third_party/blink/renderer/modules/webgl/webgl_compressed_texture_astc.h b/third_party/blink/renderer/modules/webgl/webgl_compressed_texture_astc.h
index c42b617f..d262fb19 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_compressed_texture_astc.h
+++ b/third_party/blink/renderer/modules/webgl/webgl_compressed_texture_astc.h
@@ -7,6 +7,10 @@
 
 #include "third_party/blink/renderer/modules/webgl/webgl_extension.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class WebGLCompressedTextureASTC final : public WebGLExtension {
@@ -29,7 +33,7 @@
   WebGLExtensionName GetName() const override;
   static const BlockSizeCompressASTC kBlockSizeCompressASTC[];
 
-  Vector<String> getSupportedProfiles();
+  Vector<WTF::String> getSupportedProfiles();
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webgl/webgl_debug_shaders.h b/third_party/blink/renderer/modules/webgl/webgl_debug_shaders.h
index 45352c0..00f85b2 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_debug_shaders.h
+++ b/third_party/blink/renderer/modules/webgl/webgl_debug_shaders.h
@@ -28,6 +28,10 @@
 
 #include "third_party/blink/renderer/modules/webgl/webgl_extension.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class WebGLShader;
@@ -43,7 +47,7 @@
 
   WebGLExtensionName GetName() const override;
 
-  String getTranslatedShaderSource(WebGLShader*);
+  WTF::String getTranslatedShaderSource(WebGLShader*);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/external_texture_helper.cc b/third_party/blink/renderer/modules/webgpu/external_texture_helper.cc
index 734d01b..2a1f02f7 100644
--- a/third_party/blink/renderer/modules/webgpu/external_texture_helper.cc
+++ b/third_party/blink/renderer/modules/webgpu/external_texture_helper.cc
@@ -345,19 +345,30 @@
     video_renderer = local_video_renderer.get();
   }
 
-  // We don't need to specify a sync token since both CanvasResourceProvider and
-  // PaintCanvasVideoRenderer use the SharedGpuContext.
-  gpu::MailboxHolder dst_mailbox(
-      resource_provider->GetBackingMailboxForOverwrite(
-          MailboxSyncMode::kUnverifiedSyncToken),
-      gpu::SyncToken(), resource_provider->GetBackingTextureTarget());
+  // TODO(crbug.com/327270287): Expand CopyVideoFrameToSharedImage() ability to
+  // support all video frame valid formats. And remove draw path in that time.
+  if (media::IsYuvPlanar(media_video_frame->format())) {
+    // We don't need to specify a sync token since both CanvasResourceProvider
+    // and PaintCanvasVideoRenderer use the SharedGpuContext.
+    gpu::MailboxHolder dst_mailbox(
+        resource_provider->GetBackingMailboxForOverwrite(
+            MailboxSyncMode::kUnverifiedSyncToken),
+        gpu::SyncToken(), resource_provider->GetBackingTextureTarget());
 
-  // The returned sync token is from the SharedGpuContext - it's ok to drop it
-  // here since WebGPUMailboxTexture::FromCanvasResource will generate a new
-  // sync token from the SharedContextState and wait on it anyway.
-  std::ignore = video_renderer->CopyVideoFrameToSharedImage(
-      raster_context_provider, std::move(media_video_frame), dst_mailbox,
-      /*use_visible_rect=*/true);
+    // The returned sync token is from the SharedGpuContext - it's ok to drop it
+    // here since WebGPUMailboxTexture::FromCanvasResource will generate a new
+    // sync token from the SharedContextState and wait on it anyway.
+    std::ignore = video_renderer->CopyVideoFrameToSharedImage(
+        raster_context_provider, std::move(media_video_frame), dst_mailbox,
+        /*use_visible_rect=*/true);
+  } else {
+    const gfx::Rect dest_rect = media_video_frame->visible_rect();
+    if (!DrawVideoFrameIntoResourceProvider(
+            std::move(media_video_frame), resource_provider,
+            raster_context_provider, dest_rect, video_renderer)) {
+      return {};
+    }
+  }
 
   scoped_refptr<WebGPUMailboxTexture> mailbox_texture =
       WebGPUMailboxTexture::FromCanvasResource(
diff --git a/third_party/blink/renderer/modules/webmidi/midi_port.cc b/third_party/blink/renderer/modules/webmidi/midi_port.cc
index 2877b37..b3cc27da 100644
--- a/third_party/blink/renderer/modules/webmidi/midi_port.cc
+++ b/third_party/blink/renderer/modules/webmidi/midi_port.cc
@@ -89,11 +89,12 @@
   return V8MIDIPortType(type_);
 }
 
-ScriptPromise MIDIPort::open(ScriptState* script_state) {
+ScriptPromiseTyped<MIDIPort> MIDIPort::open(ScriptState* script_state) {
   if (connection_ == MIDIPortConnectionState::kOpen)
     return Accept(script_state);
 
-  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  auto* resolver =
+      MakeGarbageCollected<ScriptPromiseResolverTyped<MIDIPort>>(script_state);
   GetExecutionContext()
       ->GetTaskRunner(TaskType::kMiscPlatformAPI)
       ->PostTask(FROM_HERE,
@@ -113,11 +114,12 @@
   running_open_count_++;
 }
 
-ScriptPromise MIDIPort::close(ScriptState* script_state) {
+ScriptPromiseTyped<MIDIPort> MIDIPort::close(ScriptState* script_state) {
   if (connection_ == MIDIPortConnectionState::kClosed)
     return Accept(script_state);
 
-  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  auto* resolver =
+      MakeGarbageCollected<ScriptPromiseResolverTyped<MIDIPort>>(script_state);
   GetExecutionContext()
       ->GetTaskRunner(TaskType::kMiscPlatformAPI)
       ->PostTask(FROM_HERE,
@@ -183,7 +185,8 @@
   ExecutionContextLifecycleObserver::Trace(visitor);
 }
 
-void MIDIPort::OpenAsynchronously(ScriptPromiseResolver* resolver) {
+void MIDIPort::OpenAsynchronously(
+    ScriptPromiseResolverTyped<MIDIPort>* resolver) {
   // The frame should exist, but it may be already detached and the execution
   // context may be lost here.
   if (!GetExecutionContext())
@@ -211,7 +214,8 @@
     resolver->Resolve(this);
 }
 
-void MIDIPort::CloseAsynchronously(ScriptPromiseResolver* resolver) {
+void MIDIPort::CloseAsynchronously(
+    ScriptPromiseResolverTyped<MIDIPort>* resolver) {
   // The frame should exist, but it may be already detached and the execution
   // context may be lost here.
   if (!GetExecutionContext())
@@ -224,9 +228,8 @@
   resolver->Resolve(this);
 }
 
-ScriptPromise MIDIPort::Accept(ScriptState* script_state) {
-  return ScriptPromise::Cast(script_state,
-                             ToV8Traits<MIDIPort>::ToV8(script_state, this));
+ScriptPromiseTyped<MIDIPort> MIDIPort::Accept(ScriptState* script_state) {
+  return ToResolvedPromise<MIDIPort>(script_state, this);
 }
 
 void MIDIPort::SetStates(PortState state, MIDIPortConnectionState connection) {
diff --git a/third_party/blink/renderer/modules/webmidi/midi_port.h b/third_party/blink/renderer/modules/webmidi/midi_port.h
index e0acb93..54bf204 100644
--- a/third_party/blink/renderer/modules/webmidi/midi_port.h
+++ b/third_party/blink/renderer/modules/webmidi/midi_port.h
@@ -64,8 +64,8 @@
   V8MIDIPortType type() const;
   String version() const { return version_; }
 
-  ScriptPromise open(ScriptState*);
-  ScriptPromise close(ScriptState*);
+  ScriptPromiseTyped<MIDIPort> open(ScriptState*);
+  ScriptPromiseTyped<MIDIPort> close(ScriptState*);
 
   midi::mojom::PortState GetState() const { return state_; }
   void SetState(midi::mojom::PortState);
@@ -101,11 +101,11 @@
   MIDIAccess* midiAccess() const { return access_.Get(); }
 
  private:
-  void OpenAsynchronously(ScriptPromiseResolver*);
+  void OpenAsynchronously(ScriptPromiseResolverTyped<MIDIPort>*);
   virtual void DidOpen(bool opened) {}
-  void CloseAsynchronously(ScriptPromiseResolver*);
+  void CloseAsynchronously(ScriptPromiseResolverTyped<MIDIPort>*);
 
-  ScriptPromise Accept(ScriptState*);
+  ScriptPromiseTyped<MIDIPort> Accept(ScriptState*);
 
   void SetStates(midi::mojom::PortState, MIDIPortConnectionState);
 
diff --git a/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.h b/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.h
index 05edccfe..f67429d2 100644
--- a/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.h
+++ b/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.h
@@ -38,9 +38,12 @@
 #include "third_party/blink/public/web/web_pepper_socket_client.h"
 #include "third_party/blink/renderer/modules/websockets/websocket_channel_client.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class WebDocument;
@@ -64,15 +67,16 @@
 
   // WebSocketChannelClient methods proxied by
   // WebPepperSocketChannelClientProxy.
-  void DidConnect(const String& subprotocol, const String& extensions);
-  void DidReceiveTextMessage(const String& payload);
+  void DidConnect(const WTF::String& subprotocol,
+                  const WTF::String& extensions);
+  void DidReceiveTextMessage(const WTF::String& payload);
   void DidReceiveBinaryMessage(std::unique_ptr<Vector<char>> payload);
   void DidError();
   void DidConsumeBufferedAmount(uint64_t consumed);
   void DidStartClosingHandshake();
   void DidClose(WebSocketChannelClient::ClosingHandshakeCompletionStatus,
                 uint16_t code,
-                const String& reason);
+                const WTF::String& reason);
 
  private:
   Persistent<WebSocketChannel> private_;
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_client.h b/third_party/blink/renderer/modules/websockets/websocket_channel_client.h
index 07992169..e0359354 100644
--- a/third_party/blink/renderer/modules/websockets/websocket_channel_client.h
+++ b/third_party/blink/renderer/modules/websockets/websocket_channel_client.h
@@ -35,17 +35,20 @@
 #include "base/containers/span.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class MODULES_EXPORT WebSocketChannelClient : public GarbageCollectedMixin {
  public:
   virtual ~WebSocketChannelClient() = default;
-  virtual void DidConnect(const String& subprotocol, const String& extensions) {
-  }
-  virtual void DidReceiveTextMessage(const String&) {}
+  virtual void DidConnect(const WTF::String& subprotocol,
+                          const WTF::String& extensions) {}
+  virtual void DidReceiveTextMessage(const WTF::String&) {}
   virtual void DidReceiveBinaryMessage(
       const Vector<base::span<const char>>& data) {}
   virtual void DidError() {}
@@ -57,7 +60,7 @@
   };
   virtual void DidClose(ClosingHandshakeCompletionStatus,
                         uint16_t /* code */,
-                        const String& /* reason */) {}
+                        const WTF::String& /* reason */) {}
   void Trace(Visitor* visitor) const override {}
 
  protected:
diff --git a/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h b/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h
index a906aa9..d956ca1d 100644
--- a/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h
+++ b/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h
@@ -46,6 +46,10 @@
 class UnguessableToken;
 }  // namespace base
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class DOMDataStore;
@@ -157,11 +161,12 @@
 
   static DOMWrapperWorld& MainWorld(v8::Isolate* isolate);
 
-  static void SetNonMainWorldStableId(int32_t world_id, const String&);
-  String NonMainWorldStableId() const;
+  static void SetNonMainWorldStableId(int32_t world_id, const WTF::String&);
+  WTF::String NonMainWorldStableId() const;
 
-  static void SetNonMainWorldHumanReadableName(int32_t world_id, const String&);
-  String NonMainWorldHumanReadableName() const;
+  static void SetNonMainWorldHumanReadableName(int32_t world_id,
+                                               const WTF::String&);
+  WTF::String NonMainWorldHumanReadableName() const;
 
   // Associates an isolated world (see above for description) with a security
   // origin. XMLHttpRequest instances used in that world will be considered
diff --git a/third_party/blink/renderer/platform/bindings/runtime_call_stats.h b/third_party/blink/renderer/platform/bindings/runtime_call_stats.h
index 03f2e5d..4d76b70 100644
--- a/third_party/blink/renderer/platform/bindings/runtime_call_stats.h
+++ b/third_party/blink/renderer/platform/bindings/runtime_call_stats.h
@@ -33,6 +33,10 @@
 class TickClock;
 }
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class TracedValue;
@@ -321,7 +325,7 @@
     return &(counters_[static_cast<uint16_t>(id)]);
   }
 
-  String ToString() const;
+  WTF::String ToString() const;
 
   static void SetRuntimeCallStatsForTesting();
   static void ClearRuntimeCallStatsForTesting();
diff --git a/third_party/blink/renderer/platform/bindings/thread_debugger.h b/third_party/blink/renderer/platform/bindings/thread_debugger.h
index 0a5f972..9e2faa3 100644
--- a/third_party/blink/renderer/platform/bindings/thread_debugger.h
+++ b/third_party/blink/renderer/platform/bindings/thread_debugger.h
@@ -13,6 +13,10 @@
 #include "v8/include/v8-forward.h"
 #include "v8/include/v8-inspector.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class SourceLocation;
@@ -42,7 +46,7 @@
   virtual void AsyncTaskStarted(void* task) = 0;
   virtual void AsyncTaskFinished(void* task) = 0;
   virtual unsigned PromiseRejected(v8::Local<v8::Context>,
-                                   const String& error_message,
+                                   const WTF::String& error_message,
                                    v8::Local<v8::Value> exception,
                                    std::unique_ptr<SourceLocation>) = 0;
   virtual void PromiseRejectionRevoked(v8::Local<v8::Context>,
diff --git a/third_party/blink/renderer/platform/blob/blob_url.h b/third_party/blink/renderer/platform/blob/blob_url.h
index ff76da3..7734a12 100644
--- a/third_party/blink/renderer/platform/blob/blob_url.h
+++ b/third_party/blink/renderer/platform/blob/blob_url.h
@@ -33,7 +33,10 @@
 
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -52,10 +55,10 @@
 
  public:
   static KURL CreatePublicURL(const SecurityOrigin*);
-  static String GetOrigin(const KURL&);
+  static WTF::String GetOrigin(const KURL&);
 
  private:
-  static KURL CreateBlobURL(const String& origin_string);
+  static KURL CreateBlobURL(const WTF::String& origin_string);
   static const char kBlobProtocol[];
 };
 
diff --git a/third_party/blink/renderer/platform/fonts/font_smoothing_mode.h b/third_party/blink/renderer/platform/fonts/font_smoothing_mode.h
index e56d307..ba158cd99 100644
--- a/third_party/blink/renderer/platform/fonts/font_smoothing_mode.h
+++ b/third_party/blink/renderer/platform/fonts/font_smoothing_mode.h
@@ -27,7 +27,10 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_SMOOTHING_MODE_H_
 
 #include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -38,7 +41,7 @@
   kSubpixelAntialiased
 };
 
-PLATFORM_EXPORT String ToString(FontSmoothingMode);
+PLATFORM_EXPORT WTF::String ToString(FontSmoothingMode);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/platform/fonts/font_variant_east_asian.h b/third_party/blink/renderer/platform/fonts/font_variant_east_asian.h
index 3e00325..a677f85 100644
--- a/third_party/blink/renderer/platform/fonts/font_variant_east_asian.h
+++ b/third_party/blink/renderer/platform/fonts/font_variant_east_asian.h
@@ -6,7 +6,10 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_VARIANT_EAST_ASIAN_H_
 
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -24,7 +27,7 @@
     kTraditional
     // Ensure |BitFields| has enough bits when adding values.
   };
-  static String ToString(EastAsianForm);
+  static WTF::String ToString(EastAsianForm);
 
   enum EastAsianWidth {
     kNormalWidth,
@@ -32,7 +35,7 @@
     kProportionalWidth
     // Ensure |BitFields| has enough bits when adding values.
   };
-  static String ToString(EastAsianWidth);
+  static WTF::String ToString(EastAsianWidth);
 
   FontVariantEastAsian() : fields_as_unsigned_(0) {}
 
@@ -58,7 +61,7 @@
     return fields_as_unsigned_ == other.fields_as_unsigned_;
   }
 
-  String ToString() const;
+  WTF::String ToString() const;
 
  private:
   FontVariantEastAsian(unsigned init_value) : fields_as_unsigned_(init_value) {}
diff --git a/third_party/blink/renderer/platform/fonts/font_variant_numeric.h b/third_party/blink/renderer/platform/fonts/font_variant_numeric.h
index 1eada3a..612f0f6f 100644
--- a/third_party/blink/renderer/platform/fonts/font_variant_numeric.h
+++ b/third_party/blink/renderer/platform/fonts/font_variant_numeric.h
@@ -6,7 +6,10 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_VARIANT_NUMERIC_H_
 
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -15,23 +18,23 @@
 
  public:
   enum NumericFigure { kNormalFigure = 0, kLiningNums, kOldstyleNums };
-  static String ToString(NumericFigure);
+  static WTF::String ToString(NumericFigure);
 
   enum NumericSpacing { kNormalSpacing = 0, kProportionalNums, kTabularNums };
-  static String ToString(NumericSpacing);
+  static WTF::String ToString(NumericSpacing);
 
   enum NumericFraction {
     kNormalFraction = 0,
     kDiagonalFractions,
     kStackedFractions
   };
-  static String ToString(NumericFraction);
+  static WTF::String ToString(NumericFraction);
 
   enum Ordinal { kOrdinalOff = 0, kOrdinalOn };
-  static String ToString(Ordinal);
+  static WTF::String ToString(Ordinal);
 
   enum SlashedZero { kSlashedZeroOff = 0, kSlashedZeroOn };
-  static String ToString(SlashedZero);
+  static WTF::String ToString(SlashedZero);
 
   FontVariantNumeric() : fields_as_unsigned_(0) {}
 
@@ -75,7 +78,7 @@
     return fields_as_unsigned_ == other.fields_as_unsigned_;
   }
 
-  String ToString() const;
+  WTF::String ToString() const;
 
  private:
   FontVariantNumeric(unsigned init_value) : fields_as_unsigned_(init_value) {}
diff --git a/third_party/blink/renderer/platform/fonts/font_width_variant.h b/third_party/blink/renderer/platform/fonts/font_width_variant.h
index 524da14..6c2bf3f 100644
--- a/third_party/blink/renderer/platform/fonts/font_width_variant.h
+++ b/third_party/blink/renderer/platform/fonts/font_width_variant.h
@@ -27,7 +27,10 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_WIDTH_VARIANT_H_
 
 #include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -44,7 +47,7 @@
 static_assert(kLastFontWidthVariant >> kFontWidthVariantWidth == 0,
               "FontWidthVariantWidth must be correct");
 
-PLATFORM_EXPORT String ToString(FontWidthVariant);
+PLATFORM_EXPORT WTF::String ToString(FontWidthVariant);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/platform/fonts/shaping/text_auto_space.h b/third_party/blink/renderer/platform/fonts/shaping/text_auto_space.h
index ef5c010..2232794 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/text_auto_space.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/text_auto_space.h
@@ -10,7 +10,11 @@
 
 #include "base/memory/stack_allocated.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -27,9 +31,9 @@
   static CharType GetType(UChar32 ch);
 
   // `GetType` and advance the `offset` by one character (grapheme cluster.)
-  static CharType GetTypeAndNext(const String& text, wtf_size_t& offset);
+  static CharType GetTypeAndNext(const WTF::String& text, wtf_size_t& offset);
   // `GetType` of the character before `offset`.
-  static CharType GetPrevType(const String& text, wtf_size_t offset);
+  static CharType GetPrevType(const WTF::String& text, wtf_size_t offset);
 
   // `CharType::kIdeograph` is `USCRIPT_HAN`, except characters in this range
   // may be other scripts.
diff --git a/third_party/blink/renderer/platform/fonts/string_truncator.h b/third_party/blink/renderer/platform/fonts/string_truncator.h
index fc5fa490..89e4e68 100644
--- a/third_party/blink/renderer/platform/fonts/string_truncator.h
+++ b/third_party/blink/renderer/platform/fonts/string_truncator.h
@@ -31,7 +31,10 @@
 
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -41,8 +44,12 @@
   STATIC_ONLY(StringTruncator);
 
  public:
-  static String CenterTruncate(const String&, float max_width, const Font&);
-  static String RightTruncate(const String&, float max_width, const Font&);
+  static WTF::String CenterTruncate(const WTF::String&,
+                                    float max_width,
+                                    const Font&);
+  static WTF::String RightTruncate(const WTF::String&,
+                                   float max_width,
+                                   const Font&);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/fonts/text_rendering_mode.h b/third_party/blink/renderer/platform/fonts/text_rendering_mode.h
index aa5bd59..45e04c1 100644
--- a/third_party/blink/renderer/platform/fonts/text_rendering_mode.h
+++ b/third_party/blink/renderer/platform/fonts/text_rendering_mode.h
@@ -27,7 +27,10 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_TEXT_RENDERING_MODE_H_
 
 #include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -38,8 +41,8 @@
   kGeometricPrecision
 };
 
-PLATFORM_EXPORT String ToString(TextRenderingMode);
-PLATFORM_EXPORT String ToStringForIdl(TextRenderingMode);
+PLATFORM_EXPORT WTF::String ToString(TextRenderingMode);
+PLATFORM_EXPORT WTF::String ToStringForIdl(TextRenderingMode);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/platform/fonts/typesetting_features.h b/third_party/blink/renderer/platform/fonts/typesetting_features.h
index 8a31e01..c095bc6 100644
--- a/third_party/blink/renderer/platform/fonts/typesetting_features.h
+++ b/third_party/blink/renderer/platform/fonts/typesetting_features.h
@@ -27,7 +27,10 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_TYPESETTING_FEATURES_H_
 
 #include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -42,7 +45,7 @@
 
 typedef unsigned TypesettingFeatures;
 
-PLATFORM_EXPORT String ToString(TypesettingFeatures);
+PLATFORM_EXPORT WTF::String ToString(TypesettingFeatures);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/platform/geometry/layout_point.h b/third_party/blink/renderer/platform/geometry/layout_point.h
index 55bdd1f6..110e663 100644
--- a/third_party/blink/renderer/platform/geometry/layout_point.h
+++ b/third_party/blink/renderer/platform/geometry/layout_point.h
@@ -39,6 +39,10 @@
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/geometry/vector2d.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class PLATFORM_EXPORT LayoutPoint {
@@ -66,7 +70,7 @@
   void SetX(LayoutUnit x) { x_ = x; }
   void SetY(LayoutUnit y) { y_ = y; }
 
-  String ToString() const;
+  WTF::String ToString() const;
 
  private:
   LayoutUnit x_, y_;
diff --git a/third_party/blink/renderer/platform/geometry/layout_rect.h b/third_party/blink/renderer/platform/geometry/layout_rect.h
index 41262fb..e860017 100644
--- a/third_party/blink/renderer/platform/geometry/layout_rect.h
+++ b/third_party/blink/renderer/platform/geometry/layout_rect.h
@@ -39,6 +39,10 @@
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "ui/gfx/geometry/rect.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 // This class is deprecated. Use PhysicalRect or LogicalRect instead.
@@ -69,7 +73,7 @@
   constexpr LayoutUnit Width() const { return size_.Width(); }
   constexpr LayoutUnit Height() const { return size_.Height(); }
 
-  String ToString() const;
+  WTF::String ToString() const;
 
  private:
   LayoutPoint location_;
diff --git a/third_party/blink/renderer/platform/geometry/layout_size.h b/third_party/blink/renderer/platform/geometry/layout_size.h
index 1eb57d2..a511f4a 100644
--- a/third_party/blink/renderer/platform/geometry/layout_size.h
+++ b/third_party/blink/renderer/platform/geometry/layout_size.h
@@ -34,10 +34,13 @@
 #include <iosfwd>
 #include "third_party/blink/renderer/platform/geometry/layout_unit.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/geometry/size_f.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 // This class is deprecated.  Use PhysicalSize, gfx::Size, gfx::SizeF or
@@ -65,7 +68,7 @@
   constexpr LayoutUnit Width() const { return width_; }
   constexpr LayoutUnit Height() const { return height_; }
 
-  String ToString() const;
+  WTF::String ToString() const;
 
  private:
   LayoutUnit width_, height_;
diff --git a/third_party/blink/renderer/platform/geometry/layout_unit.h b/third_party/blink/renderer/platform/geometry/layout_unit.h
index 8b54403..6e9e923b 100644
--- a/third_party/blink/renderer/platform/geometry/layout_unit.h
+++ b/third_party/blink/renderer/platform/geometry/layout_unit.h
@@ -47,6 +47,10 @@
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/vector_traits.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 #if DCHECK_IS_ON()
@@ -298,7 +302,7 @@
   // regular operations (i.e the result of the divide is rounded towards zero).
   LayoutUnit MulDiv(LayoutUnit m, LayoutUnit d) const;
 
-  String ToString() const;
+  WTF::String ToString() const;
 
  private:
   static bool IsInBounds(int value) {
diff --git a/third_party/blink/renderer/platform/geometry/length.h b/third_party/blink/renderer/platform/geometry/length.h
index 2f9b344..9e76e548 100644
--- a/third_party/blink/renderer/platform/geometry/length.h
+++ b/third_party/blink/renderer/platform/geometry/length.h
@@ -36,6 +36,10 @@
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 struct PixelsAndPercent {
@@ -439,7 +443,7 @@
 
   Length Zoom(double factor) const;
 
-  String ToString() const;
+  WTF::String ToString() const;
 
  private:
   Length BlendMixedTypes(const Length& from, double progress, ValueRange) const;
diff --git a/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h b/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h
index 91206c3..df3c3fda 100644
--- a/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h
+++ b/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h
@@ -7,7 +7,10 @@
 
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -34,19 +37,19 @@
   };
 
   // |type| is the return value of ImageDecoder::FilenameExtension().
-  static DecodedImageType StringToDecodedImageType(const String& type);
+  static DecodedImageType StringToDecodedImageType(const WTF::String& type);
 
   // |type| is the return value of ImageDecoder::FilenameExtension().
-  static void CountDecodedImageType(const String& type);
+  static void CountDecodedImageType(const WTF::String& type);
   // |type| is the return value of ImageDecoder::FilenameExtension().
   // |use_counter| may be a null pointer.
-  static void CountDecodedImageType(const String& type,
+  static void CountDecodedImageType(const WTF::String& type,
                                     UseCounter* use_counter);
   // Report the image compression density in 0.01 bits per pixel for an image
   // with a smallest side (width or length) of |image_min_side| and total size
   // in bytes |image_size_bytes|. Only certain image types and minimum image
   // size are reported.
-  static void CountDecodedImageDensity(const String& type,
+  static void CountDecodedImageDensity(const WTF::String& type,
                                        int image_min_side,
                                        uint64_t density_centi_bpp,
                                        size_t image_size_bytes);
diff --git a/third_party/blink/renderer/platform/graphics/canvas_color_params.h b/third_party/blink/renderer/platform/graphics/canvas_color_params.h
index 4bd20c2..c72e582 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_color_params.h
+++ b/third_party/blink/renderer/platform/graphics/canvas_color_params.h
@@ -16,6 +16,10 @@
 class ColorSpace;
 }
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 // Return the gfx::ColorSpace for the specified `predefined_color_space`.
@@ -47,8 +51,8 @@
   CanvasPixelFormat PixelFormat() const { return pixel_format_; }
   OpacityMode GetOpacityMode() const { return opacity_mode_; }
 
-  String GetColorSpaceAsString() const;
-  String GetPixelFormatAsString() const;
+  WTF::String GetColorSpaceAsString() const;
+  WTF::String GetPixelFormatAsString() const;
 
   SkColorInfo GetSkColorInfo() const;
 
diff --git a/third_party/blink/renderer/platform/graphics/color.h b/third_party/blink/renderer/platform/graphics/color.h
index 29f0295..301bd07 100644
--- a/third_party/blink/renderer/platform/graphics/color.h
+++ b/third_party/blink/renderer/platform/graphics/color.h
@@ -38,6 +38,10 @@
 #include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h"
 #include "third_party/skia/include/core/SkColor.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 typedef unsigned RGBA32;  // RGBA quadruplet
@@ -268,28 +272,28 @@
   // them.
   static bool IsBakedGamutMappingEnabled();
 
-  String SerializeInternal() const;
+  WTF::String SerializeInternal() const;
   // Returns the color serialized according to HTML5:
   // http://www.whatwg.org/specs/web-apps/current-work/#serialization-of-a-color
-  String SerializeAsCSSColor() const;
+  WTF::String SerializeAsCSSColor() const;
   // Canvas colors are serialized somewhat differently:
   // https://html.spec.whatwg.org/multipage/canvas.html#serialisation-of-a-color
-  String SerializeAsCanvasColor() const;
+  WTF::String SerializeAsCanvasColor() const;
   // For appending color interpolation spaces and hue interpolation methods to
   // the serialization of gradients and color-mix functions.
-  static String SerializeInterpolationSpace(
+  static WTF::String SerializeInterpolationSpace(
       Color::ColorSpace color_space,
       Color::HueInterpolationMethod hue_interpolation_method =
           Color::HueInterpolationMethod::kShorter);
 
   // Returns the color serialized as either #RRGGBB or #RRGGBBAA. The latter
   // format is not a valid CSS color, and should only be seen in DRT dumps.
-  String NameForLayoutTreeAsText() const;
+  WTF::String NameForLayoutTreeAsText() const;
 
   // Returns whether parsing succeeded. The resulting Color is arbitrary
   // if parsing fails.
-  bool SetFromString(const String&);
-  bool SetNamedColor(const String&);
+  bool SetFromString(const WTF::String&);
+  bool SetNamedColor(const WTF::String&);
 
   bool IsFullyTransparent() const { return Alpha() <= 0.0f; }
   bool IsOpaque() const { return Alpha() >= 1.0f; }
@@ -393,7 +397,7 @@
   FRIEND_TEST_ALL_PREFIXES(BlinkColor, SubstituteMissingParameters);
 
  private:
-  String SerializeLegacyColorAsCSSColor() const;
+  WTF::String SerializeLegacyColorAsCSSColor() const;
   constexpr explicit Color(RGBA32 color)
       : param0_is_none_(0),
         param1_is_none_(0),
@@ -423,7 +427,7 @@
   SkColor4f ToSkColor4fInternal(bool gamut_map_oklab_oklch) const;
 
   // For testing purposes and for serializer.
-  static String ColorSpaceToString(Color::ColorSpace color_space);
+  static WTF::String ColorSpaceToString(Color::ColorSpace color_space);
 
   float PremultiplyColor();
   void UnpremultiplyColor();
diff --git a/third_party/blink/renderer/platform/graphics/graphics_types.h b/third_party/blink/renderer/platform/graphics/graphics_types.h
index 543c925b..74fc5d7 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_types.h
+++ b/third_party/blink/renderer/platform/graphics/graphics_types.h
@@ -28,10 +28,13 @@
 
 #include "cc/paint/paint_flags.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/skia/include/core/SkPaint.h"
 #include "third_party/skia/include/core/SkPath.h"
 
+namespace WTF {
+class String;
+}
+
 namespace blink {
 
 typedef uintptr_t DisplayItemClientId;
@@ -356,35 +359,35 @@
 // Note that this is only appropriate to use in canvas globalCompositeOperator
 // cases.
 // TODO(vmpstr): Move these functions to near where they are used.
-PLATFORM_EXPORT String CanvasCompositeOperatorName(CompositeOperator,
-                                                   BlendMode);
-PLATFORM_EXPORT bool ParseCanvasCompositeAndBlendMode(const String&,
+PLATFORM_EXPORT WTF::String CanvasCompositeOperatorName(CompositeOperator,
+                                                        BlendMode);
+PLATFORM_EXPORT bool ParseCanvasCompositeAndBlendMode(const WTF::String&,
                                                       CompositeOperator&,
                                                       BlendMode&);
 
-PLATFORM_EXPORT String BlendModeToString(BlendMode);
+PLATFORM_EXPORT WTF::String BlendModeToString(BlendMode);
 
-PLATFORM_EXPORT String ImageEncodingMimeTypeName(ImageEncodingMimeType);
-PLATFORM_EXPORT bool ParseImageEncodingMimeType(const String&,
+PLATFORM_EXPORT WTF::String ImageEncodingMimeTypeName(ImageEncodingMimeType);
+PLATFORM_EXPORT bool ParseImageEncodingMimeType(const WTF::String&,
                                                 ImageEncodingMimeType&);
 
-PLATFORM_EXPORT String LineCapName(LineCap);
-PLATFORM_EXPORT bool ParseLineCap(const String&, LineCap&);
+PLATFORM_EXPORT WTF::String LineCapName(LineCap);
+PLATFORM_EXPORT bool ParseLineCap(const WTF::String&, LineCap&);
 
-PLATFORM_EXPORT String LineJoinName(LineJoin);
-PLATFORM_EXPORT bool ParseLineJoin(const String&, LineJoin&);
+PLATFORM_EXPORT WTF::String LineJoinName(LineJoin);
+PLATFORM_EXPORT bool ParseLineJoin(const WTF::String&, LineJoin&);
 
-PLATFORM_EXPORT String TextAlignName(TextAlign);
-PLATFORM_EXPORT bool ParseTextAlign(const String&, TextAlign&);
+PLATFORM_EXPORT WTF::String TextAlignName(TextAlign);
+PLATFORM_EXPORT bool ParseTextAlign(const WTF::String&, TextAlign&);
 
-PLATFORM_EXPORT String TextBaselineName(TextBaseline);
-PLATFORM_EXPORT bool ParseTextBaseline(const String&, TextBaseline&);
+PLATFORM_EXPORT WTF::String TextBaselineName(TextBaseline);
+PLATFORM_EXPORT bool ParseTextBaseline(const WTF::String&, TextBaseline&);
 
-PLATFORM_EXPORT String PredefinedColorSpaceName(PredefinedColorSpace);
+PLATFORM_EXPORT WTF::String PredefinedColorSpaceName(PredefinedColorSpace);
 
-PLATFORM_EXPORT String CanvasPixelFormatName(CanvasPixelFormat);
+PLATFORM_EXPORT WTF::String CanvasPixelFormatName(CanvasPixelFormat);
 
-PLATFORM_EXPORT String ImageDataStorageFormatName(ImageDataStorageFormat);
+PLATFORM_EXPORT WTF::String ImageDataStorageFormatName(ImageDataStorageFormat);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item.h b/third_party/blink/renderer/platform/graphics/paint/display_item.h
index 1fda02fe..fac6fa1 100644
--- a/third_party/blink/renderer/platform/graphics/paint/display_item.h
+++ b/third_party/blink/renderer/platform/graphics/paint/display_item.h
@@ -14,6 +14,7 @@
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
 #include "third_party/blink/renderer/platform/wtf/hash_functions.h"
 #include "third_party/blink/renderer/platform/wtf/hash_traits.h"
+#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
 #include "ui/gfx/geometry/rect.h"
 
 #if DCHECK_IS_ON()
@@ -21,6 +22,10 @@
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #endif
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class PaintArtifact;
@@ -174,9 +179,9 @@
 
     // The no-argument version is for operator<< which is used in DCHECK and
     // unit tests.
-    String ToString() const;
+    WTF::String ToString() const;
     // This version will output the debug name of the client.
-    String ToString(const PaintArtifact&) const;
+    WTF::String ToString(const PaintArtifact&) const;
 
     const DisplayItemClientId client_id;
     const Type type;
@@ -280,9 +285,9 @@
   bool IsSubsequenceTombstone() const {
     return !is_not_tombstone_ && client_id_ == kInvalidDisplayItemClientId;
   }
-  static String TypeAsDebugString(DisplayItem::Type);
-  String AsDebugString(const PaintArtifact&) const;
-  String IdAsString(const PaintArtifact&) const;
+  static WTF::String TypeAsDebugString(DisplayItem::Type);
+  WTF::String AsDebugString(const PaintArtifact&) const;
+  WTF::String IdAsString(const PaintArtifact&) const;
   void PropertiesAsJSON(JSONObject&,
                         const PaintArtifact&,
                         bool client_known_to_be_alive = false) const;
diff --git a/third_party/blink/renderer/platform/json/json_values.h b/third_party/blink/renderer/platform/json/json_values.h
index de8e81f..5b0b7f2 100644
--- a/third_party/blink/renderer/platform/json/json_values.h
+++ b/third_party/blink/renderer/platform/json/json_values.h
@@ -37,23 +37,21 @@
 #include "base/memory/ptr_util.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "third_party/blink/renderer/platform/wtf/type_traits.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
-namespace blink {
-
-class JSONValue;
-
-}  // namespace blink
+namespace WTF {
+class StringBuilder;
+}  // namespace WTF
 
 namespace blink {
 
 class JSONArray;
 class JSONObject;
+class JSONValue;
 
 class PLATFORM_EXPORT JSONValue {
   USING_FAST_MALLOC(JSONValue);
@@ -90,8 +88,8 @@
 
   String ToJSONString() const;
   String ToPrettyJSONString() const;
-  virtual void WriteJSON(StringBuilder* output) const;
-  virtual void PrettyWriteJSON(StringBuilder* output) const;
+  virtual void WriteJSON(WTF::StringBuilder* output) const;
+  virtual void PrettyWriteJSON(WTF::StringBuilder* output) const;
   virtual std::unique_ptr<JSONValue> Clone() const;
 
   static String QuoteString(const String&);
@@ -99,7 +97,8 @@
  protected:
   JSONValue() : type_(kTypeNull) {}
   explicit JSONValue(ValueType type) : type_(type) {}
-  virtual void PrettyWriteJSONInternal(StringBuilder* output, int depth) const;
+  virtual void PrettyWriteJSONInternal(WTF::StringBuilder* output,
+                                       int depth) const;
 
  private:
   friend class JSONObject;
@@ -120,7 +119,7 @@
   bool AsBoolean(bool* output) const override;
   bool AsDouble(double* output) const override;
   bool AsInteger(int* output) const override;
-  void WriteJSON(StringBuilder* output) const override;
+  void WriteJSON(WTF::StringBuilder* output) const override;
   std::unique_ptr<JSONValue> Clone() const override;
 
  private:
@@ -139,7 +138,7 @@
       : JSONValue(kTypeString), string_value_(value) {}
 
   bool AsString(String* output) const override;
-  void WriteJSON(StringBuilder* output) const override;
+  void WriteJSON(WTF::StringBuilder* output) const override;
   std::unique_ptr<JSONValue> Clone() const override;
 
  private:
@@ -174,7 +173,7 @@
   static void Cast(JSONObject*) = delete;
   static void Cast(std::unique_ptr<JSONObject>) = delete;
 
-  void WriteJSON(StringBuilder* output) const override;
+  void WriteJSON(WTF::StringBuilder* output) const override;
   std::unique_ptr<JSONValue> Clone() const override;
 
   wtf_size_t size() const { return data_.size(); }
@@ -207,7 +206,8 @@
   ~JSONObject() override;
 
  protected:
-  void PrettyWriteJSONInternal(StringBuilder* output, int depth) const override;
+  void PrettyWriteJSONInternal(WTF::StringBuilder* output,
+                               int depth) const override;
 
  private:
   template <typename T>
@@ -250,7 +250,7 @@
   JSONArray();
   ~JSONArray() override;
 
-  void WriteJSON(StringBuilder* output) const override;
+  void WriteJSON(WTF::StringBuilder* output) const override;
   std::unique_ptr<JSONValue> Clone() const override;
 
   void PushBoolean(bool);
@@ -265,7 +265,8 @@
   wtf_size_t size() const { return data_.size(); }
 
  protected:
-  void PrettyWriteJSONInternal(StringBuilder* output, int depth) const override;
+  void PrettyWriteJSONInternal(WTF::StringBuilder* output,
+                               int depth) const override;
 
  private:
   Vector<std::unique_ptr<JSONValue>> data_;
@@ -275,8 +276,8 @@
 extern const char kJSONTrueString[];
 extern const char kJSONFalseString[];
 
-PLATFORM_EXPORT void EscapeStringForJSON(const String&, StringBuilder*);
-void DoubleQuoteStringForJSON(const String&, StringBuilder*);
+PLATFORM_EXPORT void EscapeStringForJSON(const String&, WTF::StringBuilder*);
+void DoubleQuoteStringForJSON(const String&, WTF::StringBuilder*);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/platform/loader/cors/cors_error_string.h b/third_party/blink/renderer/platform/loader/cors/cors_error_string.h
index 4c7db6e..21614153 100644
--- a/third_party/blink/renderer/platform/loader/cors/cors_error_string.h
+++ b/third_party/blink/renderer/platform/loader/cors/cors_error_string.h
@@ -8,7 +8,11 @@
 #include "services/network/public/cpp/cors/cors_error_status.h"
 #include "third_party/blink/public/platform/web_url_request.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class AtomicString;
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -21,12 +25,13 @@
 
 // Stringify CorsError mainly for inspector messages. Generated string should
 // not be exposed to JavaScript for security reasons.
-PLATFORM_EXPORT String GetErrorString(const network::CorsErrorStatus& status,
-                                      const KURL& initial_request_url,
-                                      const KURL& last_request_url,
-                                      const SecurityOrigin& origin,
-                                      ResourceType resource_type,
-                                      const AtomicString& initiator_name);
+PLATFORM_EXPORT WTF::String GetErrorString(
+    const network::CorsErrorStatus& status,
+    const KURL& initial_request_url,
+    const KURL& last_request_url,
+    const SecurityOrigin& origin,
+    ResourceType resource_type,
+    const WTF::AtomicString& initiator_name);
 
 }  // namespace cors
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/body_text_decoder.h b/third_party/blink/renderer/platform/loader/fetch/body_text_decoder.h
index 42fedc2..8ff6548 100644
--- a/third_party/blink/renderer/platform/loader/fetch/body_text_decoder.h
+++ b/third_party/blink/renderer/platform/loader/fetch/body_text_decoder.h
@@ -7,14 +7,18 @@
 
 #include "third_party/blink/public/platform/web_encoding_data.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class BodyTextDecoder {
  public:
   virtual ~BodyTextDecoder() = default;
 
-  virtual String Decode(const char* data, size_t length) = 0;
-  virtual String Flush() = 0;
+  virtual WTF::String Decode(const char* data, size_t length) = 0;
+  virtual WTF::String Flush() = 0;
   virtual WebEncodingData GetEncodingData() const = 0;
 };
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_utils.h b/third_party/blink/renderer/platform/loader/fetch/fetch_utils.h
index 0494bdd..16446a80b 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_utils.h
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_utils.h
@@ -8,22 +8,26 @@
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
 
 namespace network {
 struct ResourceRequest;
 }  // namespace network
 
+namespace WTF {
+class AtomicString;
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class PLATFORM_EXPORT FetchUtils {
   STATIC_ONLY(FetchUtils);
 
  public:
-  static bool IsForbiddenMethod(const String& method);
-  static bool IsForbiddenResponseHeaderName(const String& name);
-  static AtomicString NormalizeMethod(const AtomicString& method);
-  static String NormalizeHeaderValue(const String& value);
+  static bool IsForbiddenMethod(const WTF::String& method);
+  static bool IsForbiddenResponseHeaderName(const WTF::String& name);
+  static WTF::AtomicString NormalizeMethod(const WTF::AtomicString& method);
+  static WTF::String NormalizeHeaderValue(const WTF::String& value);
 
   static net::NetworkTrafficAnnotationTag GetTrafficAnnotationTag(
       const network::ResourceRequest& request);
diff --git a/third_party/blink/renderer/platform/network/mime/mime_type_from_url.h b/third_party/blink/renderer/platform/network/mime/mime_type_from_url.h
index da01213..9dd97c3 100644
--- a/third_party/blink/renderer/platform/network/mime/mime_type_from_url.h
+++ b/third_party/blink/renderer/platform/network/mime/mime_type_from_url.h
@@ -28,11 +28,14 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_MIME_MIME_TYPE_FROM_URL_H_
 
 #include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
-PLATFORM_EXPORT String MimeTypeFromDataURL(const String& url);
+PLATFORM_EXPORT WTF::String MimeTypeFromDataURL(const WTF::String& url);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/platform/network/network_utils.h b/third_party/blink/renderer/platform/network/network_utils.h
index 3d875379..a4d85bee 100644
--- a/third_party/blink/renderer/platform/network/network_utils.h
+++ b/third_party/blink/renderer/platform/network/network_utils.h
@@ -11,6 +11,10 @@
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 class KURL;
@@ -23,16 +27,16 @@
   kExcludePrivateRegistries,
 };
 
-PLATFORM_EXPORT bool IsReservedIPAddress(const String& host);
+PLATFORM_EXPORT bool IsReservedIPAddress(const WTF::String& host);
 
-PLATFORM_EXPORT String GetDomainAndRegistry(const String& host,
-                                            PrivateRegistryFilter);
+PLATFORM_EXPORT WTF::String GetDomainAndRegistry(const WTF::String& host,
+                                                 PrivateRegistryFilter);
 
 // Returns the decoded data url as ResourceResponse and SharedBuffer if parsing
 // was successful. The result is returned as net error code. It returns net::OK
 // if decoding succeeds, otherwise it failed.
 PLATFORM_EXPORT std::tuple<int, ResourceResponse, scoped_refptr<SharedBuffer>>
-ParseDataURL(const KURL&, const String& method);
+ParseDataURL(const KURL&, const WTF::String& method);
 
 // Returns true if the URL is a data URL and its MIME type is in the list of
 // supported/recognized MIME types.
@@ -45,7 +49,7 @@
 
 PLATFORM_EXPORT bool IsCertificateTransparencyRequiredError(int);
 
-PLATFORM_EXPORT String GenerateAcceptLanguageHeader(const String&);
+PLATFORM_EXPORT WTF::String GenerateAcceptLanguageHeader(const WTF::String&);
 
 PLATFORM_EXPORT Vector<char> ParseMultipartBoundary(
     const AtomicString& content_type_header);
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 582a01d9a..51cf1e5 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1247,6 +1247,7 @@
     {
       name: "DialogNewFocusBehavior",
       status: "experimental",
+      depends_on: ["NewGetFocusableAreaBehavior"],
     },
     {
       name: "DigitalGoods",
@@ -2460,6 +2461,13 @@
       base_feature: "none",
     },
     {
+      // This is a killswitch for the behavior of Element::GetFocusableArea
+      // on delegatesFocus shadow hosts. This flag can be removed in M127 if
+      // things are stable.
+      name: "NewGetFocusableAreaBehavior",
+      status: "stable",
+    },
+    {
       name: "NextSiblingPositionUseNextCandidate",
       status: "stable",
     },
diff --git a/third_party/blink/renderer/platform/scheduler/public/virtual_time_controller.h b/third_party/blink/renderer/platform/scheduler/public/virtual_time_controller.h
index 2ce92c5a..b77d428 100644
--- a/third_party/blink/renderer/platform/scheduler/public/virtual_time_controller.h
+++ b/third_party/blink/renderer/platform/scheduler/public/virtual_time_controller.h
@@ -9,6 +9,10 @@
 #include "base/time/time.h"
 #include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 // Exposes methods to enable and control Virtual Time mode for associated
@@ -86,7 +90,7 @@
   // the WebScopedVirtualTimePauser returned by this method is initially
   // unpaused.
   virtual WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser(
-      const String& name,
+      const WTF::String& name,
       WebScopedVirtualTimePauser::VirtualTaskDuration) = 0;
 };
 
diff --git a/third_party/blink/renderer/platform/text/bidi_paragraph.h b/third_party/blink/renderer/platform/text/bidi_paragraph.h
index f9545a1..af92447 100644
--- a/third_party/blink/renderer/platform/text/bidi_paragraph.h
+++ b/third_party/blink/renderer/platform/text/bidi_paragraph.h
@@ -13,10 +13,13 @@
 #include "base/containers/span.h"
 #include "third_party/blink/renderer/platform/text/text_direction.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_view.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
+
 namespace blink {
 
 // BidiParagraph resolves bidirectional runs in a paragraph using ICU BiDi.
@@ -31,7 +34,7 @@
 
  public:
   BidiParagraph() = default;
-  BidiParagraph(const String& text,
+  BidiParagraph(const WTF::String& text,
                 std::optional<TextDirection> base_direction) {
     SetParagraph(text, base_direction);
   }
@@ -41,7 +44,8 @@
   //
   // Returns false on failure. Nothing other than the destructor should be
   // called.
-  bool SetParagraph(const String&, std::optional<TextDirection> base_direction);
+  bool SetParagraph(const WTF::String&,
+                    std::optional<TextDirection> base_direction);
 
   // @return the entire text is unidirectional.
   bool IsUnidirectional() const {
@@ -72,8 +76,8 @@
   // string with a Unicode BiDi override character (LRO or ROL) and PDF.
   // https://unicode.org/reports/tr9/#Explicit_Directional_Overrides
   // https://unicode.org/reports/tr9/#Terminating_Explicit_Directional_Embeddings_and_Overrides
-  static String StringWithDirectionalOverride(const StringView& text,
-                                              TextDirection direction);
+  static WTF::String StringWithDirectionalOverride(const StringView& text,
+                                                   TextDirection direction);
 
   struct Run {
     Run(unsigned start, unsigned end, UBiDiLevel level)
@@ -97,7 +101,7 @@
   // Get a list of `Run` in the logical order (before bidi reorder.)
   // `text` must be the same one as `SetParagraph`.
   // This is higher-level API for `GetLogicalRun`.
-  void GetLogicalRuns(const String& text, Runs* runs) const;
+  void GetLogicalRuns(const WTF::String& text, Runs* runs) const;
 
   // Returns the end offset of a logical run that starts from the |start|
   // offset.
@@ -106,7 +110,7 @@
   // Get a list of `Run` in the visual order (after bidi reorder.)
   // `text` must be the same one as `SetParagraph`.
   // This is higher-level API for `GetLogicalRuns` and `IndicesInVisualOrder`.
-  void GetVisualRuns(const String& text, Runs* runs) const;
+  void GetVisualRuns(const WTF::String& text, Runs* runs) const;
 
   // Create a list of indices in the visual order.
   // A wrapper for ICU |ubidi_reorderVisual()|.
diff --git a/third_party/blink/renderer/platform/text/capitalize.h b/third_party/blink/renderer/platform/text/capitalize.h
index 8dc5a37..c4488e55 100644
--- a/third_party/blink/renderer/platform/text/capitalize.h
+++ b/third_party/blink/renderer/platform/text/capitalize.h
@@ -7,14 +7,17 @@
 
 #include <unicode/utypes.h>
 #include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
 // Capitalize (titlecase) each word of a string.
 // https://drafts.csswg.org/css-text-3/#valdef-text-transform-capitalize
-PLATFORM_EXPORT String Capitalize(const String&,
-                                  UChar previous_character = ' ');
+PLATFORM_EXPORT WTF::String Capitalize(const WTF::String&,
+                                       UChar previous_character = ' ');
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/platform/text/date_components.h b/third_party/blink/renderer/platform/text/date_components.h
index 90ceadd..a6276d65 100644
--- a/third_party/blink/renderer/platform/text/date_components.h
+++ b/third_party/blink/renderer/platform/text/date_components.h
@@ -34,7 +34,10 @@
 #include <limits>
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
@@ -91,7 +94,7 @@
   // Returns an ISO 8601 representation for this instance.
   // The format argument is valid for kDateTime, kDateTimeLocal, and
   // kTime types.
-  String ToString(SecondFormat format = SecondFormat::kNone) const;
+  WTF::String ToString(SecondFormat format = SecondFormat::kNone) const;
 
   // Parse*() and SetMillisecondsSince*() functions are initializers for an
   // DateComponents instance. If these functions return false, the instance
@@ -104,15 +107,15 @@
   // failures, and the trailing extra characters don't cause parse failures.
 
   // Sets FullYear and Month.
-  bool ParseMonth(const String& src, unsigned start, unsigned& end);
+  bool ParseMonth(const WTF::String& src, unsigned start, unsigned& end);
   // Sets FullYear, Month and MonthDay.
-  bool ParseDate(const String& src, unsigned start, unsigned& end);
+  bool ParseDate(const WTF::String& src, unsigned start, unsigned& end);
   // Sets FullYear and Week.
-  bool ParseWeek(const String& src, unsigned start, unsigned& end);
+  bool ParseWeek(const WTF::String& src, unsigned start, unsigned& end);
   // Sets Hour, Minute, Second and Millisecond.
-  bool ParseTime(const String& src, unsigned start, unsigned& end);
+  bool ParseTime(const WTF::String& src, unsigned start, unsigned& end);
   // Sets FullYear, Month, MonthDay, Hour, Minute, Second and Millisecond.
-  bool ParseDateTimeLocal(const String&, unsigned start, unsigned& end);
+  bool ParseDateTimeLocal(const WTF::String&, unsigned start, unsigned& end);
 
   // The following SetMillisecondsSinceEpochFor*() functions take
   // the number of milliseconds since 1970-01-01 00:00:00.000 UTC as
@@ -187,14 +190,14 @@
   // Returns the maximum week number in this DateComponents's year.
   // The result is either of 52 and 53.
   int MaxWeekNumberInYear() const;
-  bool ParseYear(const String&, unsigned start, unsigned& end);
+  bool ParseYear(const WTF::String&, unsigned start, unsigned& end);
   // Helper for MillisecondsSinceEpoch().
   double MillisecondsSinceEpochForTime() const;
   // Helpers for SetMillisecondsSinceEpochFor*().
   bool SetMillisecondsSinceEpochForDateInternal(double ms);
   void SetMillisecondsSinceMidnightInternal(double ms);
   // Helper for ToString().
-  String ToStringForTime(SecondFormat) const;
+  WTF::String ToStringForTime(SecondFormat) const;
 
   // m_weekDay values
   enum {
diff --git a/third_party/blink/renderer/platform/text/date_time_format.h b/third_party/blink/renderer/platform/text/date_time_format.h
index d3db1538..11fabd2 100644
--- a/third_party/blink/renderer/platform/text/date_time_format.h
+++ b/third_party/blink/renderer/platform/text/date_time_format.h
@@ -28,7 +28,11 @@
 
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace WTF {
+class String;
+class StringBuilder;
+}  // namespace WTF
 
 namespace blink {
 
@@ -114,12 +118,12 @@
     TokenHandler& operator=(const TokenHandler&) = delete;
     virtual ~TokenHandler() = default;
     virtual void VisitField(FieldType, int number_of_pattern_characters) = 0;
-    virtual void VisitLiteral(const String&) = 0;
+    virtual void VisitLiteral(const WTF::String&) = 0;
   };
 
   // Returns true if succeeded, false if failed.
-  static bool Parse(const String&, TokenHandler&);
-  static void QuoteAndappend(const String&, StringBuilder&);
+  static bool Parse(const WTF::String&, TokenHandler&);
+  static void QuoteAndappend(const WTF::String&, WTF::StringBuilder&);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/text/locale_to_script_mapping.h b/third_party/blink/renderer/platform/text/locale_to_script_mapping.h
index d4aaaf02..d24e92d 100644
--- a/third_party/blink/renderer/platform/text/locale_to_script_mapping.h
+++ b/third_party/blink/renderer/platform/text/locale_to_script_mapping.h
@@ -35,15 +35,18 @@
 
 #include "base/check.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
 
+namespace WTF {
+class String;
+}  // namespace WTF
 
 namespace blink {
 
-PLATFORM_EXPORT UScriptCode LocaleToScriptCodeForFontSelection(const String&);
-PLATFORM_EXPORT UScriptCode ScriptNameToCode(const String&);
+PLATFORM_EXPORT UScriptCode
+LocaleToScriptCodeForFontSelection(const WTF::String&);
+PLATFORM_EXPORT UScriptCode ScriptNameToCode(const WTF::String&);
 
-PLATFORM_EXPORT UScriptCode ScriptCodeForHanFromSubtags(const String&,
+PLATFORM_EXPORT UScriptCode ScriptCodeForHanFromSubtags(const WTF::String&,
                                                         char delimiter = '-');
 
 inline bool IsUnambiguousHanScript(UScriptCode script) {
diff --git a/third_party/blink/renderer/platform/weborigin/security_origin.h b/third_party/blink/renderer/platform/weborigin/security_origin.h
index 13b4dd4..683ebbd 100644
--- a/third_party/blink/renderer/platform/weborigin/security_origin.h
+++ b/third_party/blink/renderer/platform/weborigin/security_origin.h
@@ -42,6 +42,10 @@
 #include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
 #include "url/origin.h"
 
+namespace WTF {
+class StringBuilder;
+}  // namespace WTF
+
 namespace blink {
 
 class KURL;
@@ -432,7 +436,7 @@
 
   // FIXME: Rename this function to something more semantic.
   bool PassesFileCheck(const SecurityOrigin*) const;
-  void BuildRawString(StringBuilder&) const;
+  void BuildRawString(WTF::StringBuilder&) const;
 
   // Get the nonce associated with this origin, if it is opaque. This should be
   // used only when trying to send an Origin across an IPC pipe or comparing
diff --git a/third_party/blink/renderer/platform/wtf/cross_thread_copier.h b/third_party/blink/renderer/platform/wtf/cross_thread_copier.h
index 35e8989d..64f2bc3 100644
--- a/third_party/blink/renderer/platform/wtf/cross_thread_copier.h
+++ b/third_party/blink/renderer/platform/wtf/cross_thread_copier.h
@@ -39,6 +39,8 @@
 
 namespace WTF {
 
+class String;
+
 template <typename T>
 struct CrossThreadCopierPassThrough {
   STATIC_ONLY(CrossThreadCopierPassThrough);
diff --git a/third_party/blink/renderer/platform/wtf/forward.h b/third_party/blink/renderer/platform/wtf/forward.h
index 82cbdcbd..70845cb 100644
--- a/third_party/blink/renderer/platform/wtf/forward.h
+++ b/third_party/blink/renderer/platform/wtf/forward.h
@@ -43,8 +43,6 @@
 class CaseMap;
 class OrdinalNumber;
 class SharedBuffer;
-class String;
-class StringBuilder;
 class StringImpl;
 class StringView;
 class TextOffsetMap;
@@ -57,9 +55,7 @@
 using WTF::AtomicString;
 using WTF::CaseMap;
 using WTF::SharedBuffer;
-using WTF::String;
 using WTF::StringBuffer;
-using WTF::StringBuilder;
 using WTF::StringImpl;
 using WTF::StringView;
 using WTF::TextOffsetMap;
diff --git a/third_party/blink/renderer/platform/wtf/hash_map.h b/third_party/blink/renderer/platform/wtf/hash_map.h
index 081bb34..e723b94 100644
--- a/third_party/blink/renderer/platform/wtf/hash_map.h
+++ b/third_party/blink/renderer/platform/wtf/hash_map.h
@@ -30,6 +30,7 @@
 #include "third_party/blink/renderer/platform/wtf/construct_traits.h"
 #include "third_party/blink/renderer/platform/wtf/hash_table.h"
 #include "third_party/blink/renderer/platform/wtf/key_value_pair.h"
+#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
 
 namespace WTF {
 
diff --git a/third_party/blink/renderer/platform/wtf/hash_traits.h b/third_party/blink/renderer/platform/wtf/hash_traits.h
index 8312585..8ea77318 100644
--- a/third_party/blink/renderer/platform/wtf/hash_traits.h
+++ b/third_party/blink/renderer/platform/wtf/hash_traits.h
@@ -31,7 +31,6 @@
 #include <utility>
 
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/hash_functions.h"
 #include "third_party/blink/renderer/platform/wtf/hash_table_deleted_value_type.h"
 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
@@ -74,6 +73,8 @@
 template <typename T>
 struct HashTraits;
 
+class String;
+
 namespace internal {
 
 template <typename T>
diff --git a/third_party/blink/renderer/platform/wtf/text/case_map.h b/third_party/blink/renderer/platform/wtf/text/case_map.h
index fcbf5f7..886bf27 100644
--- a/third_party/blink/renderer/platform/wtf/text/case_map.h
+++ b/third_party/blink/renderer/platform/wtf/text/case_map.h
@@ -10,6 +10,7 @@
 
 namespace WTF {
 
+class String;
 class TextOffsetMap;
 
 // This class performs the full Unicode case-mapping.
diff --git a/third_party/blink/renderer/platform/wtf/text/line_ending.h b/third_party/blink/renderer/platform/wtf/text/line_ending.h
index b3719a7..474d12a4 100644
--- a/third_party/blink/renderer/platform/wtf/text/line_ending.h
+++ b/third_party/blink/renderer/platform/wtf/text/line_ending.h
@@ -32,12 +32,13 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_LINE_ENDING_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_LINE_ENDING_H_
 
-#include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 #include "third_party/blink/renderer/platform/wtf/wtf_export.h"
 
 namespace WTF {
 
+class String;
+
 // Normalize all line-endings in the given string to CRLF.
 WTF_EXPORT String NormalizeLineEndingsToCRLF(const String& from);
 
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-skia-graphite b/third_party/blink/web_tests/FlagExpectations/enable-skia-graphite
index e0daee2..9d5eef91 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-skia-graphite
+++ b/third_party/blink/web_tests/FlagExpectations/enable-skia-graphite
@@ -31,6 +31,13 @@
 crbug.com/1518086 external/wpt/html/semantics/embedded-content/media-elements/ready-states/autoplay-hidden.optional.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 virtual/view-transition-wide-gamut/external/wpt/css/css-view-transitions/fractional-box-new.html [ Failure ]
+crbug.com/626703 virtual/view-transition-wide-gamut/external/wpt/css/css-view-transitions/pseudo-with-classes-match-multiple.html [ Failure ]
+crbug.com/626703 virtual/view-transition-mpa-serialization/external/wpt/css/css-view-transitions/massive-element-on-top-of-viewport-partially-onscreen-old.html [ Failure ]
+crbug.com/626703 virtual/view-transition-mpa-serialization/external/wpt/css/css-view-transitions/pseudo-with-classes-match-wildard.html [ Failure ]
+crbug.com/626703 virtual/view-transition-mpa-serialization/external/wpt/css/css-view-transitions/pseudo-with-classes-new-with-class-old-without.html [ Failure ]
+crbug.com/626703 virtual/view-transition-mpa-serialization/external/wpt/css/css-view-transitions/transform-origin-view-transition-group.html [ Failure ]
+crbug.com/626703 virtual/view-transition-wide-gamut/external/wpt/css/css-view-transitions/hit-test-unpainted-element.html [ Failure ]
 crbug.com/626703 virtual/view-transition-mpa-serialization/external/wpt/css/css-view-transitions/pseudo-with-classes-entry.html [ Failure ]
 crbug.com/626703 virtual/view-transition-wide-gamut/external/wpt/css/css-view-transitions/new-and-old-sizes-match.html [ Failure ]
 crbug.com/626703 virtual/view-transition/external/wpt/css/css-view-transitions/new-content-container-writing-modes.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index dc929ad..d5e0e38 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -70532,16 +70532,16 @@
        ]
       ],
       "align-content-block-break-content-020.html": [
-       "83267301b4c1c9d54598b71165a8ddb0fc3ddc44",
+       "bfd76aef23a4b4a2ff8ca18a80fd33b00a197f7f",
        [
         null,
         [
          [
-          "/css/css-align/blocks/align-content-block-break-content-010-aligned-ref.html",
+          "/css/css-align/blocks/align-content-block-break-content-020-aligned-ref.html",
           "=="
          ],
          [
-          "/css/css-align/blocks/align-content-block-break-content-010-unaligned-ref.html",
+          "/css/css-align/blocks/align-content-block-break-content-020-unaligned-ref.html",
           "=="
          ]
         ],
@@ -70562,12 +70562,12 @@
        ]
       ],
       "align-content-block-break-overflow-020.html": [
-       "5f4b3d9555a0811aeb42bf0312c1dca997afc28e",
+       "04b20f87ad72e20b280bc8f2b45d062b7eb72b33",
        [
         null,
         [
          [
-          "/css/css-align/blocks/align-content-block-break-overflow-010-ref.html",
+          "/css/css-align/blocks/align-content-block-break-overflow-020-ref.html",
           "=="
          ]
         ],
@@ -103767,6 +103767,19 @@
         {}
        ]
       ],
+      "content-visibility-intrinsic-size-001.html": [
+       "3a378d17e8947ff63928fcf86e7aa17ff51786aa",
+       [
+        null,
+        [
+         [
+          "/css/css-contain/content-visibility/content-visibility-intrinsic-size-001-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "content-visibility-on-g.html": [
        "4ff07892680c64255757915bcc675a97dd67b317",
        [
@@ -233590,6 +233603,34 @@
       ]
      ]
     },
+    "css-viewport": {
+     "line-height.html": [
+      "fa333be32f6abf97911ee62a09555ceb1071d9d6",
+      [
+       null,
+       [
+        [
+         "/css/css-viewport/line-height-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "width.html": [
+      "b6d9753ea3cb1c4907fb8e84f3b68bbec3cd194a",
+      [
+       null,
+       [
+        [
+         "/css/css-viewport/width-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ]
+    },
     "css-will-change": {
      "will-change-abspos-cb-001.html": [
       "d59e443310fa84f94533c7b18ce67d6c82cf1fc7",
@@ -260306,7 +260347,7 @@
           ]
          ],
          "canvas-filter-object-turbulence.html": [
-          "fe87d37930123e3e1113b14b620fdc5a0de08edf",
+          "eb0803e42e0d8cd925af408ee84d479852561e84",
           [
            null,
            [
@@ -260315,23 +260356,7 @@
              "=="
             ]
            ],
-           {
-            "fuzzy": [
-             [
-              null,
-              [
-               [
-                0,
-                16
-               ],
-               [
-                0,
-                1000
-               ]
-              ]
-             ]
-            ]
-           }
+           {}
           ]
          ],
          "idl-conversions": {
@@ -267711,6 +267736,19 @@
          {}
         ]
        ],
+       "select-button-min-height-001.html": [
+        "c09910507690642cfaf41479503f7f0947359634",
+        [
+         null,
+         [
+          [
+           "/html/rendering/replaced-elements/the-select-element/select-button-min-height-001-ref.html",
+           "=="
+          ]
+         ],
+         {}
+        ]
+       ],
        "select-empty.html": [
         "6568a6de34985a7fc201ce0bd530b86b145083e8",
         [
@@ -303275,6 +303313,10 @@
        "7958810b40ecc2837ecb13d419a577fab9643115",
        []
       ],
+      "content-visibility-intrinsic-size-001-ref.html": [
+       "8d9bd96f7ed0c878310917d7c7ff66ce2e1ba724",
+       []
+      ],
       "content-visibility-on-g-ref.html": [
        "e93425d5ff8afb0cd77a8492c12b36013211bf25",
        []
@@ -335039,10 +335081,6 @@
         []
        ]
       },
-      "calc-size-height.tentative-expected.txt": [
-       "0931cad225e121be2fa732ff9c15588bbe2a8710",
-       []
-      ],
       "calc-size-width.tentative-expected.txt": [
        "8b44b9c67c4af4438c1df74250c3005a9a85bb53",
        []
@@ -336205,6 +336243,14 @@
      "META.yml": [
       "0c4122a8a54873c99c996df5cdb0e5035c9af56b",
       []
+     ],
+     "line-height-ref.html": [
+      "c75539243cbb45ab7407d5519748811e0f44eef0",
+      []
+     ],
+     "width-ref.html": [
+      "5d2755f3e9ea0e3b9b1134ec40a50ef7588bf0ea",
+      []
      ]
     },
     "css-will-change": {
@@ -343125,6 +343171,14 @@
       []
      ],
      "insertion-removing-steps": {
+      "Node-appendChild-script-and-default-style-meta-from-fragment.tentative-expected.txt": [
+       "d13be88c1413c84e960b5551890da9f45d94a5f7",
+       []
+      ],
+      "Node-appendChild-script-in-script.tentative-expected.txt": [
+       "1257d45c0e7988bc2d34d16ac42f396c1a0624c6",
+       []
+      ],
       "blur-event.window-expected.txt": [
        "7c476a91ba6d9ebbca436a25cccd90144bd3e23f",
        []
@@ -355075,7 +355129,7 @@
           []
          ],
          "canvas-filter-object-turbulence-expected.html": [
-          "ff0eebe2e043c77beb0a5ea98d465b091ec6b33e",
+          "ea5600b0062dab5e2d39e584df22996ab31788c1",
           []
          ],
          "idl-conversions": {
@@ -362500,6 +362554,10 @@
         "26e5f33282192b10f56cd66fefeda2c1b9d9b389",
         []
        ],
+       "select-button-min-height-001-ref.html": [
+        "c35ad5fc420cd16baf2914d116f2e5a6e69fb96a",
+        []
+       ],
        "select-empty-ref.html": [
         "31ba23a5cf86f161b1204ea3f4c9fef4585af909",
         []
@@ -478638,6 +478696,90 @@
       ]
      ],
      "insertion-removing-steps": {
+      "Node-appendChild-script-and-button-from-div.tentative.html": [
+       "91f09ae50056661a9aa8553ca75fd6a5dc1482fb",
+       [
+        null,
+        {}
+       ]
+      ],
+      "Node-appendChild-script-and-custom-from-fragment.tentative.html": [
+       "23a050f37e748583bb3090d9cb0b22f90d4abd51",
+       [
+        null,
+        {}
+       ]
+      ],
+      "Node-appendChild-script-and-default-style-meta-from-fragment.tentative.html": [
+       "a9b7ba633e7deac4a4e56b559e3097a614bf70ef",
+       [
+        null,
+        {}
+       ]
+      ],
+      "Node-appendChild-script-and-div-from-fragment.tentative.html": [
+       "b154c1bf4fbf99b5b9ab94ceca7d496604309181",
+       [
+        null,
+        {}
+       ]
+      ],
+      "Node-appendChild-script-and-iframe.tentative.html": [
+       "68b288f24d8aaf1384495f63db57a1892d2bcbf8",
+       [
+        null,
+        {}
+       ]
+      ],
+      "Node-appendChild-script-and-source-from-fragment.tentative.html": [
+       "7f93ac43bd81b2b1579e970dcf5c4bf25141f2ca",
+       [
+        null,
+        {}
+       ]
+      ],
+      "Node-appendChild-script-and-style.tentative.html": [
+       "d3365f8a5ee9545a04a134983100570c6fdb0567",
+       [
+        null,
+        {}
+       ]
+      ],
+      "Node-appendChild-script-in-script.tentative.html": [
+       "71081b49fec1322d12c07efc5eb735d9fef2c2e6",
+       [
+        null,
+        {}
+       ]
+      ],
+      "Node-appendChild-text-and-script-in-style.tentative.html": [
+       "850af680a0d2cfa1e25ef9f12fe42a8863f83221",
+       [
+        null,
+        {}
+       ]
+      ],
+      "Node-appendChild-text-in-script.tentative.html": [
+       "4d6543695cf1ef7f3a76efb9fb80a375328c4c0f",
+       [
+        null,
+        {}
+       ]
+      ],
+      "Node-appendChild-three-scripts-from-fragment.tentative.html": [
+       "a7b7405b64b794dc6981d2ce7977d7c27e7deb74",
+       [
+        null,
+        {}
+       ]
+      ],
+      "Node-appendChild-three-scripts.tentative.html": [
+       "6ffa35515e765b0a34f4a7656bd2ea55badf44aa",
+       [
+        null,
+        {}
+       ]
+      ],
       "blur-event.window.js": [
        "4c8cd85cbf5483c552047fe9698576f201a30a5f",
        [
@@ -527552,79 +527694,6 @@
          {}
         ]
        ],
-       "pageconceal": {
-        "pageconceal-cross-origin.sub.html": [
-         "bcc8a9f888ed05839a11a4f5b6c7e6831ca7b41e",
-         [
-          null,
-          {
-           "testdriver": true
-          }
-         ]
-        ],
-        "pageconceal-iframe.html": [
-         "4202cf0e5a90dad828d89d328025988af732193b",
-         [
-          null,
-          {
-           "testdriver": true
-          }
-         ]
-        ],
-        "pageconceal-push-from-click.html": [
-         "a2a6eb941a3779df441ffdc0cef6b95a8e7b34d6",
-         [
-          null,
-          {
-           "testdriver": true
-          }
-         ]
-        ],
-        "pageconceal-push-navigation-hidden-document.html": [
-         "fdff57c7fb94abd40a022d7b19dd238c90d03ea3",
-         [
-          null,
-          {
-           "testdriver": true
-          }
-         ]
-        ],
-        "pageconceal-push-navigation.html": [
-         "57e12d9ee64a257b897308b53bd804f832d7af4b",
-         [
-          null,
-          {}
-         ]
-        ],
-        "pageconceal-push-with-redirect.html": [
-         "9ad5ee72f4f9bf474b10d2b1f6b2ba99d570550c",
-         [
-          null,
-          {}
-         ]
-        ],
-        "pageconceal-reload-navigation.html": [
-         "0dd135c160a3493ddcc637dd688f2bd2a8bf38f2",
-         [
-          null,
-          {}
-         ]
-        ],
-        "pageconceal-replace-navigation.html": [
-         "012439ae9bbfbdcce9278398db7ad1b60fecd807",
-         [
-          null,
-          {}
-         ]
-        ],
-        "pageconceal-traverse-navigation-no-bfcache.https.html": [
-         "c34c443beadc167ff9fba8ffa9469e0f0dd43208",
-         [
-          null,
-          {}
-         ]
-        ]
-       },
        "pagereveal": {
         "order-in-bfcache-restore.html": [
          "f453c80a2aee8c2cff5bca12f361a6a7b7683be8",
@@ -527650,6 +527719,79 @@
          ]
         ]
        },
+       "pageswap": {
+        "pageswap-cross-origin.sub.html": [
+         "44479cf0debbbfd6fb582fba69c48bdc9e1c6555",
+         [
+          null,
+          {
+           "testdriver": true
+          }
+         ]
+        ],
+        "pageswap-iframe.html": [
+         "05ca1a942886a841852a6afdc9fba460eae950fd",
+         [
+          null,
+          {
+           "testdriver": true
+          }
+         ]
+        ],
+        "pageswap-push-from-click.html": [
+         "936158cd4737845bc3d2bdda2edacd25abee54b9",
+         [
+          null,
+          {
+           "testdriver": true
+          }
+         ]
+        ],
+        "pageswap-push-navigation-hidden-document.html": [
+         "0a699232f071efeb16a82194a2564ef76204e8c7",
+         [
+          null,
+          {
+           "testdriver": true
+          }
+         ]
+        ],
+        "pageswap-push-navigation.html": [
+         "4542d7cae26456f61d94978f02b20392b43cba45",
+         [
+          null,
+          {}
+         ]
+        ],
+        "pageswap-push-with-redirect.html": [
+         "8252fff84d6de401ea577fc22f218aa358f1e67d",
+         [
+          null,
+          {}
+         ]
+        ],
+        "pageswap-reload-navigation.html": [
+         "f7539ebc4784280ce5b500e539d6250f1793a52e",
+         [
+          null,
+          {}
+         ]
+        ],
+        "pageswap-replace-navigation.html": [
+         "f6b3f7408cc39a3e77c220263fac70c8163f9c0b",
+         [
+          null,
+          {}
+         ]
+        ],
+        "pageswap-traverse-navigation-no-bfcache.https.html": [
+         "9e8c0e100ebed2b874556acebf00a1d09045de04",
+         [
+          null,
+          {}
+         ]
+        ]
+       },
        "persisted-user-state-restoration": {
         "resume-timer-on-history-back.html": [
          "77602b2d4258c87a7ac055475986d691da8dad90",
@@ -563890,7 +564032,7 @@
        ]
       ],
       "event-propagate-disabled.tentative.html": [
-       "e3dcd43a17ab2a4bd2b3807f699236d080b95f52",
+       "2be6dc72fe7261f7987b8babbc1628ed6e936423",
        [
         null,
         {
@@ -625875,6 +626017,15 @@
        {}
       ]
      ],
+     "focus-scroll-under-delegatesFocus.html": [
+      "ea5fc472b5a0ffd3bbc6cc2eff112c3f38c0e09e",
+      [
+       null,
+       {
+        "testdriver": true
+       }
+      ]
+     ],
      "focus-selector-delegatesFocus.html": [
       "bbc1346a460a13f17a82046ea2cfacaca5e6e1cf",
       [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-align/blocks/align-content-block-break-content-020.html b/third_party/blink/web_tests/external/wpt/css/css-align/blocks/align-content-block-break-content-020.html
index 8326730..bfd76ae 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-align/blocks/align-content-block-break-content-020.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-align/blocks/align-content-block-break-content-020.html
@@ -4,8 +4,8 @@
 <link rel="help" href="https://www.w3.org/TR/css-align-3/#align-block">
 <meta name="flags" content="may">
 <!-- fragmented alignment is underdefined; these are two possibilities -->
-<link rel="match" href="align-content-block-break-content-010-aligned-ref.html">
-<link rel="match" href="align-content-block-break-content-010-unaligned-ref.html">
+<link rel="match" href="align-content-block-break-content-020-aligned-ref.html">
+<link rel="match" href="align-content-block-break-content-020-unaligned-ref.html">
 
 <style title="Needed for automation; delete to review/debug">
   @import "/fonts/ahem.css";
diff --git a/third_party/blink/web_tests/external/wpt/css/css-align/blocks/align-content-block-break-overflow-020.html b/third_party/blink/web_tests/external/wpt/css/css-align/blocks/align-content-block-break-overflow-020.html
index 5f4b3d95..04b20f8 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-align/blocks/align-content-block-break-overflow-020.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-align/blocks/align-content-block-break-overflow-020.html
@@ -4,7 +4,7 @@
 <link rel="help" href="https://www.w3.org/TR/css-align-3/#align-block">
 <meta name="flags" content="may">
 <!-- fragmented alignment is underdefined; this is one possibility -->
-<link rel="match" href="align-content-block-break-overflow-010-ref.html">
+<link rel="match" href="align-content-block-break-overflow-020-ref.html">
 
 <style title="Needed for automation; delete to review/debug">
   @import "/fonts/ahem.css";
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-intrinsic-size-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-intrinsic-size-001-ref.html
new file mode 100644
index 0000000..8d9bd96f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-intrinsic-size-001-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+  <meta charset="utf-8">
+  <title>content-visibility and intrinsic size (reference)</title>
+  <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+  <script src="/common/rendering-utils.js"></script>
+  <style>
+    #container {
+        position: sticky;
+    }
+    #container > div {
+        font: 25px/1 Ahem;
+    }
+  </style>
+  <div id="container">
+    <div>X</div>
+    <div id="target">XX</div>
+    <div>XXX</div>
+    <div>XXXX</div>
+  </div>
+  <script>
+    target.scrollIntoView();
+    document.fonts.ready.then(() => {
+        waitForAtLeastOneFrame().then(() => {
+            document.documentElement.classList.remove("reftest-wait");
+        });
+    });
+  </script>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-intrinsic-size-001.html b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-intrinsic-size-001.html
new file mode 100644
index 0000000..3a378d1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-intrinsic-size-001.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+  <meta charset="utf-8">
+  <title>content-visibility and intrinsic size</title>
+  <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1880928">
+  <link rel="match" href="content-visibility-intrinsic-size-001-ref.html">
+  <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+  <meta name="assert" content="Rendering of should stabilize, with all the 'content-visibility: auto' divs becoming close to viewport.">
+  <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+  <script src="/common/rendering-utils.js"></script>
+  <style>
+    #container {
+        position: sticky;
+    }
+    #container > div {
+        font: 25px/1 Ahem;
+        content-visibility: auto;
+        contain-intrinsic-size: 1px 5000px;
+    }
+  </style>
+  <div id="container">
+    <div>X</div>
+    <div id="target">XX</div>
+    <div>XXX</div>
+    <div>XXXX</div>
+  </div>
+  <script>
+    target.scrollIntoView();
+    document.fonts.ready.then(() => {
+        waitForAtLeastOneFrame().then(() => {
+            document.documentElement.classList.remove("reftest-wait");
+        });
+    });
+  </script>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-button-from-div.tentative.html b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-button-from-div.tentative.html
new file mode 100644
index 0000000..91f09ae5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-button-from-div.tentative.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Node.appendChild: inserting script and button from a div</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<form id="form"></form>
+<script>
+let button = null;
+let buttonForm = null;
+test(() => {
+  const form = document.getElementById("form");
+  const script = document.createElement("script");
+  script.textContent = `
+    buttonForm = button.form;
+  `;
+  button = document.createElement("button");
+  const div = document.createElement("div");
+  div.appendChild(script);
+  div.appendChild(button);
+  assert_equals(buttonForm, null);
+  form.appendChild(div);
+  assert_equals(buttonForm, form);
+}, "Script inserted before a form-associated button can observe the button's " +
+   "form, because by the time the script executes, the DOM insertion that " +
+   "associates the button with the form is already done");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-custom-from-fragment.tentative.html b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-custom-from-fragment.tentative.html
new file mode 100644
index 0000000..23a050f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-custom-from-fragment.tentative.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Node.appendChild: inserting script and custom element from a DocumentFragment</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<body>
+<script>
+let customConstructed = false;
+let customConstructedDuringEarlierScript = false;
+class CustomElement extends HTMLElement {
+    constructor() {
+        super();
+        customConstructed = true;
+    }
+}
+test(() => {
+  const script = document.createElement("script");
+  script.textContent = `
+    customElements.define("custom-element", CustomElement);
+    customConstructedDuringEarlierScript = customConstructed;
+  `;
+  const custom = document.createElement("custom-element");
+  const df = document.createDocumentFragment();
+  df.appendChild(script);
+  df.appendChild(custom);
+  assert_false(customConstructed);
+  assert_false(customConstructedDuringEarlierScript);
+  document.head.appendChild(df);
+  assert_true(customConstructed);
+  assert_true(customConstructedDuringEarlierScript);
+}, "An earlier-inserted script can upgrade a later-inserted custom element, " +
+   "whose upgrading is synchronously observable to the script, since DOM " +
+   "insertion has been completed by the time it runs");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-default-style-meta-from-fragment.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-default-style-meta-from-fragment.tentative-expected.txt
new file mode 100644
index 0000000..d13be88c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-default-style-meta-from-fragment.tentative-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] Inserting <meta> that uses alternate stylesheets, applies the style during DOM insertion, and before script runs as a result of any atomic insertions
+  assert_equals: display: none; style was applied during DOM insertion, before later-inserted script runs expected "none" but got "block"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-default-style-meta-from-fragment.tentative.html b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-default-style-meta-from-fragment.tentative.html
new file mode 100644
index 0000000..a9b7ba6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-default-style-meta-from-fragment.tentative.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Node.appendChild: inserting script and default-style meta from a fragment</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<link rel="alternate stylesheet" title="alternative" href="data:text/css,%23div{display:none}">
+<div id="div">hello</div>
+<script>
+let scriptRan = false;
+let computedStyleDuringInsertion = null;
+test(() => {
+  const div = document.getElementById("div");
+  const meta = document.createElement("meta");
+  meta.httpEquiv = "default-style";
+  meta.content = "alternative";
+  const script = document.createElement("script");
+  script.textContent = `
+    computedStyleDuringInsertion = getComputedStyle(div).display;
+    scriptRan = true;
+  `;
+  const df = document.createDocumentFragment();
+  df.appendChild(script);
+  df.appendChild(meta);
+  assert_equals(getComputedStyle(div).display, "block", "div has block display");
+  assert_false(scriptRan, "script has not run before insertion");
+  document.head.appendChild(df);
+  assert_true(scriptRan, "script has run after insertion");
+  assert_equals(computedStyleDuringInsertion, "none",
+      "display: none; style was applied during DOM insertion, before " +
+      "later-inserted script runs");
+  assert_equals(getComputedStyle(div).display, "none",
+      "style remains display: none; after insertion");
+}, "Inserting <meta> that uses alternate stylesheets, applies the style " +
+   "during DOM insertion, and before script runs as a result of any atomic insertions");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-div-from-fragment.tentative.html b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-div-from-fragment.tentative.html
new file mode 100644
index 0000000..b154c1b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-div-from-fragment.tentative.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Node.appendChild: inserting script and div from a DocumentFragment</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<body>
+<script>
+let script = null;
+let scriptParent = null;
+let div = null;
+let divParent = null;
+test(() => {
+  script = document.createElement("script");
+  div = document.createElement("div");
+  script.textContent = `
+    divParent = div.parentNode;
+    scriptParent = script.parentNode;
+  `;
+  const df = document.createDocumentFragment();
+  df.appendChild(script);
+  df.appendChild(div);
+  assert_equals(divParent, null);
+  assert_equals(scriptParent, null);
+  document.head.appendChild(df);
+  assert_equals(divParent, scriptParent);
+  assert_equals(divParent, document.head);
+}, "Earlier-inserted scripts can observe the parentNode of later-inserted " +
+   "nodes, because script runs after DOM insertion completes");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-iframe.tentative.html b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-iframe.tentative.html
new file mode 100644
index 0000000..68b288f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-iframe.tentative.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Node.appendChild: inserting script and iframe</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<body>
+<script>
+
+const kScriptContent = `
+  state = iframe.contentWindow ? "iframe with content window" : "contentWindow is null";
+`;
+
+// This test ensures that a later-inserted script can observe an
+// earlier-inserted iframe's contentWindow.
+test(t => {
+  window.state = "script not run yet";
+  window.iframe = document.createElement("iframe");
+  t.add_cleanup(() => window.iframe.remove());
+
+  const script = document.createElement("script");
+  script.textContent = kScriptContent;
+
+  const div = document.createElement("div");
+  div.appendChild(iframe);
+  div.appendChild(script);
+
+  assert_equals(state, "script not run yet");
+  document.body.appendChild(div);
+  assert_equals(state, "iframe with content window");
+}, "Script inserted after an iframe in the same appendChild() call can " +
+   "observe the iframe's non-null contentWindow");
+
+// The below tests assert that an earlier-inserted script does not observe a
+// later-inserted iframe's contentWindow.
+test(t => {
+  window.state = "script not run yet";
+  window.iframe = document.createElement("iframe");
+  t.add_cleanup(() => window.iframe.remove());
+
+  const script = document.createElement("script");
+  script.textContent = kScriptContent;
+
+  const div = document.createElement("div");
+  div.appendChild(script);
+  div.appendChild(iframe);
+
+  assert_equals(state, "script not run yet");
+  document.body.appendChild(div);
+  assert_equals(state, "contentWindow is null");
+}, "A script inserted atomically before an iframe (using a div) does not " +
+   "observe the iframe's contentWindow, since the 'script running' and " +
+   "'iframe setup' both happen in order, after DOM insertion completes");
+
+test(t => {
+  window.state = "script not run yet";
+  window.iframe = document.createElement("iframe");
+  t.add_cleanup(() => window.iframe.remove());
+
+  const script = document.createElement("script");
+  script.textContent = kScriptContent;
+
+  const df = document.createDocumentFragment();
+  df.appendChild(script);
+  df.appendChild(iframe);
+
+  assert_equals(state, "script not run yet");
+  document.body.appendChild(df);
+  assert_equals(state, "contentWindow is null");
+}, "A script inserted atomically before an iframe (using a DocumentFragment) " +
+   "does not observe the iframe's contentWindow, since the 'script running' " +
+   "and 'iframe setup' both happen in order, after DOM insertion completes");
+
+test(t => {
+  window.state = "script not run yet";
+  window.iframe = document.createElement("iframe");
+  t.add_cleanup(() => window.iframe.remove());
+
+  const script = document.createElement("script");
+  script.textContent = kScriptContent;
+
+  assert_equals(state, "script not run yet");
+  document.body.append(script, iframe);
+
+  assert_equals(state, "contentWindow is null");
+}, "A script inserted atomically before an iframe (using a append() with " +
+   "multiple arguments) does not observe the iframe's contentWindow, since " +
+   "the 'script running' and 'iframe setup' both happen in order, after DOM " +
+   "insertion completes");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-source-from-fragment.tentative.html b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-source-from-fragment.tentative.html
new file mode 100644
index 0000000..7f93ac43b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-source-from-fragment.tentative.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Node.appendChild: inserting script and source from a fragment</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<video id="media"></video>
+<script>
+const happened = [];
+const media = document.getElementById("media");
+test(() => {
+  const source = document.createElement("source");
+  const script = document.createElement("script");
+  script.textContent = `
+    happened.push(media.networkState);
+  `;
+
+  const df = document.createDocumentFragment();
+  df.appendChild(script);
+  df.appendChild(source);
+
+  assert_array_equals(happened, []);
+  media.appendChild(df);
+  // This is because immediately during DOM insertion, before the
+  // post-insertion steps invoke script, `<source>` insertion invokes the
+  // resource selection algorithm [1] which does this assignment. This
+  // assignment takes place before earlier-inserted script elements run
+  // post-insertion.
+  //
+  // [1]: https://html.spec.whatwg.org/#concept-media-load-algorithm
+  assert_array_equals(happened, [HTMLMediaElement.NETWORK_NO_SOURCE]);
+}, "Empty <source> immediately sets media.networkState during DOM insertion, " +
+   "so that an earlier-running script can observe networkState");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-style.tentative.html b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-style.tentative.html
new file mode 100644
index 0000000..d3365f8a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-and-style.tentative.html
@@ -0,0 +1,118 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Node.appendChild: inserting a script and a style where the script modifies the style</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<body>
+<script>
+// <script> & <style> element tests.
+test(() => {
+  window.happened = [];
+  window.style = document.createElement("style");
+  let styleSheet = null;
+
+  style.appendChild(new Text("body {}"));
+  const script = document.createElement("script");
+  script.textContent = `
+    styleSheet = style.sheet;
+    happened.push(style.sheet ? "sheet" : null);
+    style.appendChild(new Text("body {}"));
+    happened.push(style.sheet?.cssRules.length);
+  `;
+
+  const div = document.createElement("div");
+  div.appendChild(script);
+  div.appendChild(style);
+
+  assert_array_equals(happened, []);
+  document.body.appendChild(div);
+  assert_array_equals(happened, ["sheet", 2]);
+  assert_not_equals(style.sheet, styleSheet, "style sheet was created only once");
+}, "An earlier-inserted <script> synchronously observes a later-inserted " +
+   "<style> (via a div) being applied");
+
+test(() => {
+  window.happened = [];
+  window.style = document.createElement("style");
+  let styleSheet = null;
+
+  style.appendChild(new Text("body {}"));
+  const script = document.createElement("script");
+  script.textContent = `
+    styleSheet = style.sheet;
+    happened.push(style.sheet ? "sheet" : null);
+    style.appendChild(new Text("body {}"));
+    happened.push(style.sheet?.cssRules.length);
+`;
+
+  const df = document.createDocumentFragment();
+  df.appendChild(script);
+  df.appendChild(style);
+
+  assert_array_equals(happened, []);
+  document.body.appendChild(df);
+  assert_array_equals(happened, ["sheet", 2]);
+  assert_not_equals(style.sheet, styleSheet, "style sheet was created only once");
+}, "An earlier-inserted <script> synchronously observes a later-inserted " +
+   "<style> (via a DocumentFragment) being applied");
+
+// <script> & <link rel=stylesheet> element tests.
+test(() => {
+  window.happened = [];
+  window.link = document.createElement("link");
+  link.rel = "stylesheet";
+  link.href = "data:text/css,";
+
+  const script = document.createElement("script");
+  script.textContent = `
+    happened.push(link.sheet ? "sheet" : null);
+  `;
+
+  const df = document.createDocumentFragment();
+  df.appendChild(script);
+  df.appendChild(link);
+
+  assert_array_equals(happened, []);
+  document.body.appendChild(df);
+  assert_array_equals(happened, ["sheet"]);
+}, "Earlier-inserted <script> (via a DocumentFragment) synchronously " +
+   "observes a later-inserted <link rel=stylesheet>'s CSSStyleSheet creation");
+
+test(() => {
+  window.happened = [];
+  window.link = document.createElement("link");
+  link.rel = "stylesheet";
+  link.href = "data:text/css,";
+
+  const script = document.createElement("script");
+  script.textContent = `
+    happened.push(link.sheet ? "sheet" : null);
+`;
+
+  const div = document.createElement("div");
+  div.appendChild(script);
+  div.appendChild(link);
+
+  assert_array_equals(happened, []);
+  document.body.appendChild(div);
+  assert_array_equals(happened, ["sheet"]);
+}, "Earlier-inserted <script> (via a div) synchronously observes a " +
+   "later-inserted <link rel=stylesheet>'s CSSStyleSheet creation");
+
+test(() => {
+  window.happened = [];
+  window.link = document.createElement("link");
+  link.rel = "stylesheet";
+  link.href = "data:text/css,";
+
+  const script = document.createElement("script");
+  script.textContent = `
+    happened.push(link.sheet ? "sheet" : null);
+`;
+
+  assert_array_equals(happened, []);
+  document.body.append(script, link);
+  assert_array_equals(happened, ["sheet"]);
+}, "Earlier-inserted <script> (via a append()) synchronously observes a " +
+   "later-inserted <link rel=stylesheet>'s CSSStyleSheet creation");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-in-script.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-in-script.tentative-expected.txt
new file mode 100644
index 0000000..1257d45
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-in-script.tentative-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] An outer script does not execute until its inner `<script>` children are finished being inserted into it. The outer script's execution considers any script text that inner scripts added to the outer one.
+  assert_array_equals: lengths differ, expected array ["s2", "s2ran", "s1", "s1ran"] length 4, got ["s1", "s2", "s2ran"] length 3
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-in-script.tentative.html b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-in-script.tentative.html
new file mode 100644
index 0000000..71081b4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-script-in-script.tentative.html
@@ -0,0 +1,48 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Node.appendChild: inserting a script and some code in an empty script</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<body>
+<script id="s1"></script>
+<script>
+const happened = [];
+test(() => {
+  const s1 = document.getElementById("s1");
+  const s2 = document.createElement("script");
+
+  // This script, which is ultimately a *child* of the
+  // already-connected-but-empty `s1` script, runs first. This is because when
+  // the DocumentFragment `df` containing this script (`s2`) is appended to
+  // `s1`, we do not immediately execute `s1`, because of this condition: [1].
+  // It specifies that when a "node or document fragment is inserted into the
+  // script", we only run the "prepare the script algorithm" for that script
+  // "after any script elements inserted at that time".
+  //
+  // So upon insertion of `s2`, its insertion conditions are met and it is
+  // prepared and run first. During its execution, it mutates `s1`, adding more
+  // text to it. This condition still does not trigger the immediate execution
+  // of `s1`, because `s2`'s insertion is not complete yet.
+  //
+  // Once `s2` is finished being inserted, the condition to prepare and execute
+  // `s1` is met, and it is processed accordingly, which includes the execution
+  // of the text that `s2` added to `s1`.
+  //
+  // [1]: https://html.spec.whatwg.org/C#script-processing-model:prepare-the-script-element-4
+  s2.textContent = `
+    happened.push("s2");
+    s1.appendChild(new Text("happened.push('s1ran');"));
+    happened.push("s2ran");
+`;
+
+  const df = document.createDocumentFragment();
+  df.appendChild(new Text(`happened.push("s1");`));
+  df.appendChild(s2);
+
+  assert_array_equals(happened, []);
+  s1.appendChild(df);
+  assert_array_equals(happened, ["s2", "s2ran", "s1", "s1ran"]);
+}, "An outer script does not execute until its inner `<script>` children are " +
+   "finished being inserted into it. The outer script's execution considers " +
+   "any script text that inner scripts added to the outer one.");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-text-and-script-in-style.tentative.html b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-text-and-script-in-style.tentative.html
new file mode 100644
index 0000000..850af680a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-text-and-script-in-style.tentative.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Node.appendChild: inserting text and script nodes in a style element</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<style id="style"></style>
+<body>
+<script>
+const happened = []
+const style = document.getElementById("style");
+test(() => {
+  const r1 = new Text("body {}");
+  const r2 = new Text("body {}");
+  const script = document.createElement("script");
+  script.textContent = `
+    happened.push(style.sheet.cssRules.length);
+  `;
+
+  const df = document.createDocumentFragment();
+  df.appendChild(r1);
+  df.appendChild(script);
+  df.appendChild(r2);
+
+  assert_array_equals(happened, []);
+  style.appendChild(df);
+  assert_array_equals(happened, [2]);
+}, "All style rules appended to a <style> element are inserted and " +
+   "script-observable to scripts inserted in the `<style>` element, by the " +
+   "time scripts execute after DOM insertions.");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-text-in-script.tentative.html b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-text-in-script.tentative.html
new file mode 100644
index 0000000..4d65436
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-text-in-script.tentative.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Node.appendChild: inserting two text nodes in an empty script</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<body>
+  <script id="script"></script>
+<script>
+const happened = [];
+test(() => {
+  const script = document.getElementById("script");
+  const df = document.createDocumentFragment();
+  df.appendChild(new Text("happened.push('t1');"));
+  df.appendChild(new Text("happened.push('t2');"));
+  assert_array_equals(happened, []);
+  script.appendChild(df);
+  assert_array_equals(happened, ["t1", "t2"]);
+  // At this point it's already executed so further motifications are a no-op
+  script.appendChild(new Text("happened.push('t3');"));
+  script.textContent = "happened.push('t4');"
+  script.text = "happened.push('t5');"
+  assert_array_equals(happened, ["t1", "t2"]);
+});
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-three-scripts-from-fragment.tentative.html b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-three-scripts-from-fragment.tentative.html
new file mode 100644
index 0000000..a7b7405b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-three-scripts-from-fragment.tentative.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Node.appendChild: inserting three scripts from a document fragment</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<body>
+  <script>
+const s1 = document.createElement("script");
+const s2 = document.createElement("script");
+const s3 = document.createElement("script");
+const happened = [];
+
+test(() => {
+  s1.textContent = `
+    s3.appendChild(new Text("happened.push('s3');"));
+    happened.push("s1");
+  `;
+  s2.textContent = `
+    happened.push("s2");
+  `;
+  const df = document.createDocumentFragment();
+  df.appendChild(s1);
+  df.appendChild(s2);
+  df.appendChild(s3);
+
+  assert_array_equals(happened, []);
+  document.body.appendChild(df);
+  assert_array_equals(happened, ["s3", "s1", "s2"]);
+});
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-three-scripts.tentative.html b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-three-scripts.tentative.html
new file mode 100644
index 0000000..6ffa355
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/insertion-removing-steps/Node-appendChild-three-scripts.tentative.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Node.appendChild: inserting three scripts from a div</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<body>
+  <script>
+const s1 = document.createElement("script");
+const s2 = document.createElement("script");
+const s3 = document.createElement("script");
+const happened = [];
+
+test(() => {
+  s1.textContent = `
+    s3.appendChild(new Text("happened.push('s3');"));
+    happened.push("s1");
+  `;
+  s2.textContent = `
+    happened.push("s2");
+  `;
+  const div = document.createElement("div");
+  div.appendChild(s1);
+  div.appendChild(s2);
+  div.appendChild(s3);
+
+  assert_array_equals(happened, []);
+  document.body.appendChild(div);
+  assert_array_equals(happened, ["s3", "s1", "s2"]);
+});
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/the-select-element/select-button-min-height-001-ref.html b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/the-select-element/select-button-min-height-001-ref.html
new file mode 100644
index 0000000..c35ad5f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/the-select-element/select-button-min-height-001-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test Reference</title>
+<style>
+  select, input, button { height: 100px; }
+</style>
+<div>
+  <select><option>Select</option></select>
+  <button>Button</button>
+  <input type="button" value="Input">
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/the-select-element/select-button-min-height-001.html b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/the-select-element/select-button-min-height-001.html
new file mode 100644
index 0000000..c099105
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/the-select-element/select-button-min-height-001.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>min-height and height both trigger same rendering for select and buttons by default</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1362907">
+<link rel="match" href="select-button-min-height-001-ref.html">
+<style>
+  select, input, button { min-height: 100px; }
+</style>
+<div>
+  <select><option>Select</option></select>
+  <button>Button</button>
+  <input type="button" value="Input">
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/disabled-elements/event-propagate-disabled.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/disabled-elements/event-propagate-disabled.tentative.html
index e3dcd43..2be6dc72 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/disabled-elements/event-propagate-disabled.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/disabled-elements/event-propagate-disabled.tentative.html
@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <meta charset="utf8">
 <meta name="timeout" content="long">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Event propagation on disabled form elements</title>
 <link rel="author" href="mailto:krosylight@mozilla.com">
 <link rel="help" href="https://github.com/whatwg/html/issues/2368">
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/focus/focus-scroll-under-delegatesFocus.html b/third_party/blink/web_tests/external/wpt/shadow-dom/focus/focus-scroll-under-delegatesFocus.html
new file mode 100644
index 0000000..ea5fc47
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/shadow-dom/focus/focus-scroll-under-delegatesFocus.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<link rel="author" href="mailto:masonf@chromium.org">
+<link rel="help" href="https://issues.chromium.org/issues/324112201">
+<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>
+
+<div id=container style="border:1px solid red; width: 100px;">
+  <template shadowrootmode=open shadowrootdelegatesfocus>
+    <slot></slot>
+  </template>
+
+  <a id=anchor href="#heading">anchor</a>
+  <div style="height:2000px"></div>
+  <h1 id=heading>Heading</h1>
+</div>
+
+<script>
+promise_test(async (t) => {
+  t.add_cleanup(() => container.remove());
+  let scrolled = new Promise(resolve => {
+    document.addEventListener('scrollend',resolve,{once:true});
+  })
+  await test_driver.click(anchor);
+  await scrolled;
+
+  scrolled = false;
+  document.addEventListener('scroll',() => {
+    scrolled = true;
+  });
+  await test_driver.click(heading);
+  await new Promise(resolve => t.step_timeout(resolve, 500));
+  assert_false(scrolled,'The document should not scroll');
+},'delegatesFocus shouldn\'t cause extra focus steps');
+</script>
diff --git a/third_party/blink/web_tests/platform/mac-mac12/virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/smooth-scroll-in-load-event-expected.txt b/third_party/blink/web_tests/platform/mac-mac12/virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/smooth-scroll-in-load-event-expected.txt
deleted file mode 100644
index 2709251..0000000
--- a/third_party/blink/web_tests/platform/mac-mac12/virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/smooth-scroll-in-load-event-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-[FAIL] Smooth scroll in load event handler
-  assert_equals: Final value of scrollLeft expected 800 but got 0
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/smooth-scroll-in-load-event-expected.txt b/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/smooth-scroll-in-load-event-expected.txt
deleted file mode 100644
index 2709251..0000000
--- a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/smooth-scroll-in-load-event-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-[FAIL] Smooth scroll in load event handler
-  assert_equals: Final value of scrollLeft expected 800 but got 0
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/mac/virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/smooth-scroll-in-load-event-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/smooth-scroll-in-load-event-expected.txt
deleted file mode 100644
index d2490db..0000000
--- a/third_party/blink/web_tests/platform/mac/virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/smooth-scroll-in-load-event-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-This is a testharness.js-based test.
-Harness: the test ran to completion.
-
diff --git a/third_party/catapult b/third_party/catapult
index 2ee42b4..f226e76 160000
--- a/third_party/catapult
+++ b/third_party/catapult
@@ -1 +1 @@
-Subproject commit 2ee42b4fee621515571f90e0aac3098caad8e712
+Subproject commit f226e76aa5f1014892221b2d426ad63f04b8ed07
diff --git a/third_party/chromium-variations b/third_party/chromium-variations
index 2f49c50..2c5458c 160000
--- a/third_party/chromium-variations
+++ b/third_party/chromium-variations
@@ -1 +1 @@
-Subproject commit 2f49c50b79ab7a6ee16f324656f0185a44fa50a6
+Subproject commit 2c5458c1057e9a8d69cfa6c15f42ef6446b1629a
diff --git a/third_party/closure_compiler/externs/terminal_private.js b/third_party/closure_compiler/externs/terminal_private.js
index fca1f78f..bb6b8ad 100644
--- a/third_party/closure_compiler/externs/terminal_private.js
+++ b/third_party/closure_compiler/externs/terminal_private.js
@@ -1,4 +1,4 @@
-// Copyright 2023 The Chromium Authors
+// Copyright 2024 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -114,7 +114,6 @@
  * Returns an object containing info about ChromeOS settings that affect the
  * Terminal, e.g. which feature flags are enabled.
  * @param {function({
- *   alternative_emulator: boolean,
  *   tast: boolean
  * }): void} callback Callback that will be called with the info object.
  */
diff --git a/third_party/devtools-frontend-internal b/third_party/devtools-frontend-internal
index 196ae62..9c278bd 160000
--- a/third_party/devtools-frontend-internal
+++ b/third_party/devtools-frontend-internal
@@ -1 +1 @@
-Subproject commit 196ae62399105a2fe043fcd30a1446e2fe80d7b3
+Subproject commit 9c278bd6f25a7da69b438b262acd0da6d2f78b1a
diff --git a/third_party/lit/v3_0/cr_lit_element.ts b/third_party/lit/v3_0/cr_lit_element.ts
index 8919bad..ee02b5ab 100644
--- a/third_party/lit/v3_0/cr_lit_element.ts
+++ b/third_party/lit/v3_0/cr_lit_element.ts
@@ -102,11 +102,20 @@
 
     const notifyProps = (this.constructor as typeof CrLitElement).notifyProps_;
     if (notifyProps !== null) {
+      const indexableThis = this as Record<PropertyKey, any>;
       for (const key of changedProperties.keys()) {
         if (notifyProps.has(key)) {
+          if (changedProperties.get(key as keyof CrLitElement) === undefined &&
+              indexableThis[key] === undefined) {
+            // Don't fire events if the property was changed back to 'undefined'
+            // before the element was connected. Lit still reports such
+            // properties in `changedProperties` as going from 'undefined' to
+            // 'undefined'.
+            continue;
+          }
           this.fire(
               `${toDashCase(key.toString())}-changed`,
-              {value: (this as Record<PropertyKey, any>)[key]});
+              {value: indexableThis[key]});
         }
       }
     }
diff --git a/third_party/pdfium b/third_party/pdfium
index f180508..ef0eeaa9 160000
--- a/third_party/pdfium
+++ b/third_party/pdfium
@@ -1 +1 @@
-Subproject commit f1805084d8ec1a854ffa6e4f3d489aaa5c9818ab
+Subproject commit ef0eeaa9e423c5aa002180cbc448f784c8e621ae
diff --git a/third_party/perfetto b/third_party/perfetto
index 77ac4b7..98921c2 160000
--- a/third_party/perfetto
+++ b/third_party/perfetto
@@ -1 +1 @@
-Subproject commit 77ac4b7528eeb8444b6f829264a2e82be99a8cd0
+Subproject commit 98921c2a0c99fa8e97f5e6c369cc3e16473c695e
diff --git a/third_party/skia b/third_party/skia
index ffbe23b..a57372c 160000
--- a/third_party/skia
+++ b/third_party/skia
@@ -1 +1 @@
-Subproject commit ffbe23b3b3b97564ad18f997f750596936db00a4
+Subproject commit a57372ca2e66d24db942f406404b8be92870afb2
diff --git a/third_party/zlib/contrib/tests/fuzzers/deflate_fuzzer.cc b/third_party/zlib/contrib/tests/fuzzers/deflate_fuzzer.cc
index 6f3e45e..2468509 100644
--- a/third_party/zlib/contrib/tests/fuzzers/deflate_fuzzer.cc
+++ b/third_party/zlib/contrib/tests/fuzzers/deflate_fuzzer.cc
@@ -84,14 +84,20 @@
     }
     ASSERT(ret == Z_OK || Z_BUF_ERROR);
   }
-
-  // Check that the bound was correct.
-  // size_t deflate_bound = deflateBound(&stream, src.size());
-  // TODO(crbug.com/40270738): This does not always hold.
-  // ASSERT(compressed.size() <= deflate_bound);
-
   deflateEnd(&stream);
 
+  // Check deflateBound().
+  // Use a newly initialized stream since computing the bound on a "used" stream
+  // may not yield a correct result (https://github.com/madler/zlib/issues/944).
+  z_stream bound_stream;
+  bound_stream.zalloc = Z_NULL;
+  bound_stream.zfree = Z_NULL;
+  ret = deflateInit2(&bound_stream, level, Z_DEFLATED, windowBits, memLevel,
+                     strategy);
+  ASSERT(ret == Z_OK);
+  size_t deflate_bound = deflateBound(&bound_stream, src.size());
+  ASSERT(compressed.size() <= deflate_bound);
+  deflateEnd(&bound_stream);
 
   // Verify that the data decompresses correctly.
   ret = inflateInit2(&stream, windowBits);
diff --git a/tools/metrics/histograms/metadata/autofill/enums.xml b/tools/metrics/histograms/metadata/autofill/enums.xml
index 1390604..5dce658 100644
--- a/tools/metrics/histograms/metadata/autofill/enums.xml
+++ b/tools/metrics/histograms/metadata/autofill/enums.xml
@@ -59,6 +59,17 @@
   <int value="2" label="Suggestion Deleted"/>
 </enum>
 
+<enum name="AutocompleteSuppressionByPlusAddress">
+  <int value="0"
+      label="Autocomplete suggestions would not have been suppressed."/>
+  <int value="1"
+      label="Autocomplete suggestions would have been suppressed and would
+             have contained email addresses."/>
+  <int value="2"
+      label="Autocomplete suggestions would have been suppressed and would
+             not have contained email addresses."/>
+</enum>
+
 <enum name="AutofillAddressProfileImportCountrySpecificFieldRequirement">
   <int value="0" label="All required fields present"/>
   <int value="1" label="Missing: ZIP"/>
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml
index 70ec174..97e363b 100644
--- a/tools/metrics/histograms/metadata/autofill/histograms.xml
+++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -882,6 +882,23 @@
   </summary>
 </histogram>
 
+<histogram name="Autofill.Autocomplete.SuppressionByPlusAddress"
+    enum="AutocompleteSuppressionByPlusAddress" expires_after="2024-09-30">
+  <owner>jkeitel@google.com</owner>
+  <owner>schwering@google.com</owner>
+  <owner>vizcay@google.com</owner>
+  <summary>
+    Records whether an Autocomplete suggestion would have been suppressed by a
+    Plus Address suggestion. In case that it would have been suppressed, it also
+    checks whether any of the Autocomplete suggestions would have contained a
+    valid email string. Emitted whenever one or more Autocomplete suggestions
+    are shown (either in the Autofill popup or the keyboard accessory), the user
+    is signed in, and is not using incognito mode. Note that this metric will
+    become meaningless once the Plus Address feature is rolled out to a
+    significant portion of users.
+  </summary>
+</histogram>
+
 <histogram name="Autofill.AutocompleteUnrecognized.FieldFillingStat"
     enum="FieldFillingStat" expires_after="2024-12-12">
   <owner>jihadghanna@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/extensions/enums.xml b/tools/metrics/histograms/metadata/extensions/enums.xml
index 07f5be8..ceb705fe 100644
--- a/tools/metrics/histograms/metadata/extensions/enums.xml
+++ b/tools/metrics/histograms/metadata/extensions/enums.xml
@@ -2722,6 +2722,7 @@
   <int value="1870" label="AUTOFILLPRIVATE_SETAUTOFILLSYNCTOGGLEENABLED"/>
   <int value="1871"
       label="ODFSCONFIGPRIVATE_ISFILESYSTEMPROVIDERCLOUDFILESYSTEMENABLED"/>
+  <int value="1872" label="PDFVIEWERPRIVATE_SETPDFDOCUMENTTITLE"/>
 </enum>
 
 <enum name="ExtensionInstallationCrxInstallError">
diff --git a/tools/typescript/definitions/BUILD.gn b/tools/typescript/definitions/BUILD.gn
deleted file mode 100644
index 97a1a528..0000000
--- a/tools/typescript/definitions/BUILD.gn
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright 2024 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/config/chromeos/ui_mode.gni")
-import("//tools/typescript/ts_library.gni")
-
-ts_library("library") {
-  composite = true
-  definitions = [
-    "accessibility_features.d.ts",
-    "accessibility_service_private.d.ts",
-    "activity_log_private.d.ts",
-    "autofill_private.d.ts",
-    "bookmarks.d.ts",
-    "chrome_downloads.d.ts",
-    "chrome_event.d.ts",
-    "chrome_send.d.ts",
-    "chrome_test.d.ts",
-    "chrome_timeticks.d.ts",
-    "content_settings.d.ts",
-    "context_menus.d.ts",
-    "developer_private.d.ts",
-    "dom_automation_controller.d.ts",
-    "extension_types.d.ts",
-    "feedback_private.d.ts",
-    "file_system.d.ts",
-    "language_settings_private.d.ts",
-    "management.d.ts",
-    "metrics_private.d.ts",
-    "mime_handler_private.d.ts",
-    "passwords_private.d.ts",
-    "pdf_viewer_private.d.ts",
-    "pending.d.ts",
-    "quick_unlock_private.d.ts",
-    "resources_private.d.ts",
-    "runtime.d.ts",
-    "scripting.d.ts",
-    "settings_private.d.ts",
-    "storage.d.ts",
-    "tabs.d.ts",
-    "webview_tag.d.ts",
-    "web_request.d.ts",
-    "windows.d.ts",
-  ]
-
-  if (is_chromeos_ash) {
-    definitions += [
-      "bluetooth.d.ts",
-      "bluetooth_private.d.ts",
-      "bookmark_manager_private.d.ts",
-      "command_line_private.d.ts",
-      "chromeos_info_private.d.ts",
-      "i18n.d.ts",
-      "input_method_private.d.ts",
-      "networking_private.d.ts",
-      "notifications.d.ts",
-      "system_display.d.ts",
-      "users_private.d.ts",
-      "wallpaper.d.ts",
-    ]
-  }
-}
diff --git a/tools/typescript/definitions/pdf_viewer_private.d.ts b/tools/typescript/definitions/pdf_viewer_private.d.ts
index 35dfcc6..73df8cdf 100644
--- a/tools/typescript/definitions/pdf_viewer_private.d.ts
+++ b/tools/typescript/definitions/pdf_viewer_private.d.ts
@@ -33,6 +33,7 @@
           url: string, callback: (isAllowed: boolean) => void): void;
       export function isPdfOcrAlwaysActive(
           callback: (isAlwaysActive: boolean) => void): void;
+      export function setPdfDocumentTitle(title: string): void;
       export function setPdfOcrPref(
           isAlwaysActive: boolean, callback: (isSet: boolean) => void): void;
       export function setPdfPluginAttributes(attributes: PdfPluginAttributes):
diff --git a/tools/typescript/path_mappings.py b/tools/typescript/path_mappings.py
index 4bfaa654..9677195 100644
--- a/tools/typescript/path_mappings.py
+++ b/tools/typescript/path_mappings.py
@@ -40,13 +40,6 @@
     )]
 
 
-def _add_typescript_definitions_mappings(path_mappings, root_src_dir):
-  path_mappings[f'//tools/typescript/definitions:library'] = [
-      ('/tools/typescript/definitions/*',
-       f'{root_src_dir}/tools/typescript/definitions/*')
-  ]
-
-
 def _add_third_party_polymer_mappings(path_mappings, root_src_dir):
   path_mappings[f'//third_party/polymer/v3_0:library'] = [
       ('//resources/polymer/v3_0/polymer/polymer_bundled.min.js',
@@ -113,7 +106,6 @@
 def GetDepToPathMappings(root_gen_dir, root_src_dir, platform):
   path_mappings = {}
 
-  _add_typescript_definitions_mappings(path_mappings, root_src_dir)
   _add_ui_webui_resources_mappings(path_mappings, root_gen_dir)
   _add_third_party_polymer_mappings(path_mappings, root_src_dir)
   _add_third_party_lit_mappings(path_mappings, root_gen_dir)
diff --git a/tools/typescript/ts_library.gni b/tools/typescript/ts_library.gni
index b5fd10d..3750d3f 100644
--- a/tools/typescript/ts_library.gni
+++ b/tools/typescript/ts_library.gni
@@ -16,7 +16,6 @@
                              "in_files",
                              "tsconfig_base",
                              "manifest_excludes",
-                             "path_mappings",
                              "testonly",
                              "visibility",
                            ])
@@ -80,10 +79,6 @@
       args += [ "--in_files" ] + in_files
     }
 
-    if (defined(path_mappings)) {
-      args += [ "--path_mappings" ] + path_mappings
-    }
-
     if (defined(manifest_excludes)) {
       assert(defined(in_files))
       args += [ "--manifest_excludes" ] + manifest_excludes
@@ -148,6 +143,14 @@
       deps += extra_deps
     }
 
+    path_mappings = [
+      "/tools/typescript/definitions/*|" +
+          rebase_path("//tools/typescript/definitions/*", target_gen_dir),
+      # NOTE: path_mappings corresponding to files generated by
+      # other ts_library() deps are automatically inferred from |deps| in
+      # path_mappings.py. Don't add any such mappings here.
+    ]
+
     # The |platform| flag is used in path_mappings.py and validate_tsconfig.py,
     # to limit some logic to certain platforms, like preventing special iOS
     # exceptions being abused on other platforms.
@@ -164,5 +167,10 @@
         platform,
       ]
     }
+
+    args += [ "--path_mappings" ] + path_mappings
+    if (defined(invoker.path_mappings)) {
+      args += invoker.path_mappings
+    }
   }
 }
diff --git a/tools/typescript/validate_tsconfig.py b/tools/typescript/validate_tsconfig.py
index 45173a2..b47ad00 100644
--- a/tools/typescript/validate_tsconfig.py
+++ b/tools/typescript/validate_tsconfig.py
@@ -316,11 +316,9 @@
   # TODO(https://crbug.com/326005022): Determine if the following are actually
   # safe for computation of gn input values.
   exceptions_list = [
-      'third_party/lit/v3_0/',
       'third_party/material_web_components/',
       'third_party/node/node_modules/',
       'third_party/polymer/v3_0/',
-      'tools/typescript/definitions/',
       'tools/typescript/tests/',
   ]
   exceptions = [getPathFromCwd(e) for e in exceptions_list]
diff --git a/tools/utr/PRESUBMIT.py b/tools/utr/PRESUBMIT.py
new file mode 100644
index 0000000..06f9bca
--- /dev/null
+++ b/tools/utr/PRESUBMIT.py
@@ -0,0 +1,11 @@
+# Copyright 2024 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+PRESUBMIT_VERSION = '2.0.0'
+
+
+def CheckTests(input_api, output_api):
+  return input_api.RunTests(
+      input_api.canned_checks.GetUnitTestsInDirectory(input_api, output_api,
+                                                      '.', [r'.+_test\.py$']))
diff --git a/tools/utr/builders_test.py b/tools/utr/builders_test.py
index 58d80bab..cf6748ae 100755
--- a/tools/utr/builders_test.py
+++ b/tools/utr/builders_test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env vpython3
 # Copyright 2024 The Chromium Authors
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
@@ -29,18 +29,18 @@
 
   def testNoProps(self):
     # Empty base dir
-    self.assertEqual(builders.find_builder_props('some-bucket', 'some-builder'),
-                     None)
+    props, _ = builders.find_builder_props('some-bucket', 'some-builder')
+    self.assertIsNone(props)
 
     # Empty bucket dir
     os.makedirs(self.tmp_dir.joinpath('some-bucket'))
-    self.assertEqual(builders.find_builder_props('some-bucket', 'some-builder'),
-                     None)
+    props, _ = builders.find_builder_props('some-bucket', 'some-builder')
+    self.assertIsNone(props)
 
     # Empty builder dir
     os.makedirs(self.tmp_dir.joinpath('some-bucket', 'some-builder'))
-    self.assertEqual(builders.find_builder_props('some-bucket', 'some-builder'),
-                     None)
+    props, _ = builders.find_builder_props('some-bucket', 'some-builder')
+    self.assertIsNone(props)
 
   def testSomeProps(self):
     builder_dir = self.tmp_dir.joinpath('some-bucket', 'some-builder')
@@ -48,7 +48,7 @@
     with open(builder_dir.joinpath('properties.json'), 'w') as f:
       json.dump({'some-key': 'some-val'}, f)
 
-    props = builders.find_builder_props('some-bucket', 'some-builder')
+    props, _ = builders.find_builder_props('some-bucket', 'some-builder')
     self.assertEqual(props['some-key'], 'some-val')
 
 
diff --git a/tools/utr/recipe_test.py b/tools/utr/recipe_test.py
index 45c028a..e70919bc 100755
--- a/tools/utr/recipe_test.py
+++ b/tools/utr/recipe_test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env vpython3
 # Copyright 2024 The Chromium Authors
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
@@ -42,27 +42,28 @@
       exit_code, _ = runner.run_recipe()
       self.assertEqual(exit_code, 123)
 
-  def testJson(self):
+  @mock.patch('tempfile.TemporaryDirectory')
+  def testJson(self, mock_tmp_dir):
+    mock_tmp_dir.return_value.__enter__.return_value = self.tmp_dir
     runner = recipe.LegacyRunner(self.tmp_dir, {}, 'some-bucket',
                                  'some-builder', 'swarming-server', [], False,
                                  False)
-    with mock.patch('tempfile.TemporaryDirectory', return_value=self.tmp_dir):
-      with mock.patch('subprocess.Popen', return_value=self.subp_mock):
-        # Missing json file
-        _, error_msg = runner.run_recipe()
-        self.assertIsNone(error_msg)
+    with mock.patch('subprocess.Popen', return_value=self.subp_mock):
+      # Missing json file
+      _, error_msg = runner.run_recipe()
+      self.assertIsNone(error_msg)
 
-        # Broken json
-        with open(self.tmp_dir.joinpath('out.json'), 'w') as f:
-          f.write('this-is-not-json')
-        _, error_msg = runner.run_recipe()
-        self.assertIsNone(error_msg)
+      # Broken json
+      with open(self.tmp_dir.joinpath('out.json'), 'w') as f:
+        f.write('this-is-not-json')
+      _, error_msg = runner.run_recipe()
+      self.assertIsNone(error_msg)
 
-        # Actual json
-        with open(self.tmp_dir.joinpath('out.json'), 'w') as f:
-          json.dump({'failure': {'humanReason': 'it exploded'}}, f)
-        _, error_msg = runner.run_recipe()
-        self.assertEqual(error_msg, 'it exploded')
+      # Actual json
+      with open(self.tmp_dir.joinpath('out.json'), 'w') as f:
+        json.dump({'failure': {'humanReason': 'it exploded'}}, f)
+      _, error_msg = runner.run_recipe()
+      self.assertEqual(error_msg, 'it exploded')
 
 
 if __name__ == '__main__':
diff --git a/ui/file_manager/image_loader/BUILD.gn b/ui/file_manager/image_loader/BUILD.gn
index a24930ed..2148b9b 100644
--- a/ui/file_manager/image_loader/BUILD.gn
+++ b/ui/file_manager/image_loader/BUILD.gn
@@ -48,6 +48,7 @@
 
 dts_files = [
   "image_loader_private.d.ts",
+  "//tools/typescript/definitions/chrome_event.d.ts",
   "//tools/typescript/definitions/runtime.d.ts",
 ]
 
diff --git a/ui/file_manager/integration_tests/BUILD.gn b/ui/file_manager/integration_tests/BUILD.gn
index b1e43de4..ee2c1ea 100644
--- a/ui/file_manager/integration_tests/BUILD.gn
+++ b/ui/file_manager/integration_tests/BUILD.gn
@@ -101,6 +101,7 @@
   composite = true
 
   definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/chrome_test.d.ts",
     "//tools/typescript/definitions/runtime.d.ts",
     "//tools/typescript/definitions/file_system.d.ts",
diff --git a/ui/gl/direct_composition_support.cc b/ui/gl/direct_composition_support.cc
index acf61347..66a50d6a 100644
--- a/ui/gl/direct_composition_support.cc
+++ b/ui/gl/direct_composition_support.cc
@@ -27,6 +27,8 @@
 bool g_supports_overlays = false;
 // Whether the GPU can support hardware overlays or not.
 bool g_supports_hardware_overlays = false;
+// Whether video processor auto HDR is supported.
+bool g_supports_vp_auto_hdr = false;
 // Whether the DecodeSwapChain is disabled or not.
 bool g_disable_decode_swap_chain = false;
 // Whether to force the nv12 overlay support.
@@ -50,6 +52,11 @@
   return g_supports_hardware_overlays;
 }
 
+bool SupportsVideoProcessorAutoHDR() {
+  base::AutoLock auto_lock(GetOverlayLock());
+  return g_supports_vp_auto_hdr;
+}
+
 void SetSupportsOverlays(bool support) {
   base::AutoLock auto_lock(GetOverlayLock());
   g_supports_overlays = support;
@@ -60,6 +67,11 @@
   g_supports_hardware_overlays = support;
 }
 
+void SetSupportsVideoProcessorAutoHDR(bool support) {
+  base::AutoLock auto_lock(GetOverlayLock());
+  g_supports_vp_auto_hdr = support;
+}
+
 bool SupportsSoftwareOverlays() {
   return base::FeatureList::IsEnabled(
              features::kDirectCompositionSoftwareOverlays) &&
@@ -451,6 +463,106 @@
   UMA_HISTOGRAM_BOOLEAN("GPU.Output.HDR", g_system_hdr_enabled);
 }
 
+// Update video processor auto HDR feature support status.
+// Must be called on GpuMain thread.
+void UpdateVideoProcessorAutoHDRSupport() {
+  if (GetGlWorkarounds().disable_vp_auto_hdr) {
+    SetSupportsVideoProcessorAutoHDR(false);
+    return;
+  }
+
+  if (!base::FeatureList::IsEnabled(features::kNvidiaVpTrueHDR)) {
+    SetSupportsVideoProcessorAutoHDR(false);
+    return;
+  }
+
+  Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device = g_d3d11_device;
+  if (!d3d11_device) {
+    DLOG(ERROR) << "Failed to get device";
+    SetSupportsVideoProcessorAutoHDR(false);
+    return;
+  }
+
+  Microsoft::WRL::ComPtr<ID3D11DeviceContext> d3d11_context;
+  // D3D11 immediate context isn't allowed to be accessed simultaneously on two
+  // threads, and all other callers are using this on the GpuMain thread, so
+  // this function must be called on GpuMain thread.
+  d3d11_device->GetImmediateContext(&d3d11_context);
+  if (!d3d11_context) {
+    DLOG(ERROR) << "Failed to get context";
+    SetSupportsVideoProcessorAutoHDR(false);
+    return;
+  }
+
+  Microsoft::WRL::ComPtr<ID3D11VideoContext> d3d11_video_context;
+  if (FAILED(d3d11_context.As(&d3d11_video_context))) {
+    DLOG(ERROR) << "Failed to retrieve video context";
+    SetSupportsVideoProcessorAutoHDR(false);
+    return;
+  }
+
+  Microsoft::WRL::ComPtr<ID3D11VideoDevice> d3d11_video_device;
+  if (FAILED(d3d11_device.As(&d3d11_video_device))) {
+    DLOG(ERROR) << "Failed to retrieve video device";
+    SetSupportsVideoProcessorAutoHDR(false);
+    return;
+  }
+
+  D3D11_VIDEO_PROCESSOR_CONTENT_DESC desc;
+  desc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
+  desc.InputFrameRate.Numerator = 60;
+  desc.InputFrameRate.Denominator = 1;
+  desc.InputWidth = 1920;
+  desc.InputHeight = 1080;
+  desc.OutputFrameRate.Numerator = 60;
+  desc.OutputFrameRate.Denominator = 1;
+  desc.OutputWidth = 1920;
+  desc.OutputHeight = 1080;
+  desc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL;
+
+  Microsoft::WRL::ComPtr<ID3D11VideoProcessorEnumerator> d3d11_video_enumerator;
+  if (FAILED(d3d11_video_device->CreateVideoProcessorEnumerator(
+          &desc, &d3d11_video_enumerator))) {
+    DLOG(ERROR) << "Failed to create video processor enumerator";
+    SetSupportsVideoProcessorAutoHDR(false);
+    return;
+  }
+
+  Microsoft::WRL::ComPtr<ID3D11VideoProcessor> d3d11_video_processor;
+  if (FAILED(d3d11_video_device->CreateVideoProcessor(
+          d3d11_video_enumerator.Get(), 0, &d3d11_video_processor))) {
+    DLOG(ERROR) << "Failed to create video processor";
+    SetSupportsVideoProcessorAutoHDR(false);
+    return;
+  }
+
+  constexpr GUID kNvidiaTrueHDRInterfaceGUID = {
+      0xfdd62bb4,
+      0x620b,
+      0x4fd7,
+      {0x9a, 0xb3, 0x1e, 0x59, 0xd0, 0xd5, 0x44, 0xb3}};
+
+  UINT driver_supports_true_hdr = 0;
+  HRESULT hr = d3d11_video_context->VideoProcessorGetStreamExtension(
+      d3d11_video_processor.Get(), 0, &kNvidiaTrueHDRInterfaceGUID,
+      sizeof(driver_supports_true_hdr), &driver_supports_true_hdr);
+  if (FAILED(hr)) {
+    DLOG(ERROR) << "Failed to get stream extension with error 0x" << std::hex
+                << hr;
+    SetSupportsVideoProcessorAutoHDR(false);
+    return;
+  }
+
+  d3d11_video_processor.Reset();
+  d3d11_video_enumerator.Reset();
+  d3d11_video_context.Reset();
+  d3d11_video_device.Reset();
+  d3d11_context.Reset();
+  d3d11_device.Reset();
+
+  SetSupportsVideoProcessorAutoHDR(driver_supports_true_hdr == 1);
+}
+
 }  // namespace
 
 void InitializeDirectComposition(
@@ -509,6 +621,8 @@
   DCHECK(g_dcomp_device);
 
   g_d3d11_device = d3d11_device.Detach();
+
+  UpdateVideoProcessorAutoHDRSupport();
 }
 
 void ShutdownDirectComposition() {
@@ -584,6 +698,10 @@
   }
 }
 
+bool VideoProcessorAutoHDRSupported() {
+  return SupportsVideoProcessorAutoHDR();
+}
+
 bool CheckVideoProcessorFormatSupport(DXGI_FORMAT dxgi_format) {
   Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device = g_d3d11_device;
   if (!d3d11_device) {
@@ -863,6 +981,7 @@
 void DirectCompositionOverlayCapsMonitor::OnDisplayAdded() {
   SetOverlayCapsValid(false);
   UpdateOverlaySupport();
+  UpdateVideoProcessorAutoHDRSupport();
   UpdateMonitorInfo();
 
   NotifyOverlayCapsChanged();
@@ -872,6 +991,7 @@
 void DirectCompositionOverlayCapsMonitor::OnDisplayRemoved() {
   SetOverlayCapsValid(false);
   UpdateOverlaySupport();
+  UpdateVideoProcessorAutoHDRSupport();
   UpdateMonitorInfo();
 
   NotifyOverlayCapsChanged();
diff --git a/ui/gl/direct_composition_support.h b/ui/gl/direct_composition_support.h
index 495be43..6b0e5fe 100644
--- a/ui/gl/direct_composition_support.h
+++ b/ui/gl/direct_composition_support.h
@@ -64,6 +64,9 @@
 // Returns preferred overlay format set when detecting overlay support.
 GL_EXPORT DXGI_FORMAT GetDirectCompositionSDROverlayFormat();
 
+// Returns true if video processor auto HDR feature is supported.
+GL_EXPORT bool VideoProcessorAutoHDRSupported();
+
 // Returns true if video processor support handling the given format.
 GL_EXPORT bool CheckVideoProcessorFormatSupport(DXGI_FORMAT format);
 
diff --git a/ui/gl/gl_utils.h b/ui/gl/gl_utils.h
index b5cbddf..f4b6d55 100644
--- a/ui/gl/gl_utils.h
+++ b/ui/gl/gl_utils.h
@@ -52,6 +52,7 @@
   bool disable_es3gl_context_for_testing = false;
   bool disable_direct_composition = false;
   bool disable_direct_composition_video_overlays = false;
+  bool disable_vp_auto_hdr = false;
 };
 
 // Obtains the global GlWorkarounds. For use by ui/gl code to determine which
diff --git a/ui/webui/resources/cr_components/settings_prefs/BUILD.gn b/ui/webui/resources/cr_components/settings_prefs/BUILD.gn
index 4c6b619..c8f4d15 100644
--- a/ui/webui/resources/cr_components/settings_prefs/BUILD.gn
+++ b/ui/webui/resources/cr_components/settings_prefs/BUILD.gn
@@ -14,7 +14,10 @@
     "pref_util.ts",
   ]
 
-  ts_definitions = [ "//tools/typescript/definitions/settings_private.d.ts" ]
+  ts_definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
+    "//tools/typescript/definitions/settings_private.d.ts",
+  ]
   ts_composite = true
 
   # Note: Do not add a dep on ui/webui/resources/cr_elements:build_ts here, as
diff --git a/ui/webui/resources/cr_elements/BUILD.gn b/ui/webui/resources/cr_elements/BUILD.gn
index 51b5cba..0c14538 100644
--- a/ui/webui/resources/cr_elements/BUILD.gn
+++ b/ui/webui/resources/cr_elements/BUILD.gn
@@ -31,7 +31,6 @@
       "cr_drawer/cr_drawer.ts",
       "cr_expand_button/cr_expand_button.ts",
       "cr_feedback_buttons/cr_feedback_buttons.ts",
-      "cr_fingerprint/cr_fingerprint_progress_arc.ts",
       "cr_grid/cr_grid.ts",
       "cr_icon_button/cr_icon_button.ts",
       "cr_input/cr_input.ts",
@@ -68,7 +67,6 @@
     }
 
     icons_html_files = [
-      "cr_fingerprint/cr_fingerprint_icons.html",
       "icons.html",
       "mwb_shared_icons.html",
     ]
@@ -145,6 +143,7 @@
     ]
   }
   ts_definitions = [
+    "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/pending.d.ts",
     "//tools/typescript/definitions/settings_private.d.ts",
   ]
diff --git a/ui/webui/resources/cr_elements/cr_fingerprint/OWNERS b/ui/webui/resources/cr_elements/cr_fingerprint/OWNERS
deleted file mode 100644
index fc7e7853..0000000
--- a/ui/webui/resources/cr_elements/cr_fingerprint/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-nsatragno@chromium.org
-ckincaid@chromium.org
diff --git a/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc_externs.js b/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc_externs.js
deleted file mode 100644
index 0af8bb1..0000000
--- a/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc_externs.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/* Minimal externs file provided for places in the code that
- * still use JavaScript instead of TypeScript.
- * @externs
- */
-
-/**
- * @constructor
- * @extends {HTMLElement}
- */
-function CrFingerprintProgressArcElement() {}
-
-/**
- * @param {number} prevPercentComplete
- * @param {number} currPercentComplete
- * @param {boolean} isComplete
- */
-CrFingerprintProgressArcElement.prototype.setProgress = function(
-    prevPercentComplete, currPercentComplete, isComplete) {};
-
-/**
- * @param {boolean} shouldPlay
- */
-CrFingerprintProgressArcElement.prototype.setPlay = function(shouldPlay) {};
diff --git a/v8 b/v8
index 68087ab..5a0470b 160000
--- a/v8
+++ b/v8
@@ -1 +1 @@
-Subproject commit 68087ab41a76501a5364273a52cd395f0e7033b3
+Subproject commit 5a0470b96e8446ef6d29fa7847b8ca28ccf504dd