diff --git a/DEPS b/DEPS
index 926e1c09..602b79a 100644
--- a/DEPS
+++ b/DEPS
@@ -304,11 +304,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '408059b57e257fd41a60e08479a5ccfb96120633',
+  'skia_revision': 'bbac790eeb8ca694bb0eb2d59b6d13215749f17c',
   # 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': 'e438515e8357757c725cd50e598c546cdda00d22',
+  'v8_revision': '5448ae387c6731f01313c69801327515e7a261e1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
@@ -391,7 +391,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '9215bd9a9bdff053660d7ebdd5a8a5bdcb8157e5',
+  'devtools_frontend_revision': '91e9cf3c2ad4b3b43f5a3142ba260d82d124049f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -812,7 +812,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    '090bdb6f4fa6a593fe0da18b90685a8145e8528e',
+    'a556e9b707e3a86b5fd4c193873f4478a4f31dba',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -911,7 +911,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/linux-amd64',
-          'version': 'FMWls2ahHgWI-Ba_TqxcqGj9el_9e9BFO8qgzlyql2wC',
+          'version': 'wSNAAG4MNvRzb3S9kASqjikUafvdi4OJNnZs6n2r6A4C',
         },
       ],
       'dep_type': 'cipd',
@@ -922,7 +922,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/mac-amd64',
-          'version': 'xUaI7iwbas5hD4CAFYVUitiCmd_QZPb1YwkzRRUIEsEC',
+          'version': 'D5s9RYd41AlBzWew32n1dijF7DRBJ4yVwGEqF61jml8C',
         },
       ],
       'dep_type': 'cipd',
@@ -1248,7 +1248,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' + '@' + 'a314fc21810a828962258d6d258c4bdecfd28ce7',
+      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + 'ced6c04705b006a39bfaf0f0784c0a760b3e02d6',
     'condition': 'checkout_src_internal',
   },
 
@@ -1860,7 +1860,7 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@850909c8c350225f950463f611af8a7505368dc8',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@6e41699c8a41d9bb068e681437b363f5d57fb1e5',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907',
@@ -2031,7 +2031,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'QWD1zQcFupAjvLzrn4AJAOA09lPdRY2gytkRrC-Nwx8C',
+        'version': 'ABZq-_Ze-t3iqPVevzJMmQjSDf2N_zfWSD74_XU6STQC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 3f88eab..dd6fe7e 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1414,11 +1414,6 @@
     "system/hotspot/hotspot_detailed_view_controller.h",
     "system/hotspot/hotspot_feature_pod_controller.cc",
     "system/hotspot/hotspot_feature_pod_controller.h",
-    "system/hotspot/hotspot_icon.cc",
-    "system/hotspot/hotspot_icon.h",
-    "system/hotspot/hotspot_icon_animation.cc",
-    "system/hotspot/hotspot_icon_animation.h",
-    "system/hotspot/hotspot_icon_animation_observer.h",
     "system/hotspot/hotspot_info_cache.cc",
     "system/hotspot/hotspot_info_cache.h",
     "system/hotspot/hotspot_notifier.cc",
@@ -3284,7 +3279,6 @@
     "system/hotspot/hotspot_detailed_view_controller_unittest.cc",
     "system/hotspot/hotspot_detailed_view_unittest.cc",
     "system/hotspot/hotspot_feature_pod_controller_unittest.cc",
-    "system/hotspot/hotspot_icon_unittest.cc",
     "system/hotspot/hotspot_info_cache_unittest.cc",
     "system/hotspot/hotspot_notifier_unittest.cc",
     "system/hotspot/hotspot_tray_view_unittest.cc",
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 5686306..6423e34 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -816,6 +816,11 @@
              "ExoConsumedByImeByFlag",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+// Enables using an extended Wayland API for ConfirmCompositionText.
+BASE_FEATURE(kExoExtendedConfirmComposition,
+             "ExoExtendedConfirmComposition",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 // Enables to check KeyEvent flag to see if the event is consumed by IME
 // or not (=decides using heuristics based on key code etc.).
 BASE_FEATURE(kExoSurroundingTextOffset,
@@ -3059,6 +3064,10 @@
   return base::FeatureList::IsEnabled(kHandwritingLegacyRecognition);
 }
 
+bool IsLanguagePacksInOobeEnabled() {
+  return base::FeatureList::IsEnabled(kLanguagePacksInOobe);
+}
+
 bool IsLauncherNudgeShortIntervalEnabled() {
   return base::FeatureList::IsEnabled(kLauncherNudgeShortInterval);
 }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index a2410474..e996dc8 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -243,6 +243,8 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kExoLinuxDmabufModifiers);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kExoOrdinalMotion);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kExoConsumedByImeByFlag);
+COMPONENT_EXPORT(ASH_CONSTANTS)
+BASE_DECLARE_FEATURE(kExoExtendedConfirmComposition);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kExoSurroundingTextOffset);
 COMPONENT_EXPORT(ASH_CONSTANTS)
 BASE_DECLARE_FEATURE(kExperimentalRgbKeyboardPatterns);
@@ -837,6 +839,7 @@
 COMPONENT_EXPORT(ASH_CONSTANTS)
 bool IsKeyboardBacklightToggleEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsLanguagePacksEnabled();
+COMPONENT_EXPORT(ASH_CONSTANTS) bool IsLanguagePacksInOobeEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsLauncherNudgeShortIntervalEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsLauncherNudgeSessionResetEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsLicensePackagedOobeFlowEnabled();
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc
index aa4231f..a6516c2 100644
--- a/ash/login/ui/lock_contents_view.cc
+++ b/ash/login/ui/lock_contents_view.cc
@@ -652,6 +652,7 @@
     LOG(WARNING)
         << "LockContentsView::OnUsersChanged called during Authentication.";
   }
+  AuthEventsRecorder::Get()->OnLockContentsViewUpdate();
   // The debug view will potentially call this method many times. Make sure to
   // invalidate any child references.
   primary_big_view_ = nullptr;
@@ -2515,7 +2516,7 @@
 void LockContentsView::RecordAndResetPasswordAttempts(
     AuthEventsRecorder::AuthenticationOutcome outcome,
     AccountId account_id) {
-  AuthEventsRecorder::Get()->OnExistingUserLoginExit(
+  AuthEventsRecorder::Get()->OnExistingUserLoginScreenExit(
       outcome, unlock_attempt_by_user_[account_id]);
   unlock_attempt_by_user_[account_id] = 0;
 }
diff --git a/ash/login/ui/lock_screen.cc b/ash/login/ui/lock_screen.cc
index 89e67c3..4edf395e 100644
--- a/ash/login/ui/lock_screen.cc
+++ b/ash/login/ui/lock_screen.cc
@@ -49,6 +49,7 @@
       screen_type = AuthEventsRecorder::AuthenticationSurface::kLock;
       break;
   }
+  AuthEventsRecorder::Get()->ResetLoginData();
   AuthEventsRecorder::Get()->OnAuthenticationSurfaceChange(screen_type);
 }
 
diff --git a/ash/login/ui/login_auth_user_view.cc b/ash/login/ui/login_auth_user_view.cc
index 026bfc9..73299415 100644
--- a/ash/login/ui/login_auth_user_view.cc
+++ b/ash/login/ui/login_auth_user_view.cc
@@ -47,6 +47,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
+#include "chromeos/ash/components/login/auth/auth_events_recorder.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "components/user_manager/known_user.h"
 #include "components/user_manager/user.h"
@@ -1369,6 +1370,7 @@
 }
 
 void LoginAuthUserView::OnAuthSubmit(const std::u16string& password) {
+  AuthEventsRecorder::Get()->OnAuthSubmit();
   LOG(WARNING) << "crbug.com/1339004 : AuthSubmit "
                << password_view_->IsReadOnly() << " / "
                << pin_input_view_->IsReadOnly();
diff --git a/ash/login/ui/login_pin_input_view.cc b/ash/login/ui/login_pin_input_view.cc
index 33458a4..3d2bc9d8 100644
--- a/ash/login/ui/login_pin_input_view.cc
+++ b/ash/login/ui/login_pin_input_view.cc
@@ -14,6 +14,7 @@
 #include "base/functional/callback_helpers.h"
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chromeos/ash/components/login/auth/auth_events_recorder.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/accessibility/ax_enums.mojom-shared.h"
 #include "ui/accessibility/ax_node_data.h"
@@ -94,6 +95,7 @@
     absl::optional<std::string> user_input = GetCode();
     DCHECK(on_submit_);
     LOG(WARNING) << "crbug.com/1339004 : Submitting PIN " << IsReadOnly();
+    AuthEventsRecorder::Get()->OnPinSubmit();
     SetReadOnly(true);
     on_submit_.Run(base::UTF8ToUTF16(user_input.value_or(std::string())));
   }
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn
index ab1539bb..d015a87 100644
--- a/ash/resources/vector_icons/BUILD.gn
+++ b/ash/resources/vector_icons/BUILD.gn
@@ -115,10 +115,8 @@
     "holding_space_download.icon",
     "holding_space_refresh.icon",
     "hollow_check_circle.icon",
-    "hotspot_dot.icon",
     "hotspot_off.icon",
     "hotspot_on.icon",
-    "hotspot_one_arc.icon",
     "ime_menu_emoticon.icon",
     "ime_menu_microphone.icon",
     "ime_menu_on_screen_keyboard.icon",
diff --git a/ash/resources/vector_icons/hotspot_dot.icon b/ash/resources/vector_icons/hotspot_dot.icon
deleted file mode 100644
index 417d7f5..0000000
--- a/ash/resources/vector_icons/hotspot_dot.icon
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2023 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, 10.5f, 12,
-CUBIC_TO, 11.33f, 12, 12, 11.33f, 12, 10.5f,
-CUBIC_TO, 12, 9.67f, 11.33f, 9, 10.5f, 9,
-CUBIC_TO, 9.67f, 9, 9, 9.67f, 9, 10.5f,
-CUBIC_TO, 9, 11.33f, 9.67f, 12, 10.5f, 12,
-CLOSE
\ No newline at end of file
diff --git a/ash/resources/vector_icons/hotspot_one_arc.icon b/ash/resources/vector_icons/hotspot_one_arc.icon
deleted file mode 100644
index 93f3f31a..0000000
--- a/ash/resources/vector_icons/hotspot_one_arc.icon
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2023 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, 15.5f, 10.5f,
-CUBIC_TO, 15.5f, 7.78f, 13.26f, 5.5f, 10.5f, 5.5f,
-CUBIC_TO, 7.74f, 5.5f, 5.5f, 7.78f, 5.5f, 10.5f,
-CUBIC_TO, 5.5f, 12.48f, 6.51f, 14.12f, 8, 15,
-LINE_TO, 9, 13.5f,
-CUBIC_TO, 7.84f, 12.93f, 7.17f, 11.85f, 7, 10.5f,
-CUBIC_TO, 7.17f, 8.72f, 8.66f, 7.2f, 10.5f, 7,
-CUBIC_TO, 12.34f, 7.2f, 13.83f, 8.72f, 14, 10.5f,
-CUBIC_TO, 13.83f, 11.85f, 13.16f, 12.93f, 12, 13.5f,
-LINE_TO, 13, 15,
-CUBIC_TO, 14.49f, 14.12f, 15.5f, 12.48f, 15.5f, 10.5f,
-CLOSE,
-NEW_PATH,
-MOVE_TO, 10.5f, 12,
-CUBIC_TO, 11.33f, 12, 12, 11.33f, 12, 10.5f,
-CUBIC_TO, 12, 9.67f, 11.33f, 9, 10.5f, 9,
-CUBIC_TO, 9.67f, 9, 9, 9.67f, 9, 10.5f,
-CUBIC_TO, 9, 11.33f, 9.67f, 12, 10.5f, 12,
-CLOSE
\ No newline at end of file
diff --git a/ash/shell.cc b/ash/shell.cc
index ceea101..66f57bc3 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -135,7 +135,6 @@
 #include "ash/system/federated/federated_service_controller_impl.h"
 #include "ash/system/firmware_update/firmware_update_notification_controller.h"
 #include "ash/system/geolocation/geolocation_controller.h"
-#include "ash/system/hotspot/hotspot_icon_animation.h"
 #include "ash/system/hotspot/hotspot_info_cache.h"
 #include "ash/system/human_presence/human_presence_orientation_controller.h"
 #include "ash/system/human_presence/snooping_protection_controller.h"
@@ -1572,7 +1571,6 @@
   }
 
   if (features::IsHotspotEnabled()) {
-    hotspot_icon_animation_ = std::make_unique<HotspotIconAnimation>();
     hotspot_info_cache_ = std::make_unique<HotspotInfoCache>();
   }
 
diff --git a/ash/shell.h b/ash/shell.h
index 262a460..e8d5f1f7 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -156,7 +156,6 @@
 class GlanceablesV2Controller;
 class ColorEnhancementController;
 class HoldingSpaceController;
-class HotspotIconAnimation;
 class HotspotInfoCache;
 class HumanPresenceOrientationController;
 class ImeControllerImpl;
@@ -559,9 +558,6 @@
   ColorEnhancementController* color_enhancement_controller() {
     return color_enhancement_controller_.get();
   }
-  HotspotIconAnimation* hotspot_icon_animation() {
-    return hotspot_icon_animation_.get();
-  }
   HotspotInfoCache* hotspot_info_cache() { return hotspot_info_cache_.get(); }
   HumanPresenceOrientationController* human_presence_orientation_controller() {
     return human_presence_orientation_controller_.get();
@@ -1111,7 +1107,6 @@
   std::unique_ptr<DisplayColorManager> display_color_manager_;
   std::unique_ptr<DisplayErrorObserver> display_error_observer_;
   std::unique_ptr<ProjectingObserver> projecting_observer_;
-  std::unique_ptr<HotspotIconAnimation> hotspot_icon_animation_;
   std::unique_ptr<HotspotInfoCache> hotspot_info_cache_;
   std::unique_ptr<display::DisplayPortObserver> display_port_observer_;
 
diff --git a/ash/system/hotspot/hotspot_detailed_view.cc b/ash/system/hotspot/hotspot_detailed_view.cc
index f55206c1..51008934 100644
--- a/ash/system/hotspot/hotspot_detailed_view.cc
+++ b/ash/system/hotspot/hotspot_detailed_view.cc
@@ -12,8 +12,6 @@
 #include "ash/style/rounded_container.h"
 #include "ash/style/switch.h"
 #include "ash/style/typography.h"
-#include "ash/system/hotspot/hotspot_icon.h"
-#include "ash/system/hotspot/hotspot_icon_animation.h"
 #include "ash/system/model/system_tray_model.h"
 #include "ash/system/tray/detailed_view_delegate.h"
 #include "ash/system/tray/hover_highlight_view.h"
@@ -61,21 +59,14 @@
   CreateContainer();
 }
 
-HotspotDetailedView::~HotspotDetailedView() {
-  Shell::Get()->hotspot_icon_animation()->RemoveObserver(this);
-}
+HotspotDetailedView::~HotspotDetailedView() = default;
 
 void HotspotDetailedView::UpdateViewForHotspot(HotspotInfoPtr hotspot_info) {
-  if (hotspot_info->state == HotspotState::kEnabling) {
-    Shell::Get()->hotspot_icon_animation()->AddObserver(this);
-  } else if (state_ == HotspotState::kEnabling) {
-    Shell::Get()->hotspot_icon_animation()->RemoveObserver(this);
-  }
-
-  if (state_ != hotspot_info->state) {
-    state_ = hotspot_info->state;
-    UpdateIcon();
-  }
+  // Update the Hotspot icon.
+  hotspot_icon_->SetImage(ui::ImageModel::FromVectorIcon(
+      IsEnabledOrEnabling(hotspot_info->state) ? kHotspotOnIcon
+                                               : kHotspotOffIcon,
+      cros_tokens::kCrosSysOnSurface));
 
   UpdateSubText(hotspot_info);
   UpdateToggleState(hotspot_info->state, hotspot_info->allow_status);
@@ -126,8 +117,6 @@
   auto hotspot_icon = std::make_unique<views::ImageView>();
   hotspot_icon->SetID(
       static_cast<int>(HotspotDetailedViewChildId::kHotspotIcon));
-  hotspot_icon->SetImage(ui::ImageModel::FromVectorIcon(
-      kHotspotOffIcon, cros_tokens::kCrosSysOnSurface));
   hotspot_icon_ = hotspot_icon.get();
   entry_row_->AddViewAndLabel(std::move(hotspot_icon), u"");
   entry_row_->text_label()->SetText(l10n_util::GetStringFUTF16(
@@ -169,15 +158,6 @@
   delegate_->OnToggleClicked(new_state);
 }
 
-void HotspotDetailedView::HotspotIconChanged() {
-  UpdateIcon();
-}
-
-void HotspotDetailedView::UpdateIcon() {
-  hotspot_icon_->SetImage(ui::ImageModel::FromVectorIcon(
-      hotspot_icon::GetIconForHotspot(state_), cros_tokens::kCrosSysOnSurface));
-}
-
 void HotspotDetailedView::UpdateToggleState(
     const HotspotState& state,
     const HotspotAllowStatus& allow_status) {
diff --git a/ash/system/hotspot/hotspot_detailed_view.h b/ash/system/hotspot/hotspot_detailed_view.h
index e96a1ae..a78e5b8 100644
--- a/ash/system/hotspot/hotspot_detailed_view.h
+++ b/ash/system/hotspot/hotspot_detailed_view.h
@@ -6,7 +6,6 @@
 #define ASH_SYSTEM_HOTSPOT_HOTSPOT_DETAILED_VIEW_H_
 
 #include "ash/ash_export.h"
-#include "ash/system/hotspot/hotspot_icon_animation_observer.h"
 #include "ash/system/tray/tray_detailed_view.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
@@ -28,8 +27,7 @@
 // This class defines both the interface used to interact with the detailed
 // Hotspot page within the quick settings. This class includes the declaration
 // for the delegate interface it uses to propagate user interactions.
-class ASH_EXPORT HotspotDetailedView : public TrayDetailedView,
-                                       public HotspotIconAnimationObserver {
+class ASH_EXPORT HotspotDetailedView : public TrayDetailedView {
  public:
   METADATA_HEADER(HotspotDetailedView);
 
@@ -56,9 +54,6 @@
   void HandleViewClicked(views::View* view) override;
   void CreateExtraTitleRowButtons() override;
 
-  // HotspotIconAnimationObserver:
-  void HotspotIconChanged() override;
-
  private:
   friend class HotspotDetailedViewControllerTest;
   friend class HotspotDetailedViewTest;
@@ -85,7 +80,6 @@
   // Handles toggling Hotspot via the UI to `new_state`.
   void ToggleHotspot(bool new_state);
 
-  void UpdateIcon();
   void UpdateToggleState(
       const hotspot_config::mojom::HotspotState& state,
       const hotspot_config::mojom::HotspotAllowStatus& allow_status);
@@ -93,9 +87,6 @@
   void UpdateExtraIcon(
       const hotspot_config::mojom::HotspotAllowStatus& allow_status);
 
-  hotspot_config::mojom::HotspotState state_ =
-      hotspot_config::mojom::HotspotState::kDisabled;
-
   const raw_ptr<Delegate, ExperimentalAsh> delegate_;
 
   // Owned by views hierarchy.
diff --git a/ash/system/hotspot/hotspot_detailed_view_unittest.cc b/ash/system/hotspot/hotspot_detailed_view_unittest.cc
index b784b329..f44c448 100644
--- a/ash/system/hotspot/hotspot_detailed_view_unittest.cc
+++ b/ash/system/hotspot/hotspot_detailed_view_unittest.cc
@@ -4,9 +4,7 @@
 
 #include "ash/system/hotspot/hotspot_detailed_view.h"
 
-#include "ash/constants/ash_features.h"
 #include "ash/public/cpp/test/test_system_tray_client.h"
-#include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/style/rounded_container.h"
 #include "ash/style/switch.h"
@@ -14,11 +12,6 @@
 #include "ash/system/tray/hover_highlight_view.h"
 #include "ash/test/ash_test_base.h"
 #include "base/memory/raw_ptr.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/test/task_environment.h"
-#include "chromeos/ash/services/hotspot_config/public/cpp/cros_hotspot_config_test_helper.h"
-#include "ui/chromeos/styles/cros_tokens_color_mappings.h"
-#include "ui/gfx/image/image_unittest_util.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/test/views_test_utils.h"
@@ -66,18 +59,10 @@
 
 class HotspotDetailedViewTest : public AshTestBase {
  public:
-  HotspotDetailedViewTest()
-      : AshTestBase(std::make_unique<base::test::TaskEnvironment>(
-            base::test::TaskEnvironment::MainThreadType::UI,
-            base::test::TaskEnvironment::TimeSource::MOCK_TIME)) {}
+  HotspotDetailedViewTest() = default;
   ~HotspotDetailedViewTest() override = default;
 
   void SetUp() override {
-    scoped_feature_list_.InitWithFeatures(
-        {features::kHotspot, features::kQsRevamp}, {});
-    cros_hotspot_config_test_helper_ =
-        std::make_unique<hotspot_config::CrosHotspotConfigTestHelper>(
-            /*use_fake_implementation=*/true);
     AshTestBase::SetUp();
 
     auto hotspot_detailed_view = std::make_unique<HotspotDetailedView>(
@@ -93,7 +78,6 @@
     widget_.reset();
 
     AshTestBase::TearDown();
-    cros_hotspot_config_test_helper_.reset();
   }
 
   void UpdateHotspotView(HotspotState state,
@@ -121,11 +105,6 @@
         HotspotDetailedView::HotspotDetailedViewChildId::kToggle);
   }
 
-  views::ImageView* GetHotspotIcon() {
-    return FindViewById<views::ImageView*>(
-        HotspotDetailedView::HotspotDetailedViewChildId::kHotspotIcon);
-  }
-
   views::ImageView* GetExtraIcon() {
     return FindViewById<views::ImageView*>(
         HotspotDetailedView::HotspotDetailedViewChildId::kExtraIcon);
@@ -175,9 +154,6 @@
         hotspot_detailed_view_->GetViewByID(static_cast<int>(id)));
   }
 
-  base::test::ScopedFeatureList scoped_feature_list_;
-  std::unique_ptr<hotspot_config::CrosHotspotConfigTestHelper>
-      cros_hotspot_config_test_helper_;
   std::unique_ptr<views::Widget> widget_;
   FakeHotspotDetailedViewDelegate hotspot_detailed_view_delegate_;
   FakeDetailedViewDelegate detailed_view_delegate_;
@@ -215,11 +191,6 @@
   AssertToggleOn(/*expected_toggle_on=*/true);
   views::ImageView* extra_icon = GetExtraIcon();
   EXPECT_FALSE(extra_icon->GetVisible());
-  views::ImageView* hotspot_icon = GetHotspotIcon();
-  ASSERT_TRUE(hotspot_icon);
-  ui::ImageModel image_model = ui::ImageModel::FromVectorIcon(
-      kHotspotOnIcon, cros_tokens::kCrosSysOnSurface);
-  EXPECT_EQ(image_model, hotspot_icon->GetImageModel());
 
   UpdateHotspotView(HotspotState::kEnabled, HotspotAllowStatus::kAllowed, 1);
   AssertSubtextLabel(u"1 device connected");
@@ -238,20 +209,6 @@
   AssertToggleOn(/*expected_toggle_on=*/true);
   views::ImageView* extra_icon = GetExtraIcon();
   EXPECT_FALSE(extra_icon->GetVisible());
-  views::ImageView* hotspot_icon = GetHotspotIcon();
-  ASSERT_TRUE(hotspot_icon);
-  ui::ImageModel image_model = ui::ImageModel::FromVectorIcon(
-      kHotspotDotIcon, cros_tokens::kCrosSysOnSurface);
-  EXPECT_EQ(image_model, hotspot_icon->GetImageModel());
-  // Verifies the hotspot icon is animating when enabling.
-  task_environment()->FastForwardBy(base::Milliseconds(500));
-  image_model = ui::ImageModel::FromVectorIcon(kHotspotOneArcIcon,
-                                               cros_tokens::kCrosSysOnSurface);
-  EXPECT_EQ(image_model, hotspot_icon->GetImageModel());
-  task_environment()->FastForwardBy(base::Milliseconds(500));
-  image_model = ui::ImageModel::FromVectorIcon(kHotspotOnIcon,
-                                               cros_tokens::kCrosSysOnSurface);
-  EXPECT_EQ(image_model, hotspot_icon->GetImageModel());
 }
 
 TEST_F(HotspotDetailedViewTest, HotspotDisablingUI) {
@@ -264,11 +221,6 @@
   AssertToggleOn(/*expected_toggle_on=*/false);
   views::ImageView* extra_icon = GetExtraIcon();
   EXPECT_FALSE(extra_icon->GetVisible());
-  views::ImageView* hotspot_icon = GetHotspotIcon();
-  ASSERT_TRUE(hotspot_icon);
-  ui::ImageModel image_model = ui::ImageModel::FromVectorIcon(
-      kHotspotOffIcon, cros_tokens::kCrosSysOnSurface);
-  EXPECT_EQ(image_model, hotspot_icon->GetImageModel());
 }
 
 TEST_F(HotspotDetailedViewTest, HotspotDisabledAndAllowedUI) {
@@ -281,11 +233,6 @@
   AssertToggleOn(/*expected_toggle_on=*/false);
   views::ImageView* extra_icon = GetExtraIcon();
   EXPECT_FALSE(extra_icon->GetVisible());
-  views::ImageView* hotspot_icon = GetHotspotIcon();
-  ASSERT_TRUE(hotspot_icon);
-  ui::ImageModel image_model = ui::ImageModel::FromVectorIcon(
-      kHotspotOffIcon, cros_tokens::kCrosSysOnSurface);
-  EXPECT_EQ(image_model, hotspot_icon->GetImageModel());
 }
 
 TEST_F(HotspotDetailedViewTest, HotspotDisabledAndNoMobileNetworkUI) {
@@ -299,11 +246,6 @@
   AssertToggleOn(/*expected_toggle_on=*/false);
   views::ImageView* extra_icon = GetExtraIcon();
   EXPECT_FALSE(extra_icon->GetVisible());
-  views::ImageView* hotspot_icon = GetHotspotIcon();
-  ASSERT_TRUE(hotspot_icon);
-  ui::ImageModel image_model = ui::ImageModel::FromVectorIcon(
-      kHotspotOffIcon, cros_tokens::kCrosSysOnSurface);
-  EXPECT_EQ(image_model, hotspot_icon->GetImageModel());
 }
 
 TEST_F(HotspotDetailedViewTest,
@@ -320,11 +262,6 @@
   EXPECT_TRUE(extra_icon->GetVisible());
   EXPECT_EQ(u"Your mobile network doesn't support hotspot",
             extra_icon->GetTooltipText());
-  views::ImageView* hotspot_icon = GetHotspotIcon();
-  ASSERT_TRUE(hotspot_icon);
-  ui::ImageModel image_model = ui::ImageModel::FromVectorIcon(
-      kHotspotOffIcon, cros_tokens::kCrosSysOnSurface);
-  EXPECT_EQ(image_model, hotspot_icon->GetImageModel());
 }
 
 TEST_F(HotspotDetailedViewTest, HotspotDisabledAndBlockedByPolicyUI) {
@@ -340,11 +277,6 @@
   EXPECT_TRUE(extra_icon->GetVisible());
   EXPECT_EQ(u"This setting is managed by your administrator",
             extra_icon->GetTooltipText());
-  views::ImageView* hotspot_icon = GetHotspotIcon();
-  ASSERT_TRUE(hotspot_icon);
-  ui::ImageModel image_model = ui::ImageModel::FromVectorIcon(
-      kHotspotOffIcon, cros_tokens::kCrosSysOnSurface);
-  EXPECT_EQ(image_model, hotspot_icon->GetImageModel());
 }
 
 TEST_F(HotspotDetailedViewTest, PressingEntryRowNotifiesDelegate) {
diff --git a/ash/system/hotspot/hotspot_feature_pod_controller.cc b/ash/system/hotspot/hotspot_feature_pod_controller.cc
index ef54342..bc3f28f 100644
--- a/ash/system/hotspot/hotspot_feature_pod_controller.cc
+++ b/ash/system/hotspot/hotspot_feature_pod_controller.cc
@@ -9,8 +9,6 @@
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
-#include "ash/system/hotspot/hotspot_icon.h"
-#include "ash/system/hotspot/hotspot_icon_animation.h"
 #include "ash/system/hotspot/hotspot_info_cache.h"
 #include "ash/system/unified/feature_tile.h"
 #include "ash/system/unified/unified_system_tray_controller.h"
@@ -36,9 +34,7 @@
       hotspot_config_observer_receiver_.BindNewPipeAndPassRemote());
 }
 
-HotspotFeaturePodController::~HotspotFeaturePodController() {
-  Shell::Get()->hotspot_icon_animation()->RemoveObserver(this);
-}
+HotspotFeaturePodController::~HotspotFeaturePodController() = default;
 
 FeaturePodButton* HotspotFeaturePodController::CreateButton() {
   NOTREACHED();
@@ -100,11 +96,6 @@
 
 void HotspotFeaturePodController::OnGetHotspotInfo(
     HotspotInfoPtr hotspot_info) {
-  if (hotspot_info->state == HotspotState::kEnabling) {
-    Shell::Get()->hotspot_icon_animation()->AddObserver(this);
-  } else if (hotspot_info_ && hotspot_info_->state == HotspotState::kEnabling) {
-    Shell::Get()->hotspot_icon_animation()->RemoveObserver(this);
-  }
   hotspot_info_ = std::move(hotspot_info);
 
   UpdateTileState();
@@ -127,14 +118,10 @@
   tile_->SetVisible(true);
   tile_->SetEnabled(true);
   tile_->SetToggled(hotspot_info_->state != HotspotState::kDisabled);
+  tile_->SetVectorIcon(ComputeIcon());
   tile_->SetSubLabel(ComputeSublabel());
   tile_->SetIconButtonTooltipText(ComputeIconTooltip());
   tile_->SetTooltipText(ComputeTileTooltip());
-  tile_->SetVectorIcon(hotspot_icon::GetIconForHotspot(hotspot_info_->state));
-}
-
-void HotspotFeaturePodController::HotspotIconChanged() {
-  tile_->SetVectorIcon(hotspot_icon::GetIconForHotspot(hotspot_info_->state));
 }
 
 void HotspotFeaturePodController::EnableHotspotIfAllowedAndDiveIn() {
diff --git a/ash/system/hotspot/hotspot_feature_pod_controller.h b/ash/system/hotspot/hotspot_feature_pod_controller.h
index 08b5588..2ece4cdb 100644
--- a/ash/system/hotspot/hotspot_feature_pod_controller.h
+++ b/ash/system/hotspot/hotspot_feature_pod_controller.h
@@ -9,7 +9,6 @@
 
 #include "ash/ash_export.h"
 #include "ash/constants/quick_settings_catalogs.h"
-#include "ash/system/hotspot/hotspot_icon_animation_observer.h"
 #include "ash/system/unified/feature_pod_controller_base.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
@@ -30,7 +29,6 @@
 // detailed page with a Hotspot info.
 class ASH_EXPORT HotspotFeaturePodController
     : public FeaturePodControllerBase,
-      public HotspotIconAnimationObserver,
       public hotspot_config::mojom::CrosHotspotConfigObserver {
  public:
   explicit HotspotFeaturePodController(
@@ -47,9 +45,6 @@
   void OnIconPressed() override;
   void OnLabelPressed() override;
 
-  // HotspotIconAnimationObserver:
-  void HotspotIconChanged() override;
-
  private:
   // mojom::CrosHotspotConfigObserver:
   void OnHotspotInfoChanged() override;
diff --git a/ash/system/hotspot/hotspot_feature_pod_controller_unittest.cc b/ash/system/hotspot/hotspot_feature_pod_controller_unittest.cc
index bba6c89..38914e2 100644
--- a/ash/system/hotspot/hotspot_feature_pod_controller_unittest.cc
+++ b/ash/system/hotspot/hotspot_feature_pod_controller_unittest.cc
@@ -17,7 +17,6 @@
 #include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
-#include "base/test/task_environment.h"
 #include "chromeos/ash/services/hotspot_config/public/cpp/cros_hotspot_config_test_helper.h"
 #include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -40,10 +39,7 @@
 
 class HotspotFeaturePodControllerTest : public AshTestBase {
  public:
-  HotspotFeaturePodControllerTest()
-      : AshTestBase(std::make_unique<base::test::TaskEnvironment>(
-            base::test::TaskEnvironment::MainThreadType::UI,
-            base::test::TaskEnvironment::TimeSource::MOCK_TIME)) {}
+  HotspotFeaturePodControllerTest() = default;
   ~HotspotFeaturePodControllerTest() override = default;
 
   void SetUp() override {
@@ -111,10 +107,6 @@
     base::RunLoop().RunUntilIdle();
   }
 
-  const char* GetVectorIconName() {
-    return hotspot_feature_tile_->vector_icon_->name;
-  }
-
   void ExpectHotspotDetailedViewShown() {
     TrayDetailedView* detailed_view = GetPrimaryUnifiedSystemTray()
                                           ->bubble()
@@ -152,7 +144,6 @@
   UpdateHotspotInfo(HotspotState::kEnabled, HotspotAllowStatus::kAllowed, 2);
   EXPECT_EQ(u"Toggle Hotspot. Hotspot is on, 2 devices connected.",
             hotspot_feature_tile_->icon_button()->GetTooltipText());
-  EXPECT_STREQ(kHotspotOnIcon.name, GetVectorIconName());
 
   // Press on the label should navigate to the detailed page without toggle
   // hotspot.
@@ -174,7 +165,6 @@
             hotspot_feature_tile_->icon_button()->GetTooltipText());
   EXPECT_EQ(u"Show hotspot details. Hotspot is on.",
             hotspot_feature_tile_->GetTooltipText());
-  EXPECT_STREQ(kHotspotOnIcon.name, GetVectorIconName());
 
   // Press on the icon should toggle hotspot.
   PressIcon();
@@ -197,12 +187,6 @@
             hotspot_feature_tile_->icon_button()->GetTooltipText());
   EXPECT_EQ(u"Show hotspot details. Hotspot is enabling.",
             hotspot_feature_tile_->GetTooltipText());
-  EXPECT_STREQ(kHotspotDotIcon.name, GetVectorIconName());
-  // Verifies the hotspot icon is animating when enabling.
-  task_environment()->FastForwardBy(base::Milliseconds(500));
-  EXPECT_STREQ(kHotspotOneArcIcon.name, GetVectorIconName());
-  task_environment()->FastForwardBy(base::Milliseconds(500));
-  EXPECT_STREQ(kHotspotOnIcon.name, GetVectorIconName());
 
   // Press on the icon should navigate to the detailed page but not to toggle
   // hotspot.
@@ -226,7 +210,6 @@
             hotspot_feature_tile_->icon_button()->GetTooltipText());
   EXPECT_EQ(u"Show hotspot details. Hotspot is disabling.",
             hotspot_feature_tile_->GetTooltipText());
-  EXPECT_STREQ(kHotspotOffIcon.name, GetVectorIconName());
 
   // Press on the icon should navigate to the detailed page but not to toggle
   // hotspot.
@@ -251,7 +234,6 @@
             hotspot_feature_tile_->icon_button()->GetTooltipText());
   EXPECT_EQ(u"Toggle Hotspot. Hotspot is off.",
             hotspot_feature_tile_->GetTooltipText());
-  EXPECT_STREQ(kHotspotOffIcon.name, GetVectorIconName());
 
   // Press on the icon should toggle hotspot and navigate to the detailed page.
   PressIcon();
@@ -275,7 +257,6 @@
             hotspot_feature_tile_->icon_button()->GetTooltipText());
   EXPECT_EQ(u"Toggle Hotspot. Hotspot is off.",
             hotspot_feature_tile_->GetTooltipText());
-  EXPECT_STREQ(kHotspotOffIcon.name, GetVectorIconName());
 
   // Press on the drive in label should toggle hotspot and navigate to the
   // detailed page.
@@ -301,7 +282,6 @@
             hotspot_feature_tile_->icon_button()->GetTooltipText());
   EXPECT_EQ(u"Show hotspot details. Hotspot is off.",
             hotspot_feature_tile_->GetTooltipText());
-  EXPECT_STREQ(kHotspotOffIcon.name, GetVectorIconName());
 
   // Press on the icon should navigate to the detailed page but not to toggle
   // hotspot.
@@ -328,7 +308,6 @@
       hotspot_feature_tile_->icon_button()->GetTooltipText());
   EXPECT_EQ(u"Show hotspot details. Hotspot is off.",
             hotspot_feature_tile_->GetTooltipText());
-  EXPECT_STREQ(kHotspotOffIcon.name, GetVectorIconName());
 
   // Press on the icon should navigate to the detailed page but not to toggle
   // hotspot.
@@ -353,7 +332,6 @@
             hotspot_feature_tile_->icon_button()->GetTooltipText());
   EXPECT_EQ(u"Show hotspot details. Hotspot is off.",
             hotspot_feature_tile_->GetTooltipText());
-  EXPECT_STREQ(kHotspotOffIcon.name, GetVectorIconName());
 
   // Press on the icon should navigate to the detailed page but not to toggle
   // hotspot.
@@ -378,7 +356,6 @@
             hotspot_feature_tile_->icon_button()->GetTooltipText());
   EXPECT_EQ(u"Toggle Hotspot. Hotspot is off.",
             hotspot_feature_tile_->GetTooltipText());
-  EXPECT_STREQ(kHotspotOffIcon.name, GetVectorIconName());
 
   // Press on the icon should toggle hotspot and navigate to the detailed page.
   PressIcon();
diff --git a/ash/system/hotspot/hotspot_icon.cc b/ash/system/hotspot/hotspot_icon.cc
deleted file mode 100644
index 5c1e94d..0000000
--- a/ash/system/hotspot/hotspot_icon.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/system/hotspot/hotspot_icon.h"
-
-#include <utility>
-
-#include "ash/resources/vector_icons/vector_icons.h"
-#include "ash/shell.h"
-#include "ash/system/hotspot/hotspot_icon_animation.h"
-#include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom.h"
-
-namespace ash {
-
-using hotspot_config::mojom::HotspotState;
-
-namespace {
-
-constexpr int kNumEnablingImages = 3;
-
-}  // namespace
-
-namespace hotspot_icon {
-
-const gfx::VectorIcon& GetIconForHotspot(const HotspotState& hotspot_state) {
-  if (hotspot_state == HotspotState::kEnabling) {
-    double animation = Shell::Get()->hotspot_icon_animation()->GetAnimation();
-    int index =
-        animation * nextafter(static_cast<float>(kNumEnablingImages), 0);
-    index = std::clamp(index, 0, kNumEnablingImages - 1);
-    if (index == 0) {
-      return kHotspotDotIcon;
-    }
-    if (index == 1) {
-      return kHotspotOneArcIcon;
-    }
-    return kHotspotOnIcon;
-  }
-
-  if (hotspot_state == HotspotState::kEnabled) {
-    return kHotspotOnIcon;
-  }
-  return kHotspotOffIcon;
-}
-
-}  //  namespace hotspot_icon
-}  //  namespace ash
diff --git a/ash/system/hotspot/hotspot_icon.h b/ash/system/hotspot/hotspot_icon.h
deleted file mode 100644
index 4383370..0000000
--- a/ash/system/hotspot/hotspot_icon.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_SYSTEM_HOTSPOT_HOTSPOT_ICON_H_
-#define ASH_SYSTEM_HOTSPOT_HOTSPOT_ICON_H_
-
-#include "ash/ash_export.h"
-#include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom-forward.h"
-
-namespace gfx {
-struct VectorIcon;
-}  // namespace gfx
-
-namespace ash::hotspot_icon {
-
-// Get the hotspot icon for the given `hotspot_state`.
-ASH_EXPORT const gfx::VectorIcon& GetIconForHotspot(
-    const hotspot_config::mojom::HotspotState& hotspot_state);
-
-}  // namespace ash::hotspot_icon
-
-#endif  // ASH_SYSTEM_HOTSPOT_HOTSPOT_ICON_H_
diff --git a/ash/system/hotspot/hotspot_icon_animation.cc b/ash/system/hotspot/hotspot_icon_animation.cc
deleted file mode 100644
index 10a3fb2..0000000
--- a/ash/system/hotspot/hotspot_icon_animation.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/system/hotspot/hotspot_icon_animation.h"
-
-#include "ash/system/hotspot/hotspot_icon_animation_observer.h"
-
-namespace ash {
-
-HotspotIconAnimation::HotspotIconAnimation() {
-  // Set up the animation throbber.
-  animation_.SetThrobDuration(base::Seconds(1));
-  animation_.SetTweenType(gfx::Tween::LINEAR);
-}
-
-HotspotIconAnimation::~HotspotIconAnimation() {
-  CHECK(observers_.empty());
-}
-
-void HotspotIconAnimation::AnimationProgressed(
-    const gfx::Animation* animation) {
-  if (animation != &animation_) {
-    return;
-  }
-  for (HotspotIconAnimationObserver& observer : observers_) {
-    observer.HotspotIconChanged();
-  }
-}
-
-double HotspotIconAnimation::GetAnimation() {
-  if (!animation_.is_animating()) {
-    animation_.Reset();
-    animation_.StartThrobbing(/*throb indefinitely=*/-1);
-    return 0;
-  }
-  return animation_.GetCurrentValue();
-}
-
-void HotspotIconAnimation::AddObserver(HotspotIconAnimationObserver* observer) {
-  if (!observers_.HasObserver(observer)) {
-    observers_.AddObserver(observer);
-  }
-}
-
-void HotspotIconAnimation::RemoveObserver(
-    HotspotIconAnimationObserver* observer) {
-  if (observers_.HasObserver(observer)) {
-    observers_.RemoveObserver(observer);
-  }
-  if (observers_.empty()) {
-    animation_.Reset();  // Stops the animation and resets the current value.
-  }
-}
-
-}  // namespace ash
diff --git a/ash/system/hotspot/hotspot_icon_animation.h b/ash/system/hotspot/hotspot_icon_animation.h
deleted file mode 100644
index 83a61a5..0000000
--- a/ash/system/hotspot/hotspot_icon_animation.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_SYSTEM_HOTSPOT_HOTSPOT_ICON_ANIMATION_H_
-#define ASH_SYSTEM_HOTSPOT_HOTSPOT_ICON_ANIMATION_H_
-
-#include "ash/ash_export.h"
-#include "base/observer_list.h"
-#include "ui/gfx/animation/animation_delegate.h"
-#include "ui/gfx/animation/throb_animation.h"
-
-namespace ash {
-
-class HotspotIconAnimationObserver;
-
-// Single instance class to handle icon animations and keep them in sync.
-class ASH_EXPORT HotspotIconAnimation : public gfx::AnimationDelegate {
- public:
-  HotspotIconAnimation();
-  ~HotspotIconAnimation() override;
-
-  // Returns the current animation value, [0-1].
-  double GetAnimation();
-
-  // The animation stops when all observers have been removed.
-  // Be sure to remove observers when no associated icons are animating.
-  void AddObserver(HotspotIconAnimationObserver* observer);
-  void RemoveObserver(HotspotIconAnimationObserver* observer);
-
-  // gfx::AnimationDelegate:
-  void AnimationProgressed(const gfx::Animation* animation) override;
-
- private:
-  gfx::ThrobAnimation animation_{this};
-  base::ObserverList<HotspotIconAnimationObserver> observers_;
-};
-
-}  // namespace ash
-
-#endif  // ASH_SYSTEM_HOTSPOT_HOTSPOT_ICON_ANIMATION_H_
diff --git a/ash/system/hotspot/hotspot_icon_animation_observer.h b/ash/system/hotspot/hotspot_icon_animation_observer.h
deleted file mode 100644
index 56e3c79..0000000
--- a/ash/system/hotspot/hotspot_icon_animation_observer.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_SYSTEM_HOTSPOT_HOTSPOT_ICON_ANIMATION_OBSERVER_H_
-#define ASH_SYSTEM_HOTSPOT_HOTSPOT_ICON_ANIMATION_OBSERVER_H_
-
-#include "ash/ash_export.h"
-#include "base/observer_list_types.h"
-
-namespace ash {
-
-// Observer interface class for animating network icons.
-class ASH_EXPORT HotspotIconAnimationObserver : public base::CheckedObserver {
- public:
-  // Called when the image has changed due to animation.
-  virtual void HotspotIconChanged() = 0;
-
- protected:
-  HotspotIconAnimationObserver() = default;
-  ~HotspotIconAnimationObserver() override = default;
-};
-
-}  // namespace ash
-
-#endif  // ASH_SYSTEM_HOTSPOT_HOTSPOT_ICON_ANIMATION_OBSERVER_H_
diff --git a/ash/system/hotspot/hotspot_icon_unittest.cc b/ash/system/hotspot/hotspot_icon_unittest.cc
deleted file mode 100644
index ad14280..0000000
--- a/ash/system/hotspot/hotspot_icon_unittest.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/system/hotspot/hotspot_icon.h"
-
-#include "ash/constants/ash_features.h"
-#include "ash/resources/vector_icons/vector_icons.h"
-#include "ash/test/ash_test_base.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/test/task_environment.h"
-#include "chromeos/ash/services/hotspot_config/public/cpp/cros_hotspot_config_test_helper.h"
-#include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom.h"
-#include "ui/gfx/vector_icon_types.h"
-
-namespace ash::hotspot_icon {
-
-using hotspot_config::mojom::HotspotState;
-
-class HotspotIconTest : public AshTestBase {
- public:
-  HotspotIconTest()
-      : AshTestBase(std::make_unique<base::test::TaskEnvironment>(
-            base::test::TaskEnvironment::MainThreadType::UI,
-            base::test::TaskEnvironment::TimeSource::MOCK_TIME)) {}
-  ~HotspotIconTest() override = default;
-
-  void SetUp() override {
-    scoped_feature_list_.InitAndEnableFeature(features::kHotspot);
-    cros_hotspot_config_test_helper_ =
-        std::make_unique<hotspot_config::CrosHotspotConfigTestHelper>(
-            /*use_fake_implementation=*/true);
-    AshTestBase::SetUp();
-  }
-
-  void TearDown() override {
-    AshTestBase::TearDown();
-    cros_hotspot_config_test_helper_.reset();
-  }
-
- protected:
-  base::test::ScopedFeatureList scoped_feature_list_;
-  std::unique_ptr<hotspot_config::CrosHotspotConfigTestHelper>
-      cros_hotspot_config_test_helper_;
-};
-
-TEST_F(HotspotIconTest, HotspotEnabledIcon) {
-  const gfx::VectorIcon& icon =
-      hotspot_icon::GetIconForHotspot(HotspotState::kEnabled);
-  EXPECT_STREQ(kHotspotOnIcon.name, icon.name);
-}
-
-TEST_F(HotspotIconTest, HotspotDisabledIcon) {
-  const gfx::VectorIcon& icon =
-      hotspot_icon::GetIconForHotspot(HotspotState::kDisabled);
-  EXPECT_STREQ(kHotspotOffIcon.name, icon.name);
-}
-
-TEST_F(HotspotIconTest, HotspotEnablingIcon) {
-  const gfx::VectorIcon& icon =
-      hotspot_icon::GetIconForHotspot(HotspotState::kEnabling);
-  EXPECT_STREQ(kHotspotDotIcon.name, icon.name);
-  task_environment()->FastForwardBy(base::Milliseconds(500));
-  EXPECT_STREQ(kHotspotOneArcIcon.name,
-               hotspot_icon::GetIconForHotspot(HotspotState::kEnabling).name);
-  task_environment()->FastForwardBy(base::Milliseconds(500));
-  EXPECT_STREQ(kHotspotOnIcon.name,
-               hotspot_icon::GetIconForHotspot(HotspotState::kEnabling).name);
-}
-
-TEST_F(HotspotIconTest, HotspotDisablingIcon) {
-  const gfx::VectorIcon& icon =
-      hotspot_icon::GetIconForHotspot(HotspotState::kDisabling);
-  EXPECT_STREQ(kHotspotOffIcon.name, icon.name);
-}
-
-}  // namespace ash::hotspot_icon
diff --git a/ash/system/hotspot/hotspot_tray_view.cc b/ash/system/hotspot/hotspot_tray_view.cc
index 3a1f62d..85094ec 100644
--- a/ash/system/hotspot/hotspot_tray_view.cc
+++ b/ash/system/hotspot/hotspot_tray_view.cc
@@ -9,8 +9,7 @@
 #include "ash/session/session_controller_impl.h"
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
-#include "ash/system/hotspot/hotspot_icon.h"
-#include "ash/system/hotspot/hotspot_icon_animation.h"
+#include "ash/style/ash_color_provider.h"
 #include "ash/system/tray/tray_constants.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -60,7 +59,6 @@
 
 HotspotTrayView::~HotspotTrayView() {
   Shell::Get()->session_controller()->RemoveObserver(this);
-  Shell::Get()->hotspot_icon_animation()->RemoveObserver(this);
 }
 
 const char* HotspotTrayView::GetClassName() const {
@@ -114,33 +112,25 @@
 }
 
 void HotspotTrayView::UpdateIconImage() {
-  image_view()->SetImage(ui::ImageModel::FromVectorIcon(
-      hotspot_icon::GetIconForHotspot(state_), cros_tokens::kCrosSysOnSurface,
-      kUnifiedTrayIconSize));
-}
-
-void HotspotTrayView::HotspotIconChanged() {
-  UpdateIconImage();
+  SkColor color;
+  if (chromeos::features::IsJellyEnabled()) {
+    color = GetColorProvider()->GetColor(cros_tokens::kCrosSysPrimary);
+  } else {
+    color = AshColorProvider::Get()->GetContentLayerColor(
+        AshColorProvider::ContentLayerType::kIconColorPrimary);
+  }
+  image_view()->SetImage(
+      gfx::CreateVectorIcon(kHotspotOnIcon, kUnifiedTrayIconSize, color));
 }
 
 void HotspotTrayView::OnGetHotspotInfo(HotspotInfoPtr hotspot_info) {
-  if (hotspot_info->state == HotspotState::kDisabled) {
+  if (hotspot_info->state != HotspotState::kEnabled) {
     SetVisible(false);
     return;
   }
 
   SetVisible(true);
   tooltip_ = ComputeHotspotTooltip(hotspot_info->client_count);
-
-  if (hotspot_info->state == HotspotState::kEnabling) {
-    Shell::Get()->hotspot_icon_animation()->AddObserver(this);
-  } else if (state_ == HotspotState::kEnabling) {
-    Shell::Get()->hotspot_icon_animation()->RemoveObserver(this);
-  }
-  if (state_ != hotspot_info->state) {
-    state_ = hotspot_info->state;
-    UpdateIconImage();
-  }
 }
 
 }  // namespace ash
diff --git a/ash/system/hotspot/hotspot_tray_view.h b/ash/system/hotspot/hotspot_tray_view.h
index 71f500d..2a76a485 100644
--- a/ash/system/hotspot/hotspot_tray_view.h
+++ b/ash/system/hotspot/hotspot_tray_view.h
@@ -9,7 +9,6 @@
 
 #include "ash/ash_export.h"
 #include "ash/public/cpp/session/session_observer.h"
-#include "ash/system/hotspot/hotspot_icon_animation_observer.h"
 #include "ash/system/tray/tray_item_view.h"
 #include "base/memory/weak_ptr.h"
 #include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom.h"
@@ -23,7 +22,6 @@
 class ASH_EXPORT HotspotTrayView
     : public TrayItemView,
       public SessionObserver,
-      public HotspotIconAnimationObserver,
       public hotspot_config::mojom::CrosHotspotConfigObserver {
  public:
   explicit HotspotTrayView(Shelf* shelf);
@@ -52,9 +50,6 @@
   // mojom::CrosHotspotConfigObserver:
   void OnHotspotInfoChanged() override;
 
-  // HotspotIconAnimationObserver:
-  void HotspotIconChanged() override;
-
   void OnGetHotspotInfo(hotspot_config::mojom::HotspotInfoPtr hotspot_info);
 
   void UpdateIconImage();
@@ -63,9 +58,6 @@
   // The tooltip and accessible name string used for the icon.
   std::u16string tooltip_;
 
-  hotspot_config::mojom::HotspotState state_ =
-      hotspot_config::mojom::HotspotState::kDisabled;
-
   mojo::Remote<hotspot_config::mojom::CrosHotspotConfig>
       remote_cros_hotspot_config_;
   mojo::Receiver<hotspot_config::mojom::CrosHotspotConfigObserver>
diff --git a/ash/system/hotspot/hotspot_tray_view_unittest.cc b/ash/system/hotspot/hotspot_tray_view_unittest.cc
index 6ffb843..f7a9627 100644
--- a/ash/system/hotspot/hotspot_tray_view_unittest.cc
+++ b/ash/system/hotspot/hotspot_tray_view_unittest.cc
@@ -8,12 +8,12 @@
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/shelf/shelf.h"
 #include "ash/strings/grit/ash_strings.h"
+#include "ash/style/ash_color_provider.h"
 #include "ash/system/tray/tray_constants.h"
 #include "ash/test/ash_test_base.h"
 #include "base/memory/raw_ptr.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
-#include "base/test/task_environment.h"
 #include "chromeos/ash/services/hotspot_config/public/cpp/cros_hotspot_config_test_helper.h"
 #include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom.h"
 #include "chromeos/constants/chromeos_features.h"
@@ -40,16 +40,14 @@
 
 }  // namespace
 
-class HotspotTrayViewTest : public AshTestBase,
+class HotspotTrayViewTest : public NoSessionAshTestBase,
                             public testing::WithParamInterface<bool> {
  public:
-  HotspotTrayViewTest()
-      : AshTestBase(std::make_unique<base::test::TaskEnvironment>(
-            base::test::TaskEnvironment::MainThreadType::UI,
-            base::test::TaskEnvironment::TimeSource::MOCK_TIME)) {}
+  HotspotTrayViewTest() = default;
   ~HotspotTrayViewTest() override = default;
 
   void SetUp() override {
+    AshTestBase::SetUp();
     if (IsJellyEnabled()) {
       scoped_feature_list_.InitWithFeatures(
           {features::kHotspot, chromeos::features::kJelly}, {});
@@ -59,12 +57,12 @@
     cros_hotspot_config_test_helper_ =
         std::make_unique<hotspot_config::CrosHotspotConfigTestHelper>(
             /*use_fake_implementation=*/true);
-    AshTestBase::SetUp();
     std::unique_ptr<HotspotTrayView> hotspot_tray_view =
         std::make_unique<HotspotTrayView>(GetPrimaryShelf());
     widget_ = CreateFramelessTestWidget();
     widget_->SetFullscreen(true);
     hotspot_tray_view_ = widget_->SetContentsView(std::move(hotspot_tray_view));
+    LogIn();
 
     // Spin the runloop to sync up the latest hotspot info.
     base::RunLoop().RunUntilIdle();
@@ -76,6 +74,8 @@
     AshTestBase::TearDown();
   }
 
+  void LogIn() { SimulateUserLogin("user1@test.com"); }
+
   void SetHotspotStateAndClientCount(HotspotState state, size_t client_count) {
     auto hotspot_info = HotspotInfo::New();
     hotspot_info->state = state;
@@ -108,39 +108,21 @@
 INSTANTIATE_TEST_SUITE_P(Jelly, HotspotTrayViewTest, testing::Bool());
 
 TEST_P(HotspotTrayViewTest, HotspotIconImage) {
-  SetHotspotStateAndClientCount(HotspotState::kDisabled, 0);
-  EXPECT_TRUE(AreImagesEqual(
-      hotspot_tray_view_->image_view()->GetImage(),
-      gfx::CreateVectorIcon(kHotspotOffIcon, kUnifiedTrayIconSize,
-                            widget_->GetColorProvider()->GetColor(
-                                cros_tokens::kCrosSysOnSurface))));
-
   SetHotspotStateAndClientCount(HotspotState::kEnabled, 0);
-  EXPECT_TRUE(AreImagesEqual(
-      hotspot_tray_view_->image_view()->GetImage(),
-      gfx::CreateVectorIcon(kHotspotOnIcon, kUnifiedTrayIconSize,
-                            widget_->GetColorProvider()->GetColor(
-                                cros_tokens::kCrosSysOnSurface))));
-
-  SetHotspotStateAndClientCount(HotspotState::kEnabling, 0);
-  EXPECT_TRUE(AreImagesEqual(
-      hotspot_tray_view_->image_view()->GetImage(),
-      gfx::CreateVectorIcon(kHotspotDotIcon, kUnifiedTrayIconSize,
-                            widget_->GetColorProvider()->GetColor(
-                                cros_tokens::kCrosSysOnSurface))));
-  // Verifies the hotspot icon is animating when enabling.
-  task_environment()->FastForwardBy(base::Milliseconds(500));
-  EXPECT_TRUE(AreImagesEqual(
-      hotspot_tray_view_->image_view()->GetImage(),
-      gfx::CreateVectorIcon(kHotspotOneArcIcon, kUnifiedTrayIconSize,
-                            widget_->GetColorProvider()->GetColor(
-                                cros_tokens::kCrosSysOnSurface))));
-  task_environment()->FastForwardBy(base::Milliseconds(500));
-  EXPECT_TRUE(AreImagesEqual(
-      hotspot_tray_view_->image_view()->GetImage(),
-      gfx::CreateVectorIcon(kHotspotOnIcon, kUnifiedTrayIconSize,
-                            widget_->GetColorProvider()->GetColor(
-                                cros_tokens::kCrosSysOnSurface))));
+  if (IsJellyEnabled()) {
+    EXPECT_TRUE(AreImagesEqual(
+        hotspot_tray_view_->image_view()->GetImage(),
+        gfx::CreateVectorIcon(kHotspotOnIcon, kUnifiedTrayIconSize,
+                              widget_->GetColorProvider()->GetColor(
+                                  cros_tokens::kCrosSysPrimary))));
+  } else {
+    EXPECT_TRUE(AreImagesEqual(
+        hotspot_tray_view_->image_view()->GetImage(),
+        gfx::CreateVectorIcon(
+            kHotspotOnIcon, kUnifiedTrayIconSize,
+            AshColorProvider::Get()->GetContentLayerColor(
+                AshColorProvider::ContentLayerType::kIconColorPrimary))));
+  }
 }
 
 TEST_P(HotspotTrayViewTest, HotspotIconVisibility) {
@@ -151,9 +133,6 @@
 
   SetHotspotStateAndClientCount(HotspotState::kDisabled, 0);
   EXPECT_FALSE(IsIconVisible());
-
-  SetHotspotStateAndClientCount(HotspotState::kEnabling, 0);
-  EXPECT_TRUE(IsIconVisible());
 }
 
 TEST_P(HotspotTrayViewTest, HotspotIconTooltip) {
diff --git a/ash/system/unified/feature_tile.h b/ash/system/unified/feature_tile.h
index 182b7fc..b1bde23 100644
--- a/ash/system/unified/feature_tile.h
+++ b/ash/system/unified/feature_tile.h
@@ -124,7 +124,6 @@
 
  private:
   friend class BluetoothFeaturePodControllerTest;
-  friend class HotspotFeaturePodControllerTest;
   friend class NotificationCounterViewTest;
 
   // views::View:
diff --git a/ash/webui/camera_app_ui/resources/js/metrics.ts b/ash/webui/camera_app_ui/resources/js/metrics.ts
index eb296854..a0b769c 100644
--- a/ash/webui/camera_app_ui/resources/js/metrics.ts
+++ b/ash/webui/camera_app_ui/resources/js/metrics.ts
@@ -32,6 +32,8 @@
 const PRODUCTION = true;
 const GA_ID = PRODUCTION ? 'UA-134822711-1' : 'UA-134822711-2';
 const GA4_ID = PRODUCTION ? 'G-TRQS261G6E' : 'G-J03LBPJBGD';
+const GA4_API_SECRET =
+    PRODUCTION ? '0Ir88y9HQtiwnchvaIzZ3Q' : 'WE_zBPUQTGefdXpHl25-ig';
 
 let baseDimen: Map<number, number|string>|null = null;
 
@@ -204,7 +206,7 @@
 
   await (await getGAHelper())
       .initGA(
-          {gaId: GA_ID, ga4Id: GA4_ID, clientId},
+          {gaId: GA_ID, ga4Id: GA4_ID, clientId, ga4ApiSecret: GA4_API_SECRET},
           Comlink.proxy(setClientId),
       );
   ready.signal();
diff --git a/ash/webui/camera_app_ui/resources/js/untrusted_ga_helper.ts b/ash/webui/camera_app_ui/resources/js/untrusted_ga_helper.ts
index 2b64c03..e716c00 100644
--- a/ash/webui/camera_app_ui/resources/js/untrusted_ga_helper.ts
+++ b/ash/webui/camera_app_ui/resources/js/untrusted_ga_helper.ts
@@ -35,6 +35,7 @@
   gaId: string;
   ga4Id: string;
   clientId: string;
+  ga4ApiSecret: string;
 }
 
 /**
@@ -81,7 +82,7 @@
   assert(m.parentNode !== null);
   m.parentNode.insertBefore(a, m);
 
-  const {gaId, ga4Id, clientId} = idParams;
+  const {gaId, ga4Id, clientId, ga4ApiSecret} = idParams;
   window.ga('create', gaId, {
     storage: 'none',
     clientId: clientId,
@@ -91,7 +92,12 @@
     assert(tracker !== undefined);
     const clientId = tracker.get('clientId');
     setClientIdCallback(clientId);
-    sendGA4EventReady.signal(genSendGA4Event({ga4Id, gaId, clientId}));
+    sendGA4EventReady.signal(genSendGA4Event({
+      ga4Id,
+      gaId,
+      clientId,
+      ga4ApiSecret,
+    }));
   });
 
   // By default GA uses a fake image and sets its source to the target URL to
@@ -108,48 +114,43 @@
   window.ga('set', 'anonymizeIp', true);
 }
 
-function genSendGA4Event({gaId, ga4Id, clientId}: InitGAIdParams):
+function genSendGA4Event({gaId, ga4Id, clientId, ga4ApiSecret}: InitGAIdParams):
     SendGA4Event {
   return (event: UniversalAnalytics.FieldsObject,
           dimensions: Record<string, string>) => {
     if (window[`ga-disable-${gaId}`]) {
       return;
     }
-    // TODO(b/267265966): Change to gtag.js instead of constructing the
-    // request manually after gtag supports sending events under
-    // non-http/https protocol.
-    /* eslint-disable @typescript-eslint/naming-convention */
-    const params: Record<string, string> = {
-      'v': '2',
-      'cid': clientId,
-      'tid': ga4Id,
-      // Redact geographic data
-      '_geo': '1',
-      'ep.anonymize_ip': 'true',
-      // Uncomment this when debugging. Currently, events don't show in Debug
-      // View (see b/277527972) so watch events in realtime events dashboard
-      // instead.
-      // '_dbg': '1',
-    };
-    /* eslint-enable @typescript-eslint/naming-convention */
-    if (event.eventAction !== undefined) {
-      params['en'] = event.eventAction;
-    }
+    // TODO(b/267265966): Use gtag.js instead of measurement protocol when
+    // gtag.js supports sending events under non-http/https protocols.
+    const params: Record<string, unknown> = {};
     if (event.eventLabel !== undefined) {
-      params[`ep.event_label`] = event.eventLabel;
+      params[`event_label`] = event.eventLabel;
     }
     if (event.eventCategory !== undefined) {
-      params['ep.event_category'] = event.eventCategory;
+      params['event_category'] = event.eventCategory;
     }
     if (event.eventValue !== undefined) {
-      params['epn.value'] = String(event.eventValue);
+      params['value'] = event.eventValue;
     }
     for (const [key, value] of Object.entries(dimensions)) {
-      params[`ep.${key}`] = value;
+      params[key] = value;
     }
-    const searchParams = new URLSearchParams(params);
-    const url = `https://www.google-analytics.com/g/collect?${searchParams}`;
-    void fetch(url, {method: 'post'});
+    /* eslint-disable @typescript-eslint/naming-convention */
+    void fetch(
+        `https://www.google-analytics.com/mp/collect?measurement_id=${
+            ga4Id}&api_secret=${ga4ApiSecret}`,
+        {
+          method: 'POST',
+          body: JSON.stringify({
+            client_id: clientId,
+            events: [{
+              name: event.eventAction,
+              params,
+            }],
+          }),
+        });
+    /* eslint-enable @typescript-eslint/naming-convention */
   };
 }
 
diff --git a/build/fuchsia/test/common.py b/build/fuchsia/test/common.py
index 0f8af33..595e571 100644
--- a/build/fuchsia/test/common.py
+++ b/build/fuchsia/test/common.py
@@ -179,6 +179,14 @@
     return 'Running' in _get_daemon_status()
 
 
+def check_ssh_config_file() -> None:
+    """Checks for ssh keys and generates them if they are missing."""
+
+    script_path = os.path.join(SDK_ROOT, 'bin', 'fuchsia-common.sh')
+    check_cmd = ['bash', '-c', f'. {script_path}; check-fuchsia-ssh-config']
+    subprocess.run(check_cmd, check=True)
+
+
 def _wait_for_daemon(start=True, timeout_seconds=100):
     """Waits for daemon to reach desired state in a polling loop.
 
diff --git a/build/fuchsia/test/compatible_utils.py b/build/fuchsia/test/compatible_utils.py
index 12904094..b917a65 100644
--- a/build/fuchsia/test/compatible_utils.py
+++ b/build/fuchsia/test/compatible_utils.py
@@ -122,8 +122,11 @@
     """Get the prefix of a barebone ssh command."""
 
     ssh_addr, ssh_port = parse_host_port(host_port_pair)
-    sshconfig = os.path.join(os.path.dirname(__file__), 'sshconfig')
-    return ['ssh', '-F', sshconfig, ssh_addr, '-p', str(ssh_port)]
+    return [
+        'ssh', '-F',
+        os.path.expanduser('~/.fuchsia/sshconfig'), ssh_addr, '-p',
+        str(ssh_port)
+    ]
 
 
 def install_symbols(package_paths: Iterable[str],
diff --git a/build/fuchsia/test/ffx_emulator.py b/build/fuchsia/test/ffx_emulator.py
index 5c0f6f0..63b4c31 100644
--- a/build/fuchsia/test/ffx_emulator.py
+++ b/build/fuchsia/test/ffx_emulator.py
@@ -13,8 +13,8 @@
 
 from contextlib import AbstractContextManager
 
-from common import find_image_in_sdk, get_system_info, run_ffx_command, \
-                   SDK_ROOT
+from common import check_ssh_config_file, find_image_in_sdk, get_system_info, \
+                   run_ffx_command, SDK_ROOT
 from compatible_utils import get_host_arch, get_sdk_hash
 
 _EMU_COMMAND_RETRIES = 3
@@ -55,6 +55,7 @@
     def _start_emulator(self) -> None:
         """Start the emulator."""
         logging.info('Starting emulator %s', self._node_name)
+        check_ssh_config_file()
         emu_command = [
             'emu', 'start', self._product_bundle, '--name', self._node_name
         ]
diff --git a/build/fuchsia/test/flash_device.py b/build/fuchsia/test/flash_device.py
index 2b415c05..ba38ca6 100755
--- a/build/fuchsia/test/flash_device.py
+++ b/build/fuchsia/test/flash_device.py
@@ -14,8 +14,8 @@
 from typing import Optional, Tuple
 
 import common
-from common import BootMode, boot_device, get_system_info, find_image_in_sdk, \
-                   register_device_args
+from common import BootMode, boot_device, check_ssh_config_file, \
+    get_system_info, find_image_in_sdk, register_device_args
 from compatible_utils import get_sdk_hash, pave, running_unattended
 from lockfile import lock
 
@@ -144,6 +144,7 @@
 
     system_image_dir = actual_image_dir
     if needs_update:
+        check_ssh_config_file()
         if should_pave:
             if running_unattended():
                 assert target, ('Target ID must be specified on swarming when'
diff --git a/build/fuchsia/test/flash_device_unittests.py b/build/fuchsia/test/flash_device_unittests.py
index 252eacf..afacc6b 100755
--- a/build/fuchsia/test/flash_device_unittests.py
+++ b/build/fuchsia/test/flash_device_unittests.py
@@ -34,13 +34,16 @@
                                                     _TEST_VERSION))
         swarming_patcher = mock.patch('flash_device.running_unattended',
                                       return_value=False)
+        check_patcher = mock.patch('flash_device.check_ssh_config_file')
         time_sleep = mock.patch('time.sleep')
         self._ffx_mock = ffx_patcher.start()
         self._sdk_hash_mock = sdk_hash_patcher.start()
+        self._check_patcher_mock = check_patcher.start()
         self._swarming_mock = swarming_patcher.start()
         self._time_sleep = time_sleep.start()
         self.addCleanup(self._ffx_mock.stop)
         self.addCleanup(self._sdk_hash_mock.stop)
+        self.addCleanup(self._check_patcher_mock.stop)
         self.addCleanup(self._swarming_mock.stop)
         self.addCleanup(self._time_sleep.stop)
 
diff --git a/build/fuchsia/test/sshconfig b/build/fuchsia/test/sshconfig
deleted file mode 100644
index 59313f5..0000000
--- a/build/fuchsia/test/sshconfig
+++ /dev/null
@@ -1,48 +0,0 @@
-# Configure port 8022 for connecting to a device with the local address.
-# This makes it possible to forward 8022 to a device connected remotely.
-# The fuchsia private key is used for the identity.
-Host 127.0.0.1
-  Port 8022
-
-Host ::1
-  Port 8022
-
-Host *
-# Turn off refusing to connect to hosts whose key has changed
-StrictHostKeyChecking no
-CheckHostIP no
-
-# Disable recording the known hosts
-UserKnownHostsFile=/dev/null
-
-# Do not forward auth agent connection to remote, no X11
-ForwardAgent no
-ForwardX11 no
-
-# Connection timeout in seconds
-ConnectTimeout=10
-
-# Check for server alive in seconds, max count before disconnecting
-ServerAliveInterval 1
-ServerAliveCountMax 10
-
-# Try to keep the master connection open to speed reconnecting.
-ControlMaster auto
-ControlPersist yes
-
-# When expanded, the ControlPath below cannot have more than 90 characters
-# (total of 108 minus 18 used by a random suffix added by ssh).
-# '%C' expands to 40 chars and there are 9 fixed chars, so '~' can expand to
-# up to 41 chars, which is a reasonable limit for a user's home in most
-# situations. If '~' expands to more than 41 chars, the ssh connection
-# will fail with an error like:
-#     unix_listener: path "..." too long for Unix domain socket
-# A possible solution is to use /tmp instead of ~, but it has
-# its own security concerns.
-ControlPath=~/.ssh/fx-%C
-
-# Connect with user, use the identity specified.
-User fuchsia
-IdentitiesOnly yes
-IdentityFile ~/.ssh/fuchsia_ed25519
-GSSAPIDelegateCredentials no
diff --git a/chrome/VERSION b/chrome/VERSION
index 2ff8ffb..943a73b 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=116
 MINOR=0
-BUILD=5797
+BUILD=5800
 PATCH=0
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 8b28cac..63e42138 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -6101,7 +6101,7 @@
     Got it
   </message>
   <message name="IDS_BOREALIS_INSTALLER_APP_NAME" desc="Name of a utility which is used to install the Steam application (Steam is a video game distribution service)">
-    Steam Installer
+    Steam installer
   </message>
   <message name="IDS_BOREALIS_INSTALLER_CONFIRMATION_TITLE" desc="Title for installer for Steam (noun, name of app).">
     Welcome to Steam on Chromebook
diff --git a/chrome/app/chromeos_strings_grdp/IDS_BOREALIS_INSTALLER_APP_NAME.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_BOREALIS_INSTALLER_APP_NAME.png.sha1
index b4def67..35640d7 100644
--- a/chrome/app/chromeos_strings_grdp/IDS_BOREALIS_INSTALLER_APP_NAME.png.sha1
+++ b/chrome/app/chromeos_strings_grdp/IDS_BOREALIS_INSTALLER_APP_NAME.png.sha1
@@ -1 +1 @@
-b6af080e13747f1c4caeec905ec92a304a2c77b2
\ No newline at end of file
+c092faa4b17df6f7276065054402ad08301212d5
\ No newline at end of file
diff --git a/chrome/browser/apps/app_service/OWNERS b/chrome/browser/apps/app_service/OWNERS
index 8dbfb9d..1b3e17d 100644
--- a/chrome/browser/apps/app_service/OWNERS
+++ b/chrome/browser/apps/app_service/OWNERS
@@ -4,6 +4,10 @@
 per-file browser_*=alexbn@chromium.org
 per-file instance_registry_updater.*=alexbn@chromium.org
 
+# For GuestOS integrations:
+per-file borealis*=file://chrome/browser/ash/borealis/OWNERS
+per-file bruschetta*=file://chrome/browser/ash/guest_os/OWNERS
+per-file crostini*=file://chrome/browser/ash/guest_os/OWNERS
 per-file plugin_vm*=file://chrome/browser/ash/guest_os/OWNERS
 
 # For files and intent handling system:
diff --git a/chrome/browser/apps/app_service/promise_apps/promise_app_registry_cache.cc b/chrome/browser/apps/app_service/promise_apps/promise_app_registry_cache.cc
index d6221539..54bf23a 100644
--- a/chrome/browser/apps/app_service/promise_apps/promise_app_registry_cache.cc
+++ b/chrome/browser/apps/app_service/promise_apps/promise_app_registry_cache.cc
@@ -62,6 +62,10 @@
   // Retrieve the current promise app state.
   apps::PromiseApp* state = FindPromiseApp(delta->package_id);
 
+  for (auto& observer : observers_) {
+    observer.OnPromiseAppUpdate(PromiseAppUpdate(state, delta.get()));
+  }
+
   if (state) {
     // Update the existing promise app if it exists.
     PromiseAppUpdate::Merge(state, delta.get());
@@ -70,10 +74,6 @@
     promise_app_map_[delta->package_id] = delta->Clone();
   }
 
-  for (auto& observer : observers_) {
-    observer.OnPromiseAppUpdate(PromiseAppUpdate(state, delta.get()));
-  }
-
   update_in_progress_ = false;
 }
 
diff --git a/chrome/browser/apps/app_service/publishers/borealis_apps.cc b/chrome/browser/apps/app_service/publishers/borealis_apps.cc
index dda2e01..3bc544cd 100644
--- a/chrome/browser/apps/app_service/publishers/borealis_apps.cc
+++ b/chrome/browser/apps/app_service/publishers/borealis_apps.cc
@@ -151,7 +151,7 @@
   auto initial_steam_app = apps::AppPublisher::MakeApp(
       apps::AppType::kBorealis, borealis::kLauncherSearchAppId,
       shown ? apps::Readiness::kReady : apps::Readiness::kDisabledByPolicy,
-      l10n_util::GetStringUTF8(IDS_BOREALIS_APP_NAME),
+      l10n_util::GetStringUTF8(IDS_BOREALIS_INSTALLER_APP_NAME),
       apps::InstallReason::kDefault, apps::InstallSource::kSystem);
   InitializeApp(*initial_steam_app, shown);
   initial_steam_app->icon_key =
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn
index 05fbfed..e452c9b6 100644
--- a/chrome/browser/ash/BUILD.gn
+++ b/chrome/browser/ash/BUILD.gn
@@ -3496,6 +3496,7 @@
     "//chromeos/ash/components/geolocation",
     "//chromeos/ash/components/hid_detection",
     "//chromeos/ash/components/install_attributes",
+    "//chromeos/ash/components/language_packs",
     "//chromeos/ash/components/login/auth",
     "//chromeos/ash/components/login/auth/public:authpublic",
     "//chromeos/ash/components/login/auth/public:challenge_response_key",
diff --git a/chrome/browser/ash/borealis/borealis_app_launcher_impl.cc b/chrome/browser/ash/borealis/borealis_app_launcher_impl.cc
index eee1c1f..995f174 100644
--- a/chrome/browser/ash/borealis/borealis_app_launcher_impl.cc
+++ b/chrome/browser/ash/borealis/borealis_app_launcher_impl.cc
@@ -32,6 +32,7 @@
            ->Features()
            .IsEnabled()) {
     borealis::ShowBorealisInstallerView(profile_);
+    std::move(callback).Run(LaunchResult::kSuccess);
     return;
   }
   if (!borealis::BorealisService::GetForProfile(profile_)
diff --git a/chrome/browser/ash/borealis/borealis_util.cc b/chrome/browser/ash/borealis/borealis_util.cc
index 2c0d7292d..08ad740 100644
--- a/chrome/browser/ash/borealis/borealis_util.cc
+++ b/chrome/browser/ash/borealis/borealis_util.cc
@@ -38,9 +38,6 @@
 const char kCompatToolVersionGameMismatch[] = "UNKNOWN (GameID mismatch)";
 const char kDeviceInformationKey[] = "entry.1613887985";
 
-const char kInsertCoinSuccessMessage[] = "Success";
-const char kInsertCoinRejectMessage[] = "Coin Invalid";
-
 namespace {
 
 // Base feedback form URL, without query parameters for prefilling.
diff --git a/chrome/browser/ash/borealis/borealis_util.h b/chrome/browser/ash/borealis/borealis_util.h
index 322988c..fbd17157 100644
--- a/chrome/browser/ash/borealis/borealis_util.h
+++ b/chrome/browser/ash/borealis/borealis_util.h
@@ -46,11 +46,6 @@
 // form.
 extern const char kDeviceInformationKey[];
 
-// TODO(b/218403711): remove these when insert_coin is deprecated. We only have
-// insert_coin in the short-term until installer UX is finalized.
-extern const char kInsertCoinSuccessMessage[];
-extern const char kInsertCoinRejectMessage[];
-
 struct CompatToolInfo {
   absl::optional<int> game_id;
   std::string proton = "None";
diff --git a/chrome/browser/ash/crosapi/browser_manager.cc b/chrome/browser/ash/crosapi/browser_manager.cc
index 3b872388..3b312fa 100644
--- a/chrome/browser/ash/crosapi/browser_manager.cc
+++ b/chrome/browser/ash/crosapi/browser_manager.cc
@@ -1549,7 +1549,9 @@
     LOG(WARNING) << "Lacros is not enabled for the current user. Terminating "
                     "pre-launched instance";
     unload_requested_ = true;
-    lacros_process_.Terminate(/*exit_code=*/0, /*wait=*/false);
+    if (lacros_process_.IsValid()) {
+      lacros_process_.Terminate(/*exit_code=*/0, /*wait=*/false);
+    }
     return;
   }
 
diff --git a/chrome/browser/ash/crosapi/input_method_test_interface_ash.cc b/chrome/browser/ash/crosapi/input_method_test_interface_ash.cc
index 3e283bc8..d8e1dbe 100644
--- a/chrome/browser/ash/crosapi/input_method_test_interface_ash.cc
+++ b/chrome/browser/ash/crosapi/input_method_test_interface_ash.cc
@@ -43,7 +43,8 @@
   return capability == kInputMethodTestCapabilitySendKeyModifiers ||
          capability == kInputMethodTestCapabilityConfirmComposition ||
          capability == kInputMethodTestCapabilityAlwaysConfirmComposition ||
-         capability == kInputMethodTestCapabilityDeleteSurroundingText;
+         capability == kInputMethodTestCapabilityDeleteSurroundingText ||
+         capability == kInputMethodTestCapabilityExtendedConfirmComposition;
 }
 
 }  // namespace
diff --git a/chrome/browser/ash/dbus/vm/vm_launch_service_provider.cc b/chrome/browser/ash/dbus/vm/vm_launch_service_provider.cc
index 7cbf718..70d206e 100644
--- a/chrome/browser/ash/dbus/vm/vm_launch_service_provider.cc
+++ b/chrome/browser/ash/dbus/vm/vm_launch_service_provider.cc
@@ -34,39 +34,35 @@
                           << method_name;
 }
 
+std::unique_ptr<dbus::Response> AllowStatusToResponse(
+    borealis::BorealisFeatures::AllowStatus status,
+    dbus::MethodCall* method_call) {
+  if (status != borealis::BorealisFeatures::AllowStatus::kAllowed) {
+    return dbus::ErrorResponse::FromMethodCall(method_call, DBUS_ERROR_FAILED,
+                                               "");
+  }
+
+  std::unique_ptr<dbus::Response> response =
+      dbus::Response::FromMethodCall(method_call);
+  dbus::MessageWriter writer(response.get());
+  writer.AppendString("");
+  return response;
+}
+
 void OnTokenChecked(Profile* profile,
                     dbus::MethodCall* method_call,
                     dbus::ExportedObject::ResponseSender response_sender,
                     bool launch,
                     borealis::BorealisFeatures::AllowStatus new_allowed) {
-  // TODO(b/218403711): Remove these messages. These messages are shown to users
-  // of the Borealis Alpha based on the status of their device, however they are
-  // not translated, because this API is only a temporary measure put in place
-  // until borealis' installer UX is finalized.
-  if (new_allowed == borealis::BorealisFeatures::AllowStatus::kAllowed) {
-    if (launch) {
-      // When requested, setting the correct token should have the effect of
-      // running the client app, which will bring up the installer or launch the
-      // client as needed.
-      borealis::BorealisService::GetForProfile(profile)->AppLauncher().Launch(
-          borealis::kClientAppId, base::DoNothing());
-    }
-    std::unique_ptr<dbus::Response> response =
-        dbus::Response::FromMethodCall(method_call);
-    dbus::MessageWriter writer(response.get());
-    writer.AppendString(borealis::kInsertCoinSuccessMessage);
-    std::move(response_sender).Run(std::move(response));
-    return;
-  }
-  std::stringstream ss;
-  if (new_allowed == borealis::BorealisFeatures::AllowStatus::kIncorrectToken) {
-    ss << borealis::kInsertCoinRejectMessage;
-  } else {
-    ss << new_allowed;
+  if (launch) {
+    // When requested, setting the correct token should have the effect of
+    // running the client app, which will bring up the installer or launch the
+    // client as needed.
+    borealis::BorealisService::GetForProfile(profile)->AppLauncher().Launch(
+        borealis::kClientAppId, base::DoNothing());
   }
   std::move(response_sender)
-      .Run(dbus::ErrorResponse::FromMethodCall(method_call, DBUS_ERROR_FAILED,
-                                               ss.str()));
+      .Run(AllowStatusToResponse(new_allowed, method_call));
 }
 
 template <typename T>
diff --git a/chrome/browser/ash/drive/drive_integration_service.cc b/chrome/browser/ash/drive/drive_integration_service.cc
index 1b1ca6a..b0e453d8 100644
--- a/chrome/browser/ash/drive/drive_integration_service.cc
+++ b/chrome/browser/ash/drive/drive_integration_service.cc
@@ -375,10 +375,10 @@
   using NetworkState = ash::NetworkState;
   using PortalState = NetworkState::PortalState;
 
-  explicit PreferenceWatcher(PrefService* pref_service)
-      : pref_service_(pref_service) {
-    DCHECK(pref_service);
-    pref_change_registrar_.Init(pref_service);
+  explicit PreferenceWatcher(Profile* profile)
+      : profile_(profile), pref_service_(profile->GetPrefs()) {
+    DCHECK(pref_service_);
+    pref_change_registrar_.Init(pref_service_);
     pref_change_registrar_.Add(
         prefs::kDisableDrive,
         base::BindRepeating(&PreferenceWatcher::OnPreferenceChanged,
@@ -393,7 +393,8 @@
           base::BindRepeating(&PreferenceWatcher::ToggleLocalMirroring,
                               weak_ptr_factory_.GetWeakPtr()));
     }
-    if (util::IsDriveFsBulkPinningEnabled()) {
+
+    if (util::IsDriveFsBulkPinningEnabled(profile_)) {
       pref_change_registrar_.Add(
           prefs::kDriveFsBulkPinningEnabled,
           base::BindRepeating(&PreferenceWatcher::ToggleBulkPinning,
@@ -515,7 +516,8 @@
     }
   }
 
-  raw_ptr<PrefService, ExperimentalAsh> pref_service_;
+  const raw_ptr<const Profile, ExperimentalAsh> profile_;
+  const raw_ptr<PrefService, ExperimentalAsh> pref_service_;
   PrefChangeRegistrar pref_change_registrar_;
   raw_ptr<DriveIntegrationService, ExperimentalAsh> integration_service_ =
       nullptr;
@@ -766,8 +768,7 @@
        base::WithBaseSyncPrimitives()});
 
   if (util::IsDriveAvailableForProfile(profile)) {
-    preference_watcher_ =
-        std::make_unique<PreferenceWatcher>(profile->GetPrefs());
+    preference_watcher_ = std::make_unique<PreferenceWatcher>(profile);
     preference_watcher_->SetIntegrationService(this);
   }
 
@@ -1033,7 +1034,7 @@
     LOG(WARNING) << "DriveFS data directory '" << data_dir
                  << "' was missing and got created again";
 
-    if (util::IsDriveFsBulkPinningEnabled()) {
+    if (util::IsDriveFsBulkPinningEnabled(profile_)) {
       VLOG(1) << "Displaying system notification";
       // Show system notification.
       file_manager::SystemNotificationManager snm(profile_);
@@ -1186,7 +1187,7 @@
   }
 
   // Enable bulk-pinning if the feature is enabled.
-  if (util::IsDriveFsBulkPinningEnabled()) {
+  if (util::IsDriveFsBulkPinningEnabled(profile_)) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
     DCHECK(!pin_manager_);
     pin_manager_ = std::make_unique<PinManager>(profile_->GetPath(),
@@ -1333,7 +1334,7 @@
 
 void DriveIntegrationService::GetTotalPinnedSize(
     base::OnceCallback<void(int64_t)> callback) {
-  if (!util::IsDriveFsBulkPinningEnabled() || !IsMounted() ||
+  if (!util::IsDriveFsBulkPinningEnabled(profile_) || !IsMounted() ||
       !GetDriveFsInterface()) {
     std::move(callback).Run(-1);
     return;
@@ -1354,7 +1355,7 @@
 
 void DriveIntegrationService::ClearOfflineFiles(
     base::OnceCallback<void(drive::FileError)> callback) {
-  if (!util::IsDriveFsBulkPinningEnabled() || !IsMounted() ||
+  if (!util::IsDriveFsBulkPinningEnabled(profile_) || !IsMounted() ||
       !GetDriveFsInterface()) {
     std::move(callback).Run(drive::FILE_ERROR_SERVICE_UNAVAILABLE);
     return;
diff --git a/chrome/browser/ash/drive/file_system_util.cc b/chrome/browser/ash/drive/file_system_util.cc
index 56b076d5..4313277 100644
--- a/chrome/browser/ash/drive/file_system_util.cc
+++ b/chrome/browser/ash/drive/file_system_util.cc
@@ -20,6 +20,7 @@
 #include "base/strings/escape.h"
 #include "chrome/browser/ash/drive/drive_integration_service.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
+#include "chrome/browser/policy/profile_policy_connector.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_paths_internal.h"
 #include "chromeos/ash/components/login/login_state/login_state.h"
@@ -118,7 +119,12 @@
   return IsDriveAvailableForProfile(profile);
 }
 
-bool IsDriveFsBulkPinningEnabled() {
+bool IsDriveFsBulkPinningEnabled(const Profile* const profile) {
+  DCHECK(profile);
+  if (profile->GetProfilePolicyConnector()->IsManaged()) {
+    return false;
+  }
+
   // TODO(b/279872186): Prior to M117 and only on canary builds the feature
   // should be enabled by the feature management module OR a direct feature
   // flag. After M117 these 2 flags should be required to enable the feature.
@@ -127,6 +133,7 @@
                ash::features::kFeatureManagementDriveFsBulkPinning) ||
            base::FeatureList::IsEnabled(ash::features::kDriveFsBulkPinning);
   }
+
   return ash::features::IsDriveFsBulkPinningEnabled();
 }
 
diff --git a/chrome/browser/ash/drive/file_system_util.h b/chrome/browser/ash/drive/file_system_util.h
index fb45461..efabb566 100644
--- a/chrome/browser/ash/drive/file_system_util.h
+++ b/chrome/browser/ash/drive/file_system_util.h
@@ -35,7 +35,7 @@
 bool IsDriveEnabledForProfile(const Profile* profile);
 
 // Returns true if bulk pinning is currently enabled for the given Profile.
-bool IsDriveFsBulkPinningEnabled();
+bool IsDriveFsBulkPinningEnabled(const Profile* profile);
 
 // Enum type for describing the current connection status to Drive.
 enum ConnectionStatusType {
diff --git a/chrome/browser/ash/extensions/file_manager/private_api_misc.cc b/chrome/browser/ash/extensions/file_manager/private_api_misc.cc
index 4976b6a8..ff90056 100644
--- a/chrome/browser/ash/extensions/file_manager/private_api_misc.cc
+++ b/chrome/browser/ash/extensions/file_manager/private_api_misc.cc
@@ -227,7 +227,7 @@
 ExtensionFunction::ResponseAction
 FileManagerPrivateGetPreferencesFunction::Run() {
   api::file_manager_private::Preferences result;
-  Profile* profile = Profile::FromBrowserContext(browser_context());
+  Profile* const profile = Profile::FromBrowserContext(browser_context());
   const PrefService* const service = profile->GetPrefs();
   auto* drive_integration_service =
       drive::DriveIntegrationServiceFactory::FindForProfile(profile);
@@ -237,7 +237,7 @@
                          !drive_integration_service->mount_failed();
   result.cellular_disabled =
       service->GetBoolean(drive::prefs::kDisableDriveOverCellular);
-  if (drive::util::IsDriveFsBulkPinningEnabled()) {
+  if (drive::util::IsDriveFsBulkPinningEnabled(profile)) {
     result.drive_fs_bulk_pinning_enabled =
         service->GetBoolean(drive::prefs::kDriveFsBulkPinningEnabled);
   }
@@ -271,14 +271,14 @@
   const absl::optional<Params> params = Params::Create(args());
   EXTENSION_FUNCTION_VALIDATE(params);
 
-  Profile* profile = Profile::FromBrowserContext(browser_context());
+  Profile* const profile = Profile::FromBrowserContext(browser_context());
   PrefService* const service = profile->GetPrefs();
 
   if (params->change_info.cellular_disabled) {
     service->SetBoolean(drive::prefs::kDisableDriveOverCellular,
                         *params->change_info.cellular_disabled);
   }
-  if (drive::util::IsDriveFsBulkPinningEnabled() &&
+  if (drive::util::IsDriveFsBulkPinningEnabled(profile) &&
       params->change_info.drive_fs_bulk_pinning_enabled) {
     service->SetBoolean(drive::prefs::kDriveFsBulkPinningEnabled,
                         *params->change_info.drive_fs_bulk_pinning_enabled);
diff --git a/chrome/browser/ash/extensions/file_manager/private_api_util.cc b/chrome/browser/ash/extensions/file_manager/private_api_util.cc
index 635c678..c42ac28 100644
--- a/chrome/browser/ash/extensions/file_manager/private_api_util.cc
+++ b/chrome/browser/ash/extensions/file_manager/private_api_util.cc
@@ -437,7 +437,7 @@
   // shows these folders as available offline, return these items as pinned and
   // available offline. This should not include shortcuts and only cover
   // directories that are parented at "My drive" (e.g. no Shared drives).
-  if (drive::util::IsDriveFsBulkPinningEnabled() &&
+  if (drive::util::IsDriveFsBulkPinningEnabled(running_profile_) &&
       IsPinManagerAvailableAndSyncingForProfile(running_profile_) &&
       IsDirectoryUnderMyDrive(metadata, relative_path_) &&
       !metadata->shortcut_details) {
diff --git a/chrome/browser/ash/file_manager/file_manager_string_util.cc b/chrome/browser/ash/file_manager/file_manager_string_util.cc
index d1bb6d5..b01a0b5 100644
--- a/chrome/browser/ash/file_manager/file_manager_string_util.cc
+++ b/chrome/browser/ash/file_manager/file_manager_string_util.cc
@@ -1251,7 +1251,7 @@
             base::FeatureList::IsEnabled(ash::features::kFilesDriveShortcuts));
 
   dict->Set("DRIVE_FS_BULK_PINNING",
-            drive::util::IsDriveFsBulkPinningEnabled());
+            drive::util::IsDriveFsBulkPinningEnabled(profile));
 
   if (base::FeatureList::IsEnabled(features::kDataLeakPreventionPolicy) &&
       base::FeatureList::IsEnabled(
diff --git a/chrome/browser/ash/input_method/suggestions_service_client.cc b/chrome/browser/ash/input_method/suggestions_service_client.cc
index 73fffd9..393db1f 100644
--- a/chrome/browser/ash/input_method/suggestions_service_client.cc
+++ b/chrome/browser/ash/input_method/suggestions_service_client.cc
@@ -8,6 +8,7 @@
 #include "base/functional/bind.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
 #include "chrome/browser/ash/input_method/suggestion_enums.h"
 #include "chromeos/services/machine_learning/public/cpp/service_connection.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -105,6 +106,11 @@
       ToSuggestionType(suggestion_mode));
 }
 
+void RecordEmptyCandidate(const ime::AssistiveSuggestionMode& suggestion_mode) {
+  UMA_HISTOGRAM_ENUMERATION("InputMethod.Assistive.MultiWord.EmptyCandidate",
+                            ToSuggestionType(suggestion_mode));
+}
+
 void RecordCandidatesGenerated(AssistiveSuggestionMode suggestion_mode) {
   base::UmaHistogramEnumeration(
       "InputMethod.Assistive.MultiWord.CandidatesGenerated",
@@ -155,6 +161,9 @@
     auto next_word_candidate = NextWordCompletionCandidate::New();
     next_word_candidate->text = candidate.text;
     next_word_candidate->normalized_score = candidate.score;
+    if (next_word_candidate->text.empty()) {
+      RecordEmptyCandidate(suggestion_mode);
+    }
     query->next_word_candidates.push_back(std::move(next_word_candidate));
   }
 
diff --git a/chrome/browser/ash/input_method/suggestions_service_client_unittest.cc b/chrome/browser/ash/input_method/suggestions_service_client_unittest.cc
index 3d1b864..a858c98 100644
--- a/chrome/browser/ash/input_method/suggestions_service_client_unittest.cc
+++ b/chrome/browser/ash/input_method/suggestions_service_client_unittest.cc
@@ -306,6 +306,36 @@
       /*expected_bucket_count=*/1);
 }
 
+TEST_F(SuggestionsServiceClientTest,
+       RecordsEmptyCandidateTextWhenCandidateTextMissing) {
+  SetTextSuggesterResult(SingleCandidate("hi there completion", 0.5f));
+
+  base::HistogramTester histogram_tester;
+  histogram_tester.ExpectTotalCount(
+      "InputMethod.Assistive.MultiWord.EmptyCandidate", 0);
+
+  client()->RequestSuggestions(
+      /*preceding_text=*/"hel",
+      /*suggestion_mode=*/AssistiveSuggestionMode::kCompletion,
+      /*completion_candidates=*/
+      std::vector<DecoderCompletionCandidate>{
+          DecoderCompletionCandidate{"hello", 0.1f},
+          DecoderCompletionCandidate{"", 0.01f},
+          DecoderCompletionCandidate{"", 0.001f},
+      },
+      /*callback=*/
+      base::BindLambdaForTesting(
+          [&](const std::vector<AssistiveSuggestion>& results) {}));
+  WaitForResults();
+
+  histogram_tester.ExpectTotalCount(
+      "InputMethod.Assistive.MultiWord.EmptyCandidate", 2);
+  histogram_tester.ExpectUniqueSample(
+      "InputMethod.Assistive.MultiWord.EmptyCandidate",
+      /*sample=*/MultiWordSuggestionType::kCompletion,
+      /*expected_bucket_count=*/2);
+}
+
 }  // namespace
 }  // namespace input_method
 }  // namespace ash
diff --git a/chrome/browser/ash/login/ui/login_display_host_common.cc b/chrome/browser/ash/login/ui/login_display_host_common.cc
index daa74d0..73e7386f 100644
--- a/chrome/browser/ash/login/ui/login_display_host_common.cc
+++ b/chrome/browser/ash/login/ui/login_display_host_common.cc
@@ -60,7 +60,6 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
 #include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
-#include "chromeos/ash/components/login/auth/auth_events_recorder.h"
 #include "chromeos/ash/components/login/auth/auth_performer.h"
 #include "components/keep_alive_registry/keep_alive_types.h"
 #include "components/strings/grit/components_strings.h"
@@ -204,9 +203,6 @@
       browser_shutdown::AddAppTerminatingCallback(base::BindOnce(
           &LoginDisplayHostCommon::OnAppTerminating, base::Unretained(this)));
   BrowserList::AddObserver(this);
-  AuthEventsRecorder::Get()->ResetLoginData();
-  AuthEventsRecorder::Get()->OnAuthenticationSurfaceChange(
-      AuthEventsRecorder::AuthenticationSurface::kLogin);
 }
 
 LoginDisplayHostCommon::~LoginDisplayHostCommon() {
diff --git a/chrome/browser/ash/login/wizard_controller.cc b/chrome/browser/ash/login/wizard_controller.cc
index 2b5005a..8cbe5dc 100644
--- a/chrome/browser/ash/login/wizard_controller.cc
+++ b/chrome/browser/ash/login/wizard_controller.cc
@@ -200,6 +200,7 @@
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
 #include "chromeos/ash/components/dbus/update_engine/update_engine_client.h"
 #include "chromeos/ash/components/geolocation/simple_geolocation_provider.h"
+#include "chromeos/ash/components/language_packs/language_pack_manager.h"
 #include "chromeos/ash/components/network/network_state.h"
 #include "chromeos/ash/components/network/network_state_handler.h"
 #include "chromeos/ash/components/settings/cros_settings_names.h"
@@ -282,6 +283,10 @@
     LocalStateErrorScreenView::kScreenId,
 };
 
+std::string GetApplicationLocale() {
+  return g_browser_process->GetApplicationLocale();
+}
+
 bool IsResumableOobeScreen(OobeScreenId screen_id) {
   for (const auto& resumable_screen : kResumableOobeScreens) {
     if (screen_id == resumable_screen) {
@@ -1759,6 +1764,13 @@
 }
 
 void WizardController::OnUpdateCompleted() {
+  // Install language packs based on the user selected language.
+  if (ash::features::IsLanguagePacksInOobeEnabled()) {
+    const std::string locale = GetApplicationLocale();
+    language_packs::LanguagePackManager::GetInstance()->UpdatePacksForOobe(
+        locale);
+  }
+
   if (demo_setup_controller_) {
     ShowConsolidatedConsentScreen();
     return;
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc
index 44dad7b..609906f 100644
--- a/chrome/browser/chrome_browser_interface_binders.cc
+++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -1438,7 +1438,7 @@
         ash::settings::OSSettingsUI>(map);
   }
 
-  if (drive::util::IsDriveFsBulkPinningEnabled()) {
+  if (drive::util::IsDriveFsBulkPinningEnabled(profile)) {
     RegisterWebUIControllerInterfaceBinder<
         ash::settings::google_drive::mojom::PageHandlerFactory,
         ash::settings::OSSettingsUI>(map);
diff --git a/chrome/browser/feedback/show_feedback_page.cc b/chrome/browser/feedback/show_feedback_page.cc
index 5198296..5b8a83e 100644
--- a/chrome/browser/feedback/show_feedback_page.cc
+++ b/chrome/browser/feedback/show_feedback_page.cc
@@ -30,6 +30,7 @@
 #include "base/functional/bind.h"
 #include "base/strings/strcat.h"
 #include "chrome/browser/ash/crosapi/browser_manager.h"
+#include "chrome/browser/ash/system_web_apps/system_web_app_manager.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h"
 #include "chromeos/components/kiosk/kiosk_utils.h"
@@ -172,7 +173,7 @@
   }
 }
 
-void OnLacrosActiveTabUrlFeteched(
+void OnLacrosActiveTabUrlFetched(
     Profile* profile,
     chrome::FeedbackSource source,
     const std::string& description_template,
@@ -188,6 +189,13 @@
                            description_placeholder_text, category_tag,
                            extra_diagnostics, std::move(autofill_metadata));
 }
+
+void LaunchFeedbackSWA(Profile* profile, const GURL& url) {
+  ash::SystemAppLaunchParams params;
+  params.url = url;
+  ash::LaunchSystemWebAppAsync(profile, ash::SystemWebAppType::OS_FEEDBACK,
+                               std::move(params));
+}
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if !BUILDFLAG(IS_CHROMEOS_LACROS)
@@ -222,18 +230,18 @@
     include_bluetooth_logs = IsFromUserInteraction(source);
     show_questionnaire = IsFromUserInteraction(source);
   }
-  // Disable a new feedback tool for kiosk, because SWAs are disabled there.
+  // Disable the new feedback tool for kiosk, because SWAs are disabled there.
   if (!chromeos::IsKioskSession() &&
       base::FeatureList::IsEnabled(ash::features::kOsFeedback)) {
-    // TODO(crbug.com/1407646): Include autofill metadata into CrOS new
-    // feedback tool.
-    ash::SystemAppLaunchParams params{};
-    params.url = BuildFeedbackUrl(
-        extra_diagnostics, description_template, description_placeholder_text,
-        category_tag, page_url, source, std::move(autofill_metadata));
+    // TODO(crbug.com/1407646): Include autofill metadata into CrOS new feedback
+    // tool.
+    GURL url = BuildFeedbackUrl(extra_diagnostics, description_template,
+                                description_placeholder_text, category_tag,
+                                page_url, source, std::move(autofill_metadata));
 
-    ash::LaunchSystemWebAppAsync(profile, ash::SystemWebAppType::OS_FEEDBACK,
-                                 std::move(params));
+    // Wait for all SWAs to be registered before continuing.
+    ash::SystemWebAppManager::Get(profile)->on_apps_synchronized().Post(
+        FROM_HERE, base::BindOnce(&LaunchFeedbackSWA, profile, url));
     return;
   }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
@@ -289,7 +297,7 @@
   if (!browser && crosapi::BrowserManager::Get()->IsRunning() &&
       crosapi::BrowserManager::Get()->GetActiveTabUrlSupported()) {
     crosapi::BrowserManager::Get()->GetActiveTabUrl(base::BindOnce(
-        &OnLacrosActiveTabUrlFeteched, profile, source, description_template,
+        &OnLacrosActiveTabUrlFetched, profile, source, description_template,
         description_placeholder_text, category_tag, extra_diagnostics,
         std::move(autofill_metadata)));
   } else {
diff --git a/chrome/browser/lacros/input_method_lacros_browsertest.cc b/chrome/browser/lacros/input_method_lacros_browsertest.cc
index 9b96c58..9b49345 100644
--- a/chrome/browser/lacros/input_method_lacros_browsertest.cc
+++ b/chrome/browser/lacros/input_method_lacros_browsertest.cc
@@ -49,7 +49,13 @@
   // - WaylandKeepSelectionFix (Lacros),
   // - AlwaysConfirmComposition (Ash).
   // - WaylandCancelComposition (Lacros).
+  //
+  // Will not be true if `extended_confirm_composition` is false.
   bool fix_265853952 = false;
+
+  // Enables kExoExtendedConfirmComposition, which uses an extended Wayland API
+  // for ConfirmCompositionText.
+  bool extended_confirm_composition = false;
 };
 
 // Binds an InputMethodTestInterface to Ash-Chrome, which allows these tests to
@@ -544,6 +550,9 @@
     if (GetParam().fix_265853952) {
       enabled_ash_features.push_back("AlwaysConfirmComposition");
     }
+    if (GetParam().extended_confirm_composition) {
+      enabled_ash_features.push_back("ExoExtendedConfirmComposition");
+    }
     if (!enabled_ash_features.empty()) {
       StartUniqueAshChrome(
           enabled_ash_features, /*disabled_features=*/{},
@@ -557,10 +566,14 @@
   base::test::ScopedFeatureList feature_list_override_;
 };
 
-INSTANTIATE_TEST_SUITE_P(InputMethodLacrosBrowserTestAllParams,
-                         InputMethodLacrosBrowserTest,
-                         ::testing::Values(TestParam{.fix_265853952 = true},
-                                           TestParam{.fix_265853952 = false}));
+INSTANTIATE_TEST_SUITE_P(
+    InputMethodLacrosBrowserTestAllParams,
+    InputMethodLacrosBrowserTest,
+    ::testing::Values(
+        TestParam{.fix_265853952 = true, .extended_confirm_composition = true},
+        TestParam{.fix_265853952 = false, .extended_confirm_composition = true},
+        TestParam{.fix_265853952 = false,
+                  .extended_confirm_composition = false}));
 
 IN_PROC_BROWSER_TEST_P(InputMethodLacrosBrowserTest,
                        FocusingInputFieldSendsFocus) {
@@ -1500,7 +1513,8 @@
           {InputMethodTestInterface::MethodMinVersions::kWaitForFocusMinVersion,
            InputMethodTestInterface::MethodMinVersions::
                kWaitForNextSurroundingTextChangeMinVersion},
-          {kInputMethodTestCapabilityConfirmComposition});
+          {kInputMethodTestCapabilityConfirmComposition,
+           kInputMethodTestCapabilityExtendedConfirmComposition});
   if (!input_method.is_bound()) {
     GTEST_SKIP() << "Unsupported ash version";
   }
@@ -1526,7 +1540,8 @@
           {InputMethodTestInterface::MethodMinVersions::kWaitForFocusMinVersion,
            InputMethodTestInterface::MethodMinVersions::
                kWaitForNextSurroundingTextChangeMinVersion},
-          {kInputMethodTestCapabilityConfirmComposition});
+          {kInputMethodTestCapabilityConfirmComposition,
+           kInputMethodTestCapabilityExtendedConfirmComposition});
   if (!input_method.is_bound()) {
     GTEST_SKIP() << "Unsupported ash version";
   }
@@ -1551,7 +1566,8 @@
           {InputMethodTestInterface::MethodMinVersions::kWaitForFocusMinVersion,
            InputMethodTestInterface::MethodMinVersions::
                kWaitForNextSurroundingTextChangeMinVersion},
-          {kInputMethodTestCapabilityConfirmComposition});
+          {kInputMethodTestCapabilityConfirmComposition,
+           kInputMethodTestCapabilityExtendedConfirmComposition});
   if (!input_method.is_bound()) {
     GTEST_SKIP() << "Unsupported ash version";
   }
@@ -1586,7 +1602,8 @@
            InputMethodTestInterface::MethodMinVersions::
                kWaitForNextSurroundingTextChangeMinVersion},
           {kInputMethodTestCapabilityConfirmComposition,
-           kInputMethodTestCapabilityAlwaysConfirmComposition});
+           kInputMethodTestCapabilityAlwaysConfirmComposition,
+           kInputMethodTestCapabilityExtendedConfirmComposition});
   if (!input_method.is_bound()) {
     GTEST_SKIP() << "Unsupported ash version";
   }
diff --git a/chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h b/chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h
index d34fb8e..60c5a233 100644
--- a/chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h
+++ b/chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h
@@ -70,8 +70,12 @@
 //   - Other unsuitable profiles (e.g. Sign-in profile): Don't launch, and send
 //     a crash report
 //
-// In tests, remember to use content::TestNavigationObserver to wait the
+// In tests, remember to use content::TestNavigationObserver to wait for the
 // navigation.
+//
+// NOTE: LaunchSystemWebAppAsync may have no effect if called before the initial
+// registration of system web apps has completed. To avoid this, first await the
+// ash::SystemWebAppManager::on_apps_synchronized event.
 void LaunchSystemWebAppAsync(
     Profile* profile,
     SystemWebAppType type,
diff --git a/chrome/browser/ui/views/borealis/borealis_installer_view.cc b/chrome/browser/ui/views/borealis/borealis_installer_view.cc
index 04cc76f..f27fc3501 100644
--- a/chrome/browser/ui/views/borealis/borealis_installer_view.cc
+++ b/chrome/browser/ui/views/borealis/borealis_installer_view.cc
@@ -126,9 +126,7 @@
 END_METADATA
 
 BorealisInstallerView::BorealisInstallerView(Profile* profile)
-    : app_name_(l10n_util::GetStringUTF16(IDS_BOREALIS_APP_NAME)),
-      profile_(profile),
-      observation_(this) {
+    : profile_(profile), observation_(this) {
   SetCanMinimize(true);
   set_draggable(true);
   set_margins(gfx::Insets::TLBR(80, 40, 40, 40));
diff --git a/chrome/browser/ui/views/borealis/borealis_installer_view.h b/chrome/browser/ui/views/borealis/borealis_installer_view.h
index d836e82e..472b932 100644
--- a/chrome/browser/ui/views/borealis/borealis_installer_view.h
+++ b/chrome/browser/ui/views/borealis/borealis_installer_view.h
@@ -105,7 +105,6 @@
 
   void StartInstallation();
 
-  std::u16string app_name_;
   raw_ptr<Profile, ExperimentalAsh> profile_ = nullptr;
   raw_ptr<views::Label, ExperimentalAsh> primary_message_label_ = nullptr;
   raw_ptr<views::Label, ExperimentalAsh> secondary_message_label_ = nullptr;
diff --git a/chrome/browser/ui/webui/management/management_ui.cc b/chrome/browser/ui/webui/management/management_ui.cc
index 089a9f6..386d6c8 100644
--- a/chrome/browser/ui/webui/management/management_ui.cc
+++ b/chrome/browser/ui/webui/management/management_ui.cc
@@ -96,10 +96,6 @@
     {kManagementScreenCaptureEvent, IDS_MANAGEMENT_SCREEN_CAPTURE_EVENT},
     {kManagementScreenCaptureData, IDS_MANAGEMENT_SCREEN_CAPTURE_DATA},
 #endif  // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-    {kManagementDeviceSignalsDisclosure,
-     IDS_MANAGEMENT_DEVICE_SIGNALS_DISCLOSURE},
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
     {"browserReporting", IDS_MANAGEMENT_BROWSER_REPORTING},
     {"browserReportingExplanation",
      IDS_MANAGEMENT_BROWSER_REPORTING_EXPLANATION},
diff --git a/chrome/browser/ui/webui/management/management_ui_handler.cc b/chrome/browser/ui/webui/management/management_ui_handler.cc
index 7b8783a7..fcfd314 100644
--- a/chrome/browser/ui/webui/management/management_ui_handler.cc
+++ b/chrome/browser/ui/webui/management/management_ui_handler.cc
@@ -86,11 +86,6 @@
 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-#include "chrome/browser/enterprise/signals/user_permission_service_factory.h"
-#include "components/device_signals/core/browser/user_permission_service.h"  // nogncheck
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/extensions/extension_util.h"
 #include "chrome/common/extensions/permissions/chrome_permission_message_provider.h"
@@ -183,11 +178,6 @@
 const char kManagementScreenCaptureData[] = "managementScreenCaptureData";
 #endif  // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)
 
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-const char kManagementDeviceSignalsDisclosure[] =
-    "managementDeviceSignalsDisclosure";
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-
 #if BUILDFLAG(IS_CHROMEOS)
 const char kManagementLogUploadEnabled[] = "managementLogUploadEnabled";
 const char kManagementReportActivityTimes[] = "managementReportActivityTimes";
@@ -738,18 +728,6 @@
              GetReportingTypeValue(report_definition.reporting_type));
     report_sources->Append(std::move(data));
   }
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-  // Insert the device signals consent disclosure at the end of browser
-  // reporting section.
-  auto* user_permission_service = GetUserPermissionService();
-  if (user_permission_service && user_permission_service->CanCollectSignals() ==
-                                     device_signals::UserPermission::kGranted) {
-    base::Value::Dict data;
-    data.Set("messageId", kManagementDeviceSignalsDisclosure);
-    data.Set("reportingType", GetReportingTypeValue(ReportingType::kDevice));
-    report_sources->Append(std::move(data));
-  }
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
 }
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -1047,14 +1025,6 @@
       ->policy_service();
 }
 
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-device_signals::UserPermissionService*
-ManagementUIHandler::GetUserPermissionService() {
-  return enterprise_signals::UserPermissionServiceFactory::GetForProfile(
-      Profile::FromWebUI(web_ui()));
-}
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-
 void ManagementUIHandler::AsyncUpdateLogo() {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   policy::BrowserPolicyConnectorAsh* connector =
diff --git a/chrome/browser/ui/webui/management/management_ui_handler.h b/chrome/browser/ui/webui/management/management_ui_handler.h
index 55fca1d..26d34eda 100644
--- a/chrome/browser/ui/webui/management/management_ui_handler.h
+++ b/chrome/browser/ui/webui/management/management_ui_handler.h
@@ -31,10 +31,6 @@
 extern const char kManagementScreenCaptureData[];
 #endif  // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)
 
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-extern const char kManagementDeviceSignalsDisclosure[];
-#endif  // #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-
 #if BUILDFLAG(IS_CHROMEOS)
 extern const char kManagementLogUploadEnabled[];
 extern const char kManagementReportActivityTimes[];
@@ -114,12 +110,6 @@
 class SystemLogUploader;
 }  // namespace policy
 
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-namespace device_signals {
-class UserPermissionService;
-}  // namespace device_signals
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-
 class Profile;
 
 // The JavaScript message handler for the chrome://management page.
@@ -173,9 +163,6 @@
   base::Value::Dict GetThreatProtectionInfo(Profile* profile);
   base::Value::List GetManagedWebsitesInfo(Profile* profile) const;
   virtual policy::PolicyService* GetPolicyService();
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-  virtual device_signals::UserPermissionService* GetUserPermissionService();
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   // Protected for testing.
diff --git a/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc b/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc
index 3b05434a2..94b4817 100644
--- a/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc
+++ b/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/webui/management/management_ui_handler.h"
 #include <map>
 #include <memory>
 #include <set>
@@ -21,6 +20,7 @@
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/policy/dm_token_utils.h"
 #include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_test_utils.h"
+#include "chrome/browser/ui/webui/management/management_ui_handler.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/ash/components/settings/cros_settings_names.h"
@@ -104,10 +104,6 @@
 #include "services/network/test/test_network_connection_tracker.h"
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-#include "components/device_signals/core/browser/mock_user_permission_service.h"  // nogncheck
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
 #include "chromeos/lacros/lacros_test_helper.h"
 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
@@ -240,17 +236,6 @@
 
   policy::PolicyService* GetPolicyService() override { return policy_service_; }
 
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-  device_signals::UserPermissionService* GetUserPermissionService() override {
-    return user_permission_service_;
-  }
-
-  void SetUserPermissionService(
-      device_signals::UserPermissionService* user_permission_service) {
-    user_permission_service_ = user_permission_service;
-  }
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   MOCK_METHOD(policy::DeviceCloudPolicyManagerAsh*,
               GetDeviceCloudPolicyManager,
@@ -266,9 +251,6 @@
   raw_ptr<policy::PolicyService> policy_service_ = nullptr;
   bool update_required_eol_ = false;
   std::string device_domain = "devicedomain.com";
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-  raw_ptr<device_signals::UserPermissionService> user_permission_service_;
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
 };
 
 // We need to use a different base class for ChromeOS and non ChromeOS case.
@@ -529,9 +511,6 @@
     base::Value::Dict data =
         handler_.GetContextualManagedDataForTesting(profile_.get());
     ExtractContextualSourceUpdate(data);
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-    handler_.SetUserPermissionService(&mock_user_permission_service_);
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
   }
 
   bool GetManaged() const { return extracted_.managed; }
@@ -640,9 +619,6 @@
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   chromeos::ScopedLacrosServiceTestHelper scoped_lacros_test_helper_;
 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-  device_signals::MockUserPermissionService mock_user_permission_service_;
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
   TestManagementUIHandler handler_;
 };
 
@@ -1312,11 +1288,6 @@
 }
 
 TEST_F(ManagementUIHandlerTests, CloudReportingPolicy) {
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-  SetUpProfileAndHandler();
-  EXPECT_CALL(mock_user_permission_service_, CanCollectSignals())
-      .WillOnce(Return(device_signals::UserPermission::kGranted));
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
   policy::PolicyMap chrome_policies;
   const policy::PolicyNamespace chrome_policies_namespace =
       policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string());
@@ -1324,13 +1295,11 @@
       .WillRepeatedly(ReturnRef(chrome_policies));
   SetPolicyValue(policy::key::kCloudReportingEnabled, true, chrome_policies);
 
-  std::set<std::string> expected_messages = {
+  const std::set<std::string> expected_messages = {
       kManagementExtensionReportMachineName, kManagementExtensionReportUsername,
       kManagementExtensionReportVersion,
       kManagementExtensionReportExtensionsPlugin};
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-  expected_messages.insert(kManagementDeviceSignalsDisclosure);
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
+
   ASSERT_PRED_FORMAT2(MessagesToBeEQ, handler_.GetExtensionReportingInfo(),
                       expected_messages);
 }
diff --git a/chrome/browser/ui/webui/settings/ash/device_section.cc b/chrome/browser/ui/webui/settings/ash/device_section.cc
index 18e2f87a..2cb8a77c 100644
--- a/chrome/browser/ui/webui/settings/ash/device_section.cc
+++ b/chrome/browser/ui/webui/settings/ash/device_section.cc
@@ -905,120 +905,6 @@
                           stylus_utils::HasInternalStylus());
 }
 
-void AddDeviceDisplayStrings(content::WebUIDataSource* html_source) {
-  static constexpr webui::LocalizedString kDisplayStrings[] = {
-      {"displayAmbientColorTitle", IDS_SETTINGS_DISPLAY_AMBIENT_COLOR_TITLE},
-      {"displayAmbientColorSubtitle",
-       IDS_SETTINGS_DISPLAY_AMBIENT_COLOR_SUBTITLE},
-      {"displayArrangementTitle", IDS_SETTINGS_DISPLAY_ARRANGEMENT_TITLE},
-      {"displayMirror", IDS_SETTINGS_DISPLAY_MIRROR},
-      {"displayMirrorDisplayName", IDS_SETTINGS_DISPLAY_MIRROR_DISPLAY_NAME},
-      {"displayNightLightLabel", IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_LABEL},
-      {"displayNightLightOnAtSunset",
-       IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_ON_AT_SUNSET},
-      {"displayNightLightOffAtSunrise",
-       IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_OFF_AT_SUNRISE},
-      {"displayNightLightScheduleCustom",
-       IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_CUSTOM},
-      {"displayNightLightScheduleLabel",
-       IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_LABEL},
-      {"displayNightLightScheduleNever",
-       IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_NEVER},
-      {"displayNightLightScheduleSunsetToSunRise",
-       IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_SUNSET_TO_SUNRISE},
-      {"displayNightLightTemperatureLabel",
-       IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEMPERATURE_LABEL},
-      {"displayNightLightTempSliderMaxLabel",
-       IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEMP_SLIDER_MAX_LABEL},
-      {"displayNightLightTempSliderMinLabel",
-       IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEMP_SLIDER_MIN_LABEL},
-      {"displayNightLightText", IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEXT},
-      {"displayOrientation", IDS_SETTINGS_DISPLAY_ORIENTATION},
-      {"displayOrientationAutoRotate",
-       IDS_SETTINGS_DISPLAY_ORIENTATION_AUTO_ROTATE},
-      {"displayOrientationStandard", IDS_SETTINGS_DISPLAY_ORIENTATION_STANDARD},
-      {"displayOverscanInstructions",
-       IDS_SETTINGS_DISPLAY_OVERSCAN_INSTRUCTIONS},
-      {"displayOverscanPageText", IDS_SETTINGS_DISPLAY_OVERSCAN_TEXT},
-      {"displayOverscanPageTitle", IDS_SETTINGS_DISPLAY_OVERSCAN_TITLE},
-      {"displayOverscanPosition", IDS_SETTINGS_DISPLAY_OVERSCAN_POSITION},
-      {"displayOverscanResize", IDS_SETTINGS_DISPLAY_OVERSCAN_RESIZE},
-      {"displayOverscanReset", IDS_SETTINGS_DISPLAY_OVERSCAN_RESET},
-      {"displayOverscanSubtitle", IDS_SETTINGS_DISPLAY_OVERSCAN_SUBTITLE},
-      {"displayRefreshRateInterlacedMenuItem",
-       IDS_SETTINGS_DISPLAY_REFRESH_RATE_INTERLACED_MENU_ITEM},
-      {"displayRefreshRateMenuItem",
-       IDS_SETTINGS_DISPLAY_REFRESH_RATE_MENU_ITEM},
-      {"displayRefreshRateSublabel",
-       IDS_SETTINGS_DISPLAY_REFRESH_RATE_SUBLABEL},
-      {"displayRefreshRateTitle", IDS_SETTINGS_DISPLAY_REFRESH_RATE_TITLE},
-      {"displayResolutionInterlacedMenuItem",
-       IDS_SETTINGS_DISPLAY_RESOLUTION_INTERLACED_MENU_ITEM},
-      {"displayResolutionMenuItem", IDS_SETTINGS_DISPLAY_RESOLUTION_MENU_ITEM},
-      {"displayResolutionOnlyMenuItem",
-       IDS_SETTINGS_DISPLAY_RESOLUTION_ONLY_MENU_ITEM},
-      {"displayResolutionSublabel", IDS_SETTINGS_DISPLAY_RESOLUTION_SUBLABEL},
-      {"displayResolutionText", IDS_SETTINGS_DISPLAY_RESOLUTION_TEXT},
-      {"displayResolutionTextBest", IDS_SETTINGS_DISPLAY_RESOLUTION_TEXT_BEST},
-      {"displayResolutionTextNative",
-       IDS_SETTINGS_DISPLAY_RESOLUTION_TEXT_NATIVE},
-      {"displayResolutionTitle", IDS_SETTINGS_DISPLAY_RESOLUTION_TITLE},
-      {"displayScreenExtended", IDS_SETTINGS_DISPLAY_SCREEN_EXTENDED},
-      {"displayScreenPrimary", IDS_SETTINGS_DISPLAY_SCREEN_PRIMARY},
-      {"displayScreenTitle", IDS_SETTINGS_DISPLAY_SCREEN},
-      {"displaySizeSliderMaxLabel", IDS_SETTINGS_DISPLAY_ZOOM_SLIDER_MAXIMUM},
-      {"displaySizeSliderMinLabel", IDS_SETTINGS_DISPLAY_ZOOM_SLIDER_MINIMUM},
-      {"displayTitle", IDS_SETTINGS_DISPLAY_TITLE},
-      {"displayTouchCalibrationText",
-       IDS_SETTINGS_DISPLAY_TOUCH_CALIBRATION_TEXT},
-      {"displayTouchCalibrationTitle",
-       IDS_SETTINGS_DISPLAY_TOUCH_CALIBRATION_TITLE},
-      {"displayUnifiedDesktop", IDS_SETTINGS_DISPLAY_UNIFIED_DESKTOP},
-      {"displayUnifiedDesktopOff", IDS_SETTINGS_DISPLAY_UNIFIED_DESKTOP_OFF},
-      {"displayUnifiedDesktopOn", IDS_SETTINGS_DISPLAY_UNIFIED_DESKTOP_ON},
-      {"displayZoomLogicalResolutionDefaultText",
-       IDS_SETTINGS_DISPLAY_ZOOM_LOGICAL_RESOLUTION_DEFAULT_TEXT},
-      {"displayZoomLogicalResolutionText",
-       IDS_SETTINGS_DISPLAY_ZOOM_LOGICAL_RESOLUTION_TEXT},
-      {"displayZoomNativeLogicalResolutionNativeText",
-       IDS_SETTINGS_DISPLAY_ZOOM_LOGICAL_RESOLUTION_NATIVE_TEXT},
-      {"displayZoomSublabel", IDS_SETTINGS_DISPLAY_ZOOM_SUBLABEL},
-      {"displayZoomTitle", IDS_SETTINGS_DISPLAY_ZOOM_TITLE},
-      {"displayZoomValue", IDS_SETTINGS_DISPLAY_ZOOM_VALUE},
-  };
-  html_source->AddLocalizedStrings(kDisplayStrings);
-
-  html_source->AddLocalizedString(
-      "displayArrangementText",
-      IDS_SETTINGS_DISPLAY_ARRANGEMENT_WITH_KEYBOARD_TEXT);
-
-  html_source->AddBoolean(
-      "isCryptohomeDataEphemeral",
-      user_manager::UserManager::Get()->IsCurrentUserCryptohomeDataEphemeral());
-
-  html_source->AddBoolean("unifiedDesktopAvailable",
-                          IsUnifiedDesktopAvailable());
-
-  html_source->AddBoolean("listAllDisplayModes",
-                          IsListAllDisplayModesEnabled());
-
-  html_source->AddBoolean("deviceSupportsAmbientColor",
-                          DoesDeviceSupportAmbientColor());
-
-  html_source->AddBoolean("enableTouchCalibrationSetting",
-                          IsTouchCalibrationAvailable());
-
-  html_source->AddString("invalidDisplayId",
-                         base::NumberToString(display::kInvalidDisplayId));
-
-  html_source->AddBoolean("enableDriveFsBulkPinning",
-                          drive::util::IsDriveFsBulkPinningEnabled());
-
-  html_source->AddBoolean(
-      "allowDisplayAlignmentApi",
-      base::FeatureList::IsEnabled(ash::features::kDisplayAlignAssist));
-}
-
 void AddDeviceStorageStrings(content::WebUIDataSource* html_source,
                              bool is_external_storage_page_available) {
   static constexpr webui::LocalizedString kStorageStrings[] = {
@@ -1777,4 +1663,119 @@
       base::FeatureList::IsEnabled(ash::features::kInputDeviceSettingsSplit));
 }
 
+void DeviceSection::AddDeviceDisplayStrings(
+    content::WebUIDataSource* html_source) const {
+  static constexpr webui::LocalizedString kDisplayStrings[] = {
+      {"displayAmbientColorTitle", IDS_SETTINGS_DISPLAY_AMBIENT_COLOR_TITLE},
+      {"displayAmbientColorSubtitle",
+       IDS_SETTINGS_DISPLAY_AMBIENT_COLOR_SUBTITLE},
+      {"displayArrangementTitle", IDS_SETTINGS_DISPLAY_ARRANGEMENT_TITLE},
+      {"displayMirror", IDS_SETTINGS_DISPLAY_MIRROR},
+      {"displayMirrorDisplayName", IDS_SETTINGS_DISPLAY_MIRROR_DISPLAY_NAME},
+      {"displayNightLightLabel", IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_LABEL},
+      {"displayNightLightOnAtSunset",
+       IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_ON_AT_SUNSET},
+      {"displayNightLightOffAtSunrise",
+       IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_OFF_AT_SUNRISE},
+      {"displayNightLightScheduleCustom",
+       IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_CUSTOM},
+      {"displayNightLightScheduleLabel",
+       IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_LABEL},
+      {"displayNightLightScheduleNever",
+       IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_NEVER},
+      {"displayNightLightScheduleSunsetToSunRise",
+       IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_SUNSET_TO_SUNRISE},
+      {"displayNightLightTemperatureLabel",
+       IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEMPERATURE_LABEL},
+      {"displayNightLightTempSliderMaxLabel",
+       IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEMP_SLIDER_MAX_LABEL},
+      {"displayNightLightTempSliderMinLabel",
+       IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEMP_SLIDER_MIN_LABEL},
+      {"displayNightLightText", IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEXT},
+      {"displayOrientation", IDS_SETTINGS_DISPLAY_ORIENTATION},
+      {"displayOrientationAutoRotate",
+       IDS_SETTINGS_DISPLAY_ORIENTATION_AUTO_ROTATE},
+      {"displayOrientationStandard", IDS_SETTINGS_DISPLAY_ORIENTATION_STANDARD},
+      {"displayOverscanInstructions",
+       IDS_SETTINGS_DISPLAY_OVERSCAN_INSTRUCTIONS},
+      {"displayOverscanPageText", IDS_SETTINGS_DISPLAY_OVERSCAN_TEXT},
+      {"displayOverscanPageTitle", IDS_SETTINGS_DISPLAY_OVERSCAN_TITLE},
+      {"displayOverscanPosition", IDS_SETTINGS_DISPLAY_OVERSCAN_POSITION},
+      {"displayOverscanResize", IDS_SETTINGS_DISPLAY_OVERSCAN_RESIZE},
+      {"displayOverscanReset", IDS_SETTINGS_DISPLAY_OVERSCAN_RESET},
+      {"displayOverscanSubtitle", IDS_SETTINGS_DISPLAY_OVERSCAN_SUBTITLE},
+      {"displayRefreshRateInterlacedMenuItem",
+       IDS_SETTINGS_DISPLAY_REFRESH_RATE_INTERLACED_MENU_ITEM},
+      {"displayRefreshRateMenuItem",
+       IDS_SETTINGS_DISPLAY_REFRESH_RATE_MENU_ITEM},
+      {"displayRefreshRateSublabel",
+       IDS_SETTINGS_DISPLAY_REFRESH_RATE_SUBLABEL},
+      {"displayRefreshRateTitle", IDS_SETTINGS_DISPLAY_REFRESH_RATE_TITLE},
+      {"displayResolutionInterlacedMenuItem",
+       IDS_SETTINGS_DISPLAY_RESOLUTION_INTERLACED_MENU_ITEM},
+      {"displayResolutionMenuItem", IDS_SETTINGS_DISPLAY_RESOLUTION_MENU_ITEM},
+      {"displayResolutionOnlyMenuItem",
+       IDS_SETTINGS_DISPLAY_RESOLUTION_ONLY_MENU_ITEM},
+      {"displayResolutionSublabel", IDS_SETTINGS_DISPLAY_RESOLUTION_SUBLABEL},
+      {"displayResolutionText", IDS_SETTINGS_DISPLAY_RESOLUTION_TEXT},
+      {"displayResolutionTextBest", IDS_SETTINGS_DISPLAY_RESOLUTION_TEXT_BEST},
+      {"displayResolutionTextNative",
+       IDS_SETTINGS_DISPLAY_RESOLUTION_TEXT_NATIVE},
+      {"displayResolutionTitle", IDS_SETTINGS_DISPLAY_RESOLUTION_TITLE},
+      {"displayScreenExtended", IDS_SETTINGS_DISPLAY_SCREEN_EXTENDED},
+      {"displayScreenPrimary", IDS_SETTINGS_DISPLAY_SCREEN_PRIMARY},
+      {"displayScreenTitle", IDS_SETTINGS_DISPLAY_SCREEN},
+      {"displaySizeSliderMaxLabel", IDS_SETTINGS_DISPLAY_ZOOM_SLIDER_MAXIMUM},
+      {"displaySizeSliderMinLabel", IDS_SETTINGS_DISPLAY_ZOOM_SLIDER_MINIMUM},
+      {"displayTitle", IDS_SETTINGS_DISPLAY_TITLE},
+      {"displayTouchCalibrationText",
+       IDS_SETTINGS_DISPLAY_TOUCH_CALIBRATION_TEXT},
+      {"displayTouchCalibrationTitle",
+       IDS_SETTINGS_DISPLAY_TOUCH_CALIBRATION_TITLE},
+      {"displayUnifiedDesktop", IDS_SETTINGS_DISPLAY_UNIFIED_DESKTOP},
+      {"displayUnifiedDesktopOff", IDS_SETTINGS_DISPLAY_UNIFIED_DESKTOP_OFF},
+      {"displayUnifiedDesktopOn", IDS_SETTINGS_DISPLAY_UNIFIED_DESKTOP_ON},
+      {"displayZoomLogicalResolutionDefaultText",
+       IDS_SETTINGS_DISPLAY_ZOOM_LOGICAL_RESOLUTION_DEFAULT_TEXT},
+      {"displayZoomLogicalResolutionText",
+       IDS_SETTINGS_DISPLAY_ZOOM_LOGICAL_RESOLUTION_TEXT},
+      {"displayZoomNativeLogicalResolutionNativeText",
+       IDS_SETTINGS_DISPLAY_ZOOM_LOGICAL_RESOLUTION_NATIVE_TEXT},
+      {"displayZoomSublabel", IDS_SETTINGS_DISPLAY_ZOOM_SUBLABEL},
+      {"displayZoomTitle", IDS_SETTINGS_DISPLAY_ZOOM_TITLE},
+      {"displayZoomValue", IDS_SETTINGS_DISPLAY_ZOOM_VALUE},
+  };
+  html_source->AddLocalizedStrings(kDisplayStrings);
+
+  html_source->AddLocalizedString(
+      "displayArrangementText",
+      IDS_SETTINGS_DISPLAY_ARRANGEMENT_WITH_KEYBOARD_TEXT);
+
+  html_source->AddBoolean(
+      "isCryptohomeDataEphemeral",
+      user_manager::UserManager::Get()->IsCurrentUserCryptohomeDataEphemeral());
+
+  html_source->AddBoolean("unifiedDesktopAvailable",
+                          IsUnifiedDesktopAvailable());
+
+  html_source->AddBoolean("listAllDisplayModes",
+                          IsListAllDisplayModesEnabled());
+
+  html_source->AddBoolean("deviceSupportsAmbientColor",
+                          DoesDeviceSupportAmbientColor());
+
+  html_source->AddBoolean("enableTouchCalibrationSetting",
+                          IsTouchCalibrationAvailable());
+
+  html_source->AddString("invalidDisplayId",
+                         base::NumberToString(display::kInvalidDisplayId));
+
+  html_source->AddBoolean("enableDriveFsBulkPinning",
+                          drive::util::IsDriveFsBulkPinningEnabled(profile()));
+
+  html_source->AddBoolean(
+      "allowDisplayAlignmentApi",
+      base::FeatureList::IsEnabled(ash::features::kDisplayAlignAssist));
+}
+
 }  // namespace ash::settings
diff --git a/chrome/browser/ui/webui/settings/ash/device_section.h b/chrome/browser/ui/webui/settings/ash/device_section.h
index 161fa7b4..0dbacf9b 100644
--- a/chrome/browser/ui/webui/settings/ash/device_section.h
+++ b/chrome/browser/ui/webui/settings/ash/device_section.h
@@ -85,6 +85,7 @@
       crosapi::mojom::DisplayLayoutInfoPtr display_layout_info);
 
   void AddDevicePointersStrings(content::WebUIDataSource* html_source);
+  void AddDeviceDisplayStrings(content::WebUIDataSource* html_source) const;
 
   raw_ptr<PrefService, ExperimentalAsh> pref_service_;
   system::PointerDeviceObserver pointer_device_observer_;
diff --git a/chrome/browser/ui/webui/settings/ash/files_section.cc b/chrome/browser/ui/webui/settings/ash/files_section.cc
index c736fc1e..98f12ef 100644
--- a/chrome/browser/ui/webui/settings/ash/files_section.cc
+++ b/chrome/browser/ui/webui/settings/ash/files_section.cc
@@ -94,7 +94,7 @@
   if (cloud_upload::IsEligibleAndEnabledUploadOfficeToCloud(profile)) {
     updater.AddSearchTags(GetFilesOfficeSearchConcepts());
   }
-  if (drive::util::IsDriveFsBulkPinningEnabled()) {
+  if (drive::util::IsDriveFsBulkPinningEnabled(profile)) {
     updater.AddSearchTags(GetFilesGoogleDriveSearchConcepts());
   }
 }
@@ -203,7 +203,7 @@
   }
 
   html_source->AddBoolean("enableDriveFsBulkPinning",
-                          drive::util::IsDriveFsBulkPinningEnabled());
+                          drive::util::IsDriveFsBulkPinningEnabled(profile()));
 }
 
 void FilesSection::AddHandlers(content::WebUI* web_ui) {
diff --git a/chrome/browser/ui/webui/settings/ash/os_settings_ui.cc b/chrome/browser/ui/webui/settings/ash/os_settings_ui.cc
index 8cd8fe21..2502412 100644
--- a/chrome/browser/ui/webui/settings/ash/os_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/ash/os_settings_ui.cc
@@ -302,7 +302,6 @@
 
 void OSSettingsUI::BindInterface(
     mojo::PendingReceiver<google_drive::mojom::PageHandlerFactory> receiver) {
-  CHECK(drive::util::IsDriveFsBulkPinningEnabled());
   // The PageHandlerFactory is reused across same-origin navigations, so ensure
   // any existing factories are reset.
   google_drive_page_handler_factory_.reset();
diff --git a/chrome/build/lacros-arm.pgo.txt b/chrome/build/lacros-arm.pgo.txt
index c1c8fd5b..bc37061c 100644
--- a/chrome/build/lacros-arm.pgo.txt
+++ b/chrome/build/lacros-arm.pgo.txt
@@ -1 +1 @@
-chrome-chromeos-arm-generic-main-1685188997-ebb36696ddefb0e6211f33de1073dd4374454624.profdata
+chrome-chromeos-arm-generic-main-1685317487-1e540316a1ad5c705eb802d78394b8e464f4db6e.profdata
diff --git a/chrome/build/lacros-arm64.pgo.txt b/chrome/build/lacros-arm64.pgo.txt
index b024c96..2a95c8f 100644
--- a/chrome/build/lacros-arm64.pgo.txt
+++ b/chrome/build/lacros-arm64.pgo.txt
@@ -1 +1 @@
-chrome-chromeos-arm64-generic-main-1685187303-fc0ecffabf6074ef58efc584c006872570184c37.profdata
+chrome-chromeos-arm64-generic-main-1685317487-46c20a27d1e52a066ab10f082397ad3c3ee1e3f7.profdata
diff --git a/chrome/build/lacros64.pgo.txt b/chrome/build/lacros64.pgo.txt
index 6445f38..10283846 100644
--- a/chrome/build/lacros64.pgo.txt
+++ b/chrome/build/lacros64.pgo.txt
@@ -1 +1 @@
-chrome-chromeos-amd64-generic-main-1685188997-3eaff79bd702bb0a6207756f688f0e8a2bdd2233.profdata
+chrome-chromeos-amd64-generic-main-1685317487-0f0039a4d71cc1fc90ffdc4ee8c7cc51877d8662.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index d969b83..c93674bf 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1685187303-0e209350897cdf3682e579bf85a684f7088e3922.profdata
+chrome-linux-main-1685317487-6534795d7067d317a56a8e91fde934d9ea9052b3.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 565608e..c72acde 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1685200043-762e6df7ee9c6eef53317cc04bffbb564c080f13.profdata
+chrome-mac-arm-main-1685332194-b6b6509c742246d1db476d77dd22e0ae85b2f6c5.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index b67a13f..35722e75 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1685166946-eab5c0731188204daafb7d01b1b27a51023ad3ff.profdata
+chrome-mac-main-1685317487-ec35461d749866246973ec97d6cd9b2abc202b86.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 0f2bd31a..b1861d83 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1685199317-7f0a09d1dadc779e2bf34312552651e8b6d8fe4e.profdata
+chrome-win32-main-1685329068-a01143bda5726cbfb75f687ccda34b18638afa73.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index fc6f711..da9c96a8 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1685199317-6820c3c7c0753e5425a82de88711197590885417.profdata
+chrome-win64-main-1685329068-292ea550a2dd781706d074bf5ef20e83c1930b02.profdata
diff --git a/chromeos/ash/components/login/auth/auth_events_recorder.cc b/chromeos/ash/components/login/auth/auth_events_recorder.cc
index b367d7d2..da02532e 100644
--- a/chromeos/ash/components/login/auth/auth_events_recorder.cc
+++ b/chromeos/ash/components/login/auth/auth_events_recorder.cc
@@ -4,6 +4,7 @@
 
 #include "chromeos/ash/components/login/auth/auth_events_recorder.h"
 
+#include <numeric>
 #include <vector>
 
 #include "base/check_is_test.h"
@@ -23,12 +24,19 @@
 namespace ash {
 namespace {
 
-constexpr int kMaxSessionStateCrashKeyLength = 32;
-constexpr char kSessionStateCrashKey[] = "session-state";
-
 using AuthenticationSurface = AuthEventsRecorder::AuthenticationSurface;
 using AuthenticationOutcome = AuthEventsRecorder::AuthenticationOutcome;
 using CryptohomeRecoveryResult = AuthEventsRecorder::CryptohomeRecoveryResult;
+using UserLoginType = AuthEventsRecorder::UserLoginType;
+
+// Constants for crash keys:
+constexpr int kMaxSessionStateCrashKeyLength = 32;
+constexpr int kMaxAuthEventsCrashKeyLength = 1024;
+constexpr char kAuthEventSeparator = ',';
+
+// Names of the crash keys:
+constexpr char kAuthEventsCrashKey[] = "auth-events";
+constexpr char kSessionStateCrashKey[] = "session-state";
 
 // Histogram for tracking the reason of auth failure
 constexpr char kFailureReasonHistogramName[] = "Login.FailureReason";
@@ -101,7 +109,7 @@
 // Suffix for grouping by screen type. Should match suffixes of the
 // Ash.OSAuth.{Login,Lock}.NbPasswordAttempts.{UntilFailure,UntilSuccess}
 // metrics in metadata/ash/histograms.xml
-std::string GetAuthenticationSurfaceSuffix(AuthenticationSurface screen) {
+std::string GetAuthenticationSurfaceName(AuthenticationSurface screen) {
   switch (screen) {
     case AuthenticationSurface::kLock:
       return "Lock";
@@ -141,7 +149,7 @@
     AuthenticationSurface screen,
     AuthenticationOutcome exit_type) {
   return base::StringPrintf(kNbPasswordAttemptsHistogramName,
-                            GetAuthenticationSurfaceSuffix(screen).c_str(),
+                            GetAuthenticationSurfaceName(screen).c_str(),
                             GetAuthenticationOutcomeSuffix(exit_type).c_str());
 }
 
@@ -209,6 +217,39 @@
   }
 }
 
+std::string GetUserLoginTypeName(AuthEventsRecorder::UserLoginType type) {
+  switch (type) {
+    case UserLoginType::kOnlineNew:
+      return "online_new";
+    case UserLoginType::kOnlineExisting:
+      return "online_existing";
+    case UserLoginType::kOffline:
+      return "offline";
+    case UserLoginType::kEphemeral:
+      return "ephemeral";
+  }
+  NOTREACHED();
+  return "";
+}
+
+std::string GetAuthenticationOutcomeName(AuthenticationOutcome exit_type) {
+  switch (exit_type) {
+    case AuthenticationOutcome::kSuccess:
+      return "success";
+    case AuthenticationOutcome::kFailure:
+      return "failure";
+    case AuthenticationOutcome::kRecovery:
+      return "recovery";
+  }
+  NOTREACHED();
+  return "";
+}
+
+std::string GetCrashKeyStringWithStatus(const std::string& event_name,
+                                        bool success) {
+  return event_name + (success ? "_success" : "_failure");
+}
+
 }  // namespace
 
 // static
@@ -258,6 +299,7 @@
   base::RecordAction(base::UserMetricsAction("Login_Failure"));
   UMA_HISTOGRAM_ENUMERATION(kFailureReasonHistogramName, reason,
                             AuthFailure::NUM_FAILURE_REASONS);
+  AddAuthEvent(GetCrashKeyStringWithStatus("login", /*success=*/false));
 }
 
 void AuthEventsRecorder::OnLoginSuccess(const SuccessReason& reason,
@@ -267,11 +309,12 @@
   base::RecordAction(base::UserMetricsAction("Login_Success"));
   UMA_HISTOGRAM_ENUMERATION(kSuccessReasonHistogramName, reason,
                             SuccessReason::NUM_SUCCESS_REASONS);
-  MaybeUpdateUserLoginType(is_new_user, is_login_offline, is_ephemeral);
+  UpdateUserLoginType(is_new_user, is_login_offline, is_ephemeral);
 }
 
 void AuthEventsRecorder::OnGuestLoginSuccess() {
   base::RecordAction(base::UserMetricsAction("Login_GuestLoginSuccess"));
+  AddAuthEvent(GetCrashKeyStringWithStatus("guest_login", /*success=*/true));
 }
 
 void AuthEventsRecorder::OnUserCount(int user_count) {
@@ -287,11 +330,12 @@
 void AuthEventsRecorder::OnAuthenticationSurfaceChange(
     AuthenticationSurface surface) {
   auth_surface_ = surface;
+  AddAuthEvent("auth_surface_change_" + GetAuthenticationSurfaceName(surface));
 }
 
-void AuthEventsRecorder::OnExistingUserLoginExit(
+void AuthEventsRecorder::OnExistingUserLoginScreenExit(
     AuthenticationOutcome exit_type,
-    int num_login_attempts) const {
+    int num_login_attempts) {
   CHECK(auth_surface_);
   CHECK_GE(num_login_attempts, 0);
   if (exit_type == AuthenticationOutcome::kFailure) {
@@ -301,6 +345,7 @@
   base::UmaHistogramCounts100(
       GetNbPasswordAttemptsHistogramName(auth_surface_.value(), exit_type),
       num_login_attempts);
+  AddAuthEvent("login_screen_exit_" + GetAuthenticationOutcomeName(exit_type));
 }
 
 void AuthEventsRecorder::RecordUserAuthFactors(
@@ -322,6 +367,20 @@
                                         const base::TimeDelta& time) {
   base::UmaHistogramMediumTimes(GetRecoveryDurationHistogramName(result), time);
   base::UmaHistogramEnumeration(kRecoveryResultHistogramName, result);
+  AddAuthEvent(GetCrashKeyStringWithStatus(
+      "recovery_done", result == CryptohomeRecoveryResult::kSucceeded));
+}
+
+void AuthEventsRecorder::OnAuthSubmit() {
+  AddAuthEvent("auth_submit");
+}
+
+void AuthEventsRecorder::OnPinSubmit() {
+  AddAuthEvent("pin_submit");
+}
+
+void AuthEventsRecorder::OnLockContentsViewUpdate() {
+  AddAuthEvent("update_lock_screen_view");
 }
 
 void AuthEventsRecorder::OnSessionStateChanged() {
@@ -332,21 +391,22 @@
   key.Set(GetSessionStateCrashKeyValue(session_state));
 }
 
-void AuthEventsRecorder::MaybeUpdateUserLoginType(bool is_new_user,
-                                                  bool is_login_offline,
-                                                  bool is_ephemeral) {
+void AuthEventsRecorder::UpdateUserLoginType(bool is_new_user,
+                                             bool is_login_offline,
+                                             bool is_ephemeral) {
   if (is_login_offline) {
-    user_login_type_ = AuthEventsRecorder::kOffline;
+    user_login_type_ = UserLoginType::kOffline;
   } else if (!is_new_user) {
     // The rest 3 online login types are with either existing user and new users
-    user_login_type_ = AuthEventsRecorder::kOnlineExisting;
+    user_login_type_ = UserLoginType::kOnlineExisting;
   } else if (is_ephemeral) {
     // The rest 2 new user login types are either ephemeral or new online users
-    user_login_type_ = AuthEventsRecorder::kEphemeral;
+    user_login_type_ = UserLoginType::kEphemeral;
   } else {
-    user_login_type_ = AuthEventsRecorder::kOnlineNew;
+    user_login_type_ = UserLoginType::kOnlineNew;
   }
 
+  AddAuthEvent("login_" + GetUserLoginTypeName(user_login_type_.value()));
   MaybeReportFlowMetrics();
 }
 
@@ -362,6 +422,44 @@
       user_login_type_.value());
 }
 
+void AuthEventsRecorder::AddAuthEvent(const std::string& event_name) {
+  events_.push_back(event_name);
+  UpdateAuthEventsCrashKey();
+}
+
+void AuthEventsRecorder::UpdateAuthEventsCrashKey() {
+  if (events_.size() == 0) {
+    return;
+  }
+
+  // Preallocate the space needed for all the events combined.
+  const size_t events_string_length =
+      std::accumulate(events_.begin(), events_.end(), 0,
+                      [](const size_t sum, const std::string& event) {
+                        return sum + event.length() + 1;
+                      });
+  std::string crash_key_string;
+  crash_key_string.reserve(events_string_length);
+
+  // Put new events at the front, so that we keep the most recent & relevant
+  // ones.
+  for (const std::string& event : events_) {
+    crash_key_string += event;
+    crash_key_string += kAuthEventSeparator;
+  }
+  DCHECK_EQ(crash_key_string.length(), events_string_length);
+
+  if (crash_key_string.length() > kMaxAuthEventsCrashKeyLength) {
+    crash_key_string = crash_key_string.substr(crash_key_string.length() -
+                                               kMaxAuthEventsCrashKeyLength);
+  }
+
+  // Note: the string will be truncated to `kMaxAuthEventsCrashKeyLength`.
+  static crash_reporter::CrashKeyString<kMaxAuthEventsCrashKeyLength> key(
+      kAuthEventsCrashKey);
+  key.Set(crash_key_string);
+}
+
 void AuthEventsRecorder::Reset() {
   user_count_ = absl::nullopt;
   show_users_on_signin_ = absl::nullopt;
diff --git a/chromeos/ash/components/login/auth/auth_events_recorder.h b/chromeos/ash/components/login/auth/auth_events_recorder.h
index b783abb..8dcdefe 100644
--- a/chromeos/ash/components/login/auth/auth_events_recorder.h
+++ b/chromeos/ash/components/login/auth/auth_events_recorder.h
@@ -5,8 +5,10 @@
 #ifndef CHROMEOS_ASH_COMPONENTS_LOGIN_AUTH_AUTH_EVENTS_RECORDER_H_
 #define CHROMEOS_ASH_COMPONENTS_LOGIN_AUTH_AUTH_EVENTS_RECORDER_H_
 
+#include <string>
 #include <vector>
 
+#include "base/containers/circular_deque.h"
 #include "base/scoped_observation.h"
 #include "base/time/time.h"
 #include "chromeos/ash/components/cryptohome/auth_factor.h"
@@ -26,12 +28,12 @@
  public:
   // Enum used for UMA. Do NOT reorder or remove entry. Don't forget to
   // update LoginFlowUserLoginType enum in enums.xml when adding new entries.
-  enum UserLoginType {
+  enum class UserLoginType {
     kOnlineNew = 0,
     kOnlineExisting = 1,
     kOffline = 2,
     kEphemeral = 3,
-    kMaxValue
+    kMaxValue = kEphemeral
   };
 
   enum class AuthenticationSurface { kLogin, kLock };
@@ -116,8 +118,8 @@
   // `OnAuthenticationSurfaceChange` must be called before this method.
   // Nothing will be recorded if the `exit_type` is `kFailure` and
   // `num_login_attempts` is 0.
-  void OnExistingUserLoginExit(AuthenticationOutcome exit_type,
-                               int num_login_attempts) const;
+  void OnExistingUserLoginScreenExit(AuthenticationOutcome exit_type,
+                                     int num_login_attempts);
 
   // Report which auth factors the user has configured.
   void RecordUserAuthFactors(
@@ -127,6 +129,15 @@
   void OnRecoveryDone(CryptohomeRecoveryResult result,
                       const base::TimeDelta& time);
 
+  // Report that the user submitted an auth method.
+  void OnAuthSubmit();
+
+  // Report that the user submitted the pin input field.
+  void OnPinSubmit();
+
+  // Report that `LockContentsView` layout was updated.
+  void OnLockContentsViewUpdate();
+
   int knowledge_factor_auth_failure_count() {
     return knowledge_factor_auth_failure_count_;
   }
@@ -145,17 +156,29 @@
 
   // Determine the user login type from the provided information.
   // Call `MaybeReportFlowMetrics`.
-  void MaybeUpdateUserLoginType(bool is_new_user,
-                                bool is_login_offline,
-                                bool is_ephemeral);
+  void UpdateUserLoginType(bool is_new_user,
+                           bool is_login_offline,
+                           bool is_ephemeral);
 
   // Report the user login type in association with policy and total user count
   // if 3 information are available: user_count_, show_users_on_signin_,
   // user_login_type_.
   void MaybeReportFlowMetrics();
 
+  // Append a new auth event to the list and call `UpdateAuthEventsCrashKey`.
+  void AddAuthEvent(const std::string& event_name);
+
+  // Update the `kAuthEventsCrashKey`.
+  // Note: The maximum total length of the crash key value that is saved is
+  // `kMaxAuthEventsCrashKeyLength`. The newest events will be kept when the
+  // string is too long.
+  void UpdateAuthEventsCrashKey();
+
   void Reset();
 
+  // List of auth event, newer events are at the end.
+  base::circular_deque<std::string> events_;
+
   base::ScopedObservation<session_manager::SessionManager,
                           session_manager::SessionManagerObserver>
       session_observation_{this};
diff --git a/chromeos/ash/components/login/auth/auth_events_recorder_unittest.cc b/chromeos/ash/components/login/auth/auth_events_recorder_unittest.cc
index 9d1c4f9..481b462 100644
--- a/chromeos/ash/components/login/auth/auth_events_recorder_unittest.cc
+++ b/chromeos/ash/components/login/auth/auth_events_recorder_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <vector>
 
+#include "base/strings/stringprintf.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/time/time.h"
 #include "chromeos/ash/components/cryptohome/auth_factor.h"
@@ -20,6 +21,25 @@
   return crash_reporter::GetCrashKeyValue("session-state");
 }
 
+std::string GetAuthEventsCrashKeyValue() {
+  std::string result = crash_reporter::GetCrashKeyValue("auth-events");
+  if (!result.empty()) {
+    return result;
+  }
+
+  // Breakpad breaks the crash key value up into chunks into chunks labeled
+  // name__1 through name__N.
+  static const std::string kCrashKeyName = "auth-events__%d";
+  std::string chunk;
+  int index = 0;
+  do {
+    chunk = crash_reporter::GetCrashKeyValue(
+        base::StringPrintf(kCrashKeyName.c_str(), ++index));
+    result += chunk;
+  } while (chunk.length() > 0);
+  return result;
+}
+
 }  // namespace
 
 class AuthEventsRecorderTest : public ::testing::Test {
@@ -59,8 +79,8 @@
                             /*is_ephemeral=*/false);
   histogram_tester.ExpectTotalCount("Login.Flow.ShowUsers.1", 1);
   histogram_tester.ExpectBucketCount(
-      "Login.Flow.ShowUsers.1", static_cast<int>(AuthEventsRecorder::kOffline),
-      1);
+      "Login.Flow.ShowUsers.1",
+      static_cast<int>(AuthEventsRecorder::UserLoginType::kOffline), 1);
   histogram_tester.ExpectTotalCount("Login.SuccessReason", 1);
   histogram_tester.ExpectBucketCount(
       "Login.SuccessReason",
@@ -75,7 +95,7 @@
   histogram_tester.ExpectTotalCount("Login.Flow.ShowUsers.Few", 1);
   histogram_tester.ExpectBucketCount(
       "Login.Flow.ShowUsers.Few",
-      static_cast<int>(AuthEventsRecorder::kOnlineExisting), 1);
+      static_cast<int>(AuthEventsRecorder::UserLoginType::kOnlineExisting), 1);
   histogram_tester.ExpectTotalCount("Login.SuccessReason", 2);
   histogram_tester.ExpectBucketCount(
       "Login.SuccessReason",
@@ -90,7 +110,7 @@
   histogram_tester.ExpectTotalCount("Login.Flow.ShowUsers.Many", 1);
   histogram_tester.ExpectBucketCount(
       "Login.Flow.ShowUsers.Many",
-      static_cast<int>(AuthEventsRecorder::kOnlineNew), 1);
+      static_cast<int>(AuthEventsRecorder::UserLoginType::kOnlineNew), 1);
   histogram_tester.ExpectTotalCount("Login.SuccessReason", 3);
   histogram_tester.ExpectBucketCount(
       "Login.SuccessReason",
@@ -108,8 +128,8 @@
                             /*is_ephemeral=*/false);
   histogram_tester.ExpectTotalCount("Login.Flow.HideUsers.1", 1);
   histogram_tester.ExpectBucketCount(
-      "Login.Flow.HideUsers.1", static_cast<int>(AuthEventsRecorder::kOffline),
-      1);
+      "Login.Flow.HideUsers.1",
+      static_cast<int>(AuthEventsRecorder::UserLoginType::kOffline), 1);
   histogram_tester.ExpectTotalCount("Login.SuccessReason", 1);
   histogram_tester.ExpectBucketCount(
       "Login.SuccessReason",
@@ -124,7 +144,7 @@
   histogram_tester.ExpectTotalCount("Login.Flow.HideUsers.Few", 1);
   histogram_tester.ExpectBucketCount(
       "Login.Flow.HideUsers.Few",
-      static_cast<int>(AuthEventsRecorder::kOnlineExisting), 1);
+      static_cast<int>(AuthEventsRecorder::UserLoginType::kOnlineExisting), 1);
   histogram_tester.ExpectTotalCount("Login.SuccessReason", 2);
   histogram_tester.ExpectBucketCount(
       "Login.SuccessReason",
@@ -139,20 +159,20 @@
   histogram_tester.ExpectTotalCount("Login.Flow.HideUsers.Many", 1);
   histogram_tester.ExpectBucketCount(
       "Login.Flow.HideUsers.Many",
-      static_cast<int>(AuthEventsRecorder::kOnlineNew), 1);
+      static_cast<int>(AuthEventsRecorder::UserLoginType::kOnlineNew), 1);
   histogram_tester.ExpectTotalCount("Login.SuccessReason", 3);
   histogram_tester.ExpectBucketCount(
       "Login.SuccessReason",
       static_cast<int>(SuccessReason::OFFLINE_AND_ONLINE), 3);
 }
 
-TEST_F(AuthEventsRecorderTest, OnExistingUserLoginExit) {
+TEST_F(AuthEventsRecorderTest, OnExistingUserLoginScreenExit) {
   base::HistogramTester histogram_tester;
 
   int two_attempts = 2;
   recorder_->OnAuthenticationSurfaceChange(
       AuthEventsRecorder::AuthenticationSurface::kLogin);
-  recorder_->OnExistingUserLoginExit(
+  recorder_->OnExistingUserLoginScreenExit(
       AuthEventsRecorder::AuthenticationOutcome::kSuccess, two_attempts);
   histogram_tester.ExpectTotalCount(
       "Ash.OSAuth.Login.NbPasswordAttempts.UntilSuccess", 1);
@@ -160,7 +180,7 @@
       "Ash.OSAuth.Login.NbPasswordAttempts.UntilSuccess", two_attempts, 1);
 
   int three_attempts = 3;
-  recorder_->OnExistingUserLoginExit(
+  recorder_->OnExistingUserLoginScreenExit(
       AuthEventsRecorder::AuthenticationOutcome::kFailure, three_attempts);
   histogram_tester.ExpectTotalCount(
       "Ash.OSAuth.Login.NbPasswordAttempts.UntilFailure", 1);
@@ -168,7 +188,7 @@
       "Ash.OSAuth.Login.NbPasswordAttempts.UntilFailure", three_attempts, 1);
 
   int eleven_attempts = 11;
-  recorder_->OnExistingUserLoginExit(
+  recorder_->OnExistingUserLoginScreenExit(
       AuthEventsRecorder::AuthenticationOutcome::kRecovery, eleven_attempts);
   histogram_tester.ExpectTotalCount(
       "Ash.OSAuth.Login.NbPasswordAttempts.UntilRecovery", 1);
@@ -178,7 +198,7 @@
   int five_attempts = 5;
   recorder_->OnAuthenticationSurfaceChange(
       AuthEventsRecorder::AuthenticationSurface::kLock);
-  recorder_->OnExistingUserLoginExit(
+  recorder_->OnExistingUserLoginScreenExit(
       AuthEventsRecorder::AuthenticationOutcome::kSuccess, five_attempts);
   histogram_tester.ExpectTotalCount(
       "Ash.OSAuth.Lock.NbPasswordAttempts.UntilSuccess", 1);
@@ -186,7 +206,7 @@
       "Ash.OSAuth.Lock.NbPasswordAttempts.UntilSuccess", five_attempts, 1);
 
   int seven_attempts = 7;
-  recorder_->OnExistingUserLoginExit(
+  recorder_->OnExistingUserLoginScreenExit(
       AuthEventsRecorder::AuthenticationOutcome::kFailure, seven_attempts);
   histogram_tester.ExpectTotalCount(
       "Ash.OSAuth.Lock.NbPasswordAttempts.UntilFailure", 1);
@@ -195,13 +215,13 @@
 }
 
 // User exits the login/lock screen without any failed attempts.
-TEST_F(AuthEventsRecorderTest, OnExistingUserLoginExitWithNoFailure) {
+TEST_F(AuthEventsRecorderTest, OnExistingUserLoginScreenExitWithNoFailure) {
   base::HistogramTester histogram_tester;
 
   int zero_attempts = 0;
   recorder_->OnAuthenticationSurfaceChange(
       AuthEventsRecorder::AuthenticationSurface::kLock);
-  recorder_->OnExistingUserLoginExit(
+  recorder_->OnExistingUserLoginScreenExit(
       AuthEventsRecorder::AuthenticationOutcome::kSuccess, zero_attempts);
   histogram_tester.ExpectTotalCount(
       "Ash.OSAuth.Lock.NbPasswordAttempts.UntilSuccess", 1);
@@ -274,4 +294,47 @@
   EXPECT_EQ(GetSessionStateCrashKeyValue(), "unknown");
 }
 
+TEST_F(AuthEventsRecorderTest, AuthEventsCrashKeyOnSuccessfullLogin) {
+  // Login screen:
+  recorder_->OnAuthenticationSurfaceChange(
+      AuthEventsRecorder::AuthenticationSurface::kLogin);
+  recorder_->OnLockContentsViewUpdate();
+  recorder_->OnAuthSubmit();
+  recorder_->OnLoginSuccess(SuccessReason::OFFLINE_ONLY,
+                            /*is_new_user=*/false, /*is_login_offline=*/true,
+                            /*is_ephemeral=*/false);
+  recorder_->OnExistingUserLoginScreenExit(
+      AuthEventsRecorder::AuthenticationOutcome::kSuccess, 1);
+  EXPECT_EQ(GetAuthEventsCrashKeyValue(),
+            "auth_surface_change_Login,update_lock_screen_view,auth_submit,"
+            "login_offline,login_screen_exit_success,");
+  // Lock screen:
+  recorder_->OnAuthenticationSurfaceChange(
+      AuthEventsRecorder::AuthenticationSurface::kLock);
+  recorder_->OnLockContentsViewUpdate();
+  // 3 failed attempts:
+  recorder_->OnAuthSubmit();
+  recorder_->OnAuthFailure(
+      AuthFailure::FailureReason::COULD_NOT_MOUNT_CRYPTOHOME);
+  recorder_->OnAuthSubmit();
+  recorder_->OnAuthFailure(
+      AuthFailure::FailureReason::COULD_NOT_MOUNT_CRYPTOHOME);
+  recorder_->OnAuthSubmit();
+  recorder_->OnAuthFailure(
+      AuthFailure::FailureReason::COULD_NOT_MOUNT_CRYPTOHOME);
+  // 1 successfull attempt:
+  recorder_->OnAuthSubmit();
+  recorder_->OnLoginSuccess(SuccessReason::OFFLINE_ONLY,
+                            /*is_new_user=*/false, /*is_login_offline=*/true,
+                            /*is_ephemeral=*/false);
+  recorder_->OnExistingUserLoginScreenExit(
+      AuthEventsRecorder::AuthenticationOutcome::kSuccess, 4);
+  EXPECT_EQ(GetAuthEventsCrashKeyValue(),
+            "auth_surface_change_Login,update_lock_screen_view,auth_submit,"
+            "login_offline,login_screen_exit_success,auth_surface_change_Lock,"
+            "update_lock_screen_view,auth_submit,login_failure,auth_submit,"
+            "login_failure,auth_submit,login_failure,auth_submit,login_offline,"
+            "login_screen_exit_success,");
+}
+
 }  // namespace ash
diff --git a/chromeos/crosapi/cpp/input_method_test_interface_constants.h b/chromeos/crosapi/cpp/input_method_test_interface_constants.h
index 66cd69d..f8ed37d 100644
--- a/chromeos/crosapi/cpp/input_method_test_interface_constants.h
+++ b/chromeos/crosapi/cpp/input_method_test_interface_constants.h
@@ -30,6 +30,11 @@
 inline constexpr base::StringPiece
     kInputMethodTestCapabilityDeleteSurroundingText = "DeleteSurroundingText";
 
+COMPONENT_EXPORT(CROSAPI)
+inline constexpr base::StringPiece
+    kInputMethodTestCapabilityExtendedConfirmComposition =
+        "ExtendedConfirmComposition";
+
 }  // namespace crosapi
 
 #endif  // CHROMEOS_CROSAPI_CPP_INPUT_METHOD_TEST_INTERFACE_CONSTANTS_H_
diff --git a/components/captive_portal/content/captive_portal_tab_helper_unittest.cc b/components/captive_portal/content/captive_portal_tab_helper_unittest.cc
index a618b289..7c204785 100644
--- a/components/captive_portal/content/captive_portal_tab_helper_unittest.cc
+++ b/components/captive_portal/content/captive_portal_tab_helper_unittest.cc
@@ -279,7 +279,6 @@
   std::unique_ptr<NavigationSimulator> same_site_navigation =
       NavigationSimulator::CreateRendererInitiated(same_site_url, main_rfh());
   same_site_navigation->Start();
-  same_site_navigation->ReadyToCommit();
 
   // It's unexpectedly interrupted by a cross-process navigation, which starts
   // navigating before the old navigation cancels.
diff --git a/components/exo/text_input.cc b/components/exo/text_input.cc
index 7c913cbf..a1fda9e 100644
--- a/components/exo/text_input.cc
+++ b/components/exo/text_input.cc
@@ -215,14 +215,22 @@
   const auto& [surrounding_text, utf16_offset, cursor_pos, composition] =
       predicted_state;
 
-  if (keep_selection && cursor_pos.IsValid() &&
-      cursor_pos.IsBoundedBy(predicted_state.GetSurroundingTextRange())) {
-    delegate_->SetCursor(surrounding_text,
-                         RemoveOffset(cursor_pos, utf16_offset));
+  if (!(base::FeatureList::IsEnabled(
+            ash::features::kExoExtendedConfirmComposition) &&
+        delegate_->ConfirmComposition(keep_selection))) {
+    // Fallback to SetCursor and Commit if ConfirmComposition is not supported.
+    // TODO(b/265853952): Remove once all versions of Lacros supports
+    // ConfirmComposition.
+    if (keep_selection && cursor_pos.IsValid() &&
+        cursor_pos.IsBoundedBy(predicted_state.GetSurroundingTextRange())) {
+      delegate_->SetCursor(surrounding_text,
+                           RemoveOffset(cursor_pos, utf16_offset));
+    }
+
+    delegate_->Commit(
+        predicted_state.GetCompositionText().value_or(base::StringPiece16()));
   }
 
-  delegate_->Commit(
-      predicted_state.GetCompositionText().value_or(base::StringPiece16()));
   // Preserve the result value before updating the tracker's state.
   const size_t composition_text_length = composition.length();
   surrounding_text_tracker_.OnConfirmCompositionText(keep_selection);
diff --git a/components/exo/text_input.h b/components/exo/text_input.h
index ce883b0..62a3012 100644
--- a/components/exo/text_input.h
+++ b/components/exo/text_input.h
@@ -123,6 +123,12 @@
     // |surrounding_text|. All offsets are in UTF16, and must be valid.
     virtual void SetAutocorrectRange(base::StringPiece16 surrounding_text,
                                      const gfx::Range& range) = 0;
+
+    // Commits the current composition text.
+    // If `keep_selection` is true, keep the selection range unchanged.
+    // Otherwise, set the selection range to be after the committed text.
+    // Returns whether the operation is supported by the client.
+    virtual bool ConfirmComposition(bool keep_selection) = 0;
   };
 
   explicit TextInput(std::unique_ptr<Delegate> delegate);
diff --git a/components/exo/text_input_unittest.cc b/components/exo/text_input_unittest.cc
index d7a41c0..d942f97 100644
--- a/components/exo/text_input_unittest.cc
+++ b/components/exo/text_input_unittest.cc
@@ -102,6 +102,7 @@
               SetAutocorrectRange,
               (base::StringPiece16, const gfx::Range&),
               (override));
+  MOCK_METHOD(bool, ConfirmComposition, (bool), (override));
 };
 
 class TestingInputMethodObserver : public ui::InputMethodObserver {
@@ -249,6 +250,31 @@
 
 INSTANTIATE_TEST_SUITE_P(, TextInputTestWithConsumedByIme, ::testing::Bool());
 
+// Test for both kExoExtendedConfirmComposition enabled and disabled.
+class TextInputTestWithExtendedConfirmComposition
+    : public TextInputTest,
+      public testing::WithParamInterface<bool> {
+ public:
+  void SetUp() override {
+    if (GetParam()) {
+      feature_list_.InitAndEnableFeature(
+          ash::features::kExoExtendedConfirmComposition);
+    } else {
+      feature_list_.InitAndDisableFeature(
+          ash::features::kExoExtendedConfirmComposition);
+    }
+
+    TextInputTest::SetUp();
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+INSTANTIATE_TEST_SUITE_P(,
+                         TextInputTestWithExtendedConfirmComposition,
+                         ::testing::Bool());
+
 TEST_F(TextInputTest, Activate) {
   EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, text_input()->GetTextInputType());
   EXPECT_EQ(ui::TEXT_INPUT_MODE_DEFAULT, text_input()->GetTextInputMode());
@@ -533,11 +559,16 @@
   text_input()->ClearCompositionText();
 }
 
-TEST_F(TextInputTest, ConfirmCompositionText) {
+TEST_P(TextInputTestWithExtendedConfirmComposition,
+       ConfirmCompositionTextDontKeepSelection) {
   SetCompositionText(u"composition");
 
-  EXPECT_CALL(*delegate(), Commit(base::StringPiece16(u"composition")))
-      .Times(1);
+  if (GetParam()) {
+    EXPECT_CALL(*delegate(), ConfirmComposition(/*keep_selection=*/false))
+        .Times(1);
+  } else {
+    EXPECT_CALL(*delegate(), Commit(base::StringPiece16(u"composition")));
+  }
   const size_t composition_text_length =
       text_input()->ConfirmCompositionText(/*keep_selection=*/false);
   EXPECT_EQ(composition_text_length, 11u);
@@ -548,18 +579,23 @@
   EXPECT_FALSE(text_input()->HasCompositionText());
 }
 
-TEST_F(TextInputTest, ConfirmCompositionTextKeepSelection) {
+TEST_P(TextInputTestWithExtendedConfirmComposition,
+       ConfirmCompositionTextKeepSelection) {
   constexpr char16_t kCompositionText[] = u"composition";
   SetCompositionText(kCompositionText);
   text_input()->SetEditableSelectionRange(gfx::Range(2, 3));
   text_input()->SetSurroundingText(kCompositionText, 0u, gfx::Range(2, 3),
                                    absl::nullopt, absl::nullopt);
 
-  EXPECT_CALL(*delegate(), SetCursor(base::StringPiece16(kCompositionText),
-                                     gfx::Range(2, 3)))
-      .Times(1);
-  EXPECT_CALL(*delegate(), Commit(base::StringPiece16(kCompositionText)))
-      .Times(1);
+  if (GetParam()) {
+    EXPECT_CALL(*delegate(), ConfirmComposition(/*keep_selection=*/true))
+        .Times(1);
+  } else {
+    EXPECT_CALL(*delegate(), SetCursor(base::StringPiece16(kCompositionText),
+                                       gfx::Range(2, 3)))
+        .Times(1);
+    EXPECT_CALL(*delegate(), Commit(base::StringPiece16(kCompositionText)));
+  }
   const uint32_t composition_text_length =
       text_input()->ConfirmCompositionText(/*keep_selection=*/true);
   EXPECT_EQ(composition_text_length, static_cast<uint32_t>(11));
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc
index 4215ef0b..f69ef2d 100644
--- a/components/exo/wayland/server.cc
+++ b/components/exo/wayland/server.cc
@@ -154,6 +154,18 @@
   LOG(WARNING) << "libwayland: " << base::StringPrintV(fmt, argp);
 }
 
+int GetTextInputExtensionV1Version() {
+  if (base::FeatureList::IsEnabled(
+          ash::features::kExoExtendedConfirmComposition) &&
+      base::FeatureList::IsEnabled(ash::features::kExoSurroundingTextOffset)) {
+    return 11;
+  }
+  if (base::FeatureList::IsEnabled(ash::features::kExoSurroundingTextOffset)) {
+    return 10;
+  }
+  return 9;
+}
+
 }  // namespace
 
 bool Server::Open() {
@@ -382,12 +394,10 @@
 
   zcr_text_input_extension_data_ =
       std::make_unique<WaylandTextInputExtension>();
-  wl_global_create(
-      wl_display_.get(), &zcr_text_input_extension_v1_interface,
-      base::FeatureList::IsEnabled(ash::features::kExoSurroundingTextOffset)
-          ? 10
-          : 9,
-      zcr_text_input_extension_data_.get(), bind_text_input_extension);
+  wl_global_create(wl_display_.get(), &zcr_text_input_extension_v1_interface,
+                   GetTextInputExtensionV1Version(),
+                   zcr_text_input_extension_data_.get(),
+                   bind_text_input_extension);
 
   zxdg_shell_data_ =
       std::make_unique<WaylandZxdgShell>(display_, serial_tracker_.get());
diff --git a/components/exo/wayland/zwp_text_input_manager.cc b/components/exo/wayland/zwp_text_input_manager.cc
index fd987e5..c460a51 100644
--- a/components/exo/wayland/zwp_text_input_manager.cc
+++ b/components/exo/wayland/zwp_text_input_manager.cc
@@ -402,6 +402,25 @@
     }
   }
 
+  bool ConfirmComposition(bool keep_selection) override {
+    if (!extended_text_input_) {
+      return false;
+    }
+
+    if (wl_resource_get_version(extended_text_input_) <
+        ZCR_EXTENDED_TEXT_INPUT_V1_CONFIRM_PREEDIT_SINCE_VERSION) {
+      return false;
+    }
+
+    zcr_extended_text_input_v1_send_confirm_preedit(
+        extended_text_input_,
+        keep_selection
+            ? ZCR_EXTENDED_TEXT_INPUT_V1_CONFIRM_PREEDIT_SELECTION_BEHAVIOR_UNCHANGED
+            : ZCR_EXTENDED_TEXT_INPUT_V1_CONFIRM_PREEDIT_SELECTION_BEHAVIOR_AFTER_PREEDIT);
+    wl_client_flush(client());
+    return true;
+  }
+
   raw_ptr<wl_resource, ExperimentalAsh> text_input_;
   raw_ptr<wl_resource, ExperimentalAsh> extended_text_input_ = nullptr;
   raw_ptr<wl_resource, ExperimentalAsh> surface_ = nullptr;
diff --git a/components/management_strings.grdp b/components/management_strings.grdp
index 07d7871..f019a4a 100644
--- a/components/management_strings.grdp
+++ b/components/management_strings.grdp
@@ -319,11 +319,4 @@
       URLs of pages you visit are sent to Google Cloud or third parties for analysis. For example, they might be scanned to detect unsafe websites or filter websites based on rules set by the administrator.
     </message>
   </if>
-
-  <!-- Strings related to Chrome Enterprise Device Signals Sharing -->
-  <if expr="is_win or is_linux or is_macosx">
-    <message name="IDS_MANAGEMENT_DEVICE_SIGNALS_DISCLOSURE" desc="Disclosure message explaining that device signals can be shared.">
-      Information about your browser, OS, device, installed software, and files
-    </message>
-  </if>
 </grit-part>
diff --git a/components/management_strings_grdp/IDS_MANAGEMENT_DEVICE_SIGNALS_DISCLOSURE.png.sha1 b/components/management_strings_grdp/IDS_MANAGEMENT_DEVICE_SIGNALS_DISCLOSURE.png.sha1
deleted file mode 100644
index 5c05bfb..0000000
--- a/components/management_strings_grdp/IDS_MANAGEMENT_DEVICE_SIGNALS_DISCLOSURE.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-b6ca5d74b0974e288e867ca1cbf0928833972931
\ No newline at end of file
diff --git a/content/browser/renderer_host/navigation_controller_impl_unittest.cc b/content/browser/renderer_host/navigation_controller_impl_unittest.cc
index 9b21af7..87856c6 100644
--- a/content/browser/renderer_host/navigation_controller_impl_unittest.cc
+++ b/content/browser/renderer_host/navigation_controller_impl_unittest.cc
@@ -914,10 +914,7 @@
   EXPECT_EQ(0U, navigation_entry_changed_counter_);
   EXPECT_EQ(0U, navigation_list_pruned_counter_);
 
-  // After the beforeunload but before it commits...
-  navigation->ReadyToCommit();
-
-  // ... Do a new navigation.
+  // After the navigation starts but before it commits, do a new navigation.
   const GURL kNewURL("http://see");
   NavigationSimulator::NavigateAndCommitFromDocument(kNewURL, main_test_rfh());
 
@@ -1007,7 +1004,7 @@
   // The zeroth entry should be pending.
   auto back_navigation = NavigationSimulator::CreateHistoryNavigation(
       -1, contents(), false /* is_renderer_initiated */);
-  back_navigation->ReadyToCommit();
+  back_navigation->Start();
   EXPECT_EQ(0U, navigation_entry_changed_counter_);
   EXPECT_EQ(0U, navigation_list_pruned_counter_);
   EXPECT_EQ(0, controller.GetPendingEntryIndex());
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 8701dde..ee1d4b22 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -1805,10 +1805,7 @@
   // a speculative RFH.  So, a speculative main frame being deleted will always
   // pass this condition as well.
   if (was_created && render_view_host_->GetMainRenderFrameHost() != this) {
-    CHECK(IsPendingDeletion() || IsInBackForwardCache() ||
-          lifecycle_state() == LifecycleStateImpl::kPrerendering ||
-          lifecycle_state() == LifecycleStateImpl::kSpeculative)
-        << lifecycle_state();
+    CHECK_NE(lifecycle_state(), LifecycleStateImpl::kActive);
   }
 
   GetAgentSchedulingGroup().RemoveRoute(routing_id_);
diff --git a/content/browser/renderer_host/render_frame_host_manager_browsertest.cc b/content/browser/renderer_host/render_frame_host_manager_browsertest.cc
index 01d1b89..3236768 100644
--- a/content/browser/renderer_host/render_frame_host_manager_browsertest.cc
+++ b/content/browser/renderer_host/render_frame_host_manager_browsertest.cc
@@ -49,6 +49,7 @@
 #include "content/browser/webui/web_ui_impl.h"
 #include "content/common/content_constants_internal.h"
 #include "content/common/content_navigation_policy.h"
+#include "content/common/features.h"
 #include "content/public/browser/browser_child_process_host.h"
 #include "content/public/browser/child_process_launcher_utils.h"
 #include "content/public/browser/navigation_controller.h"
@@ -1678,16 +1679,11 @@
 IN_PROC_BROWSER_TEST_P(
     RenderFrameHostManagerTest,
     DeleteSpeculativeRFHPendingCommitOfPendingEntryOnInterrupted1) {
-  if (ShouldCreateNewHostForAllFrames()) {
-    // This test involves starting a navigation while another navigation is
-    // committing, which might lead to deletion of a pending commit RFH, which
-    // will crash when RenderDocument is enabled. Skip the test if so.
-    // TODO(https://crbug.com/1220337): Update this test to work under
-    // navigation queueing, which will prevent the deletion of the pending
-    // commit RFH but still fails because this test actually expects the pending
-    // commit RFH to get deleted.
-    return;
+  if (!AreAllSitesIsolatedForTesting()) {
+    GTEST_SKIP() << "This test requires speculative RenderFrameHosts, so skip "
+                    "it when site isolation is turned off";
   }
+
   const std::string kOriginalPath = "/original.html";
   const std::string kFirstRedirectPath = "/redirect1.html";
   const std::string kSecondRedirectPath = "/reidrect2.html";
@@ -1755,40 +1751,39 @@
       "Content-Type: text/html; charset=utf-8\r\n"
       "\r\n");
   EXPECT_TRUE(first_reload.WaitForResponse());
-  first_reload.ResumeNavigation();
 
-  // The navigation is ready to commit: it has been handed to the speculative
-  // RenderFrameHost for commit if Site Isolation is enabled, otherwise it
-  // commits in the same RenderFrameHost.
-  RenderFrameHostImpl* speculative_rfh =
-      static_cast<WebContentsImpl*>(shell()->web_contents())
-          ->GetPrimaryFrameTree()
-          .root()
-          ->render_manager()
-          ->speculative_frame_host();
-  if (AreAllSitesIsolatedForTesting()) {
-    CHECK(speculative_rfh);
-  } else {
-    CHECK(!speculative_rfh);
-  }
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetPrimaryFrameTree()
+                            .root();
+  RenderFrameHostImplWrapper first_speculative_rfh(
+      root->render_manager()->speculative_frame_host());
+  EXPECT_TRUE(first_speculative_rfh.get());
 
   // The user requests a new reload while the previous reload hasn't committed
-  // yet. The navigation start deletes the speculative RenderFrameHost that was
-  // supposed to commit the browser-initiated navigation, unless Site Isolation
-  // is enabled. This should not crash.
+  // yet. This second reload starts immediately after pausing the commit of the
+  // first reload. It might delete the speculative RenderFrameHost that was
+  // supposed to commit the first reload. This should not crash.
   TestNavigationManager second_reload(shell()->web_contents(), kOriginalURL);
+  CommitNavigationPauser commit_pauser(first_speculative_rfh.get());
+  first_reload.ResumeNavigation();
+  commit_pauser.WaitForCommitAndPause();
   shell()->web_contents()->GetController().Reload(
       ReloadType::ORIGINAL_REQUEST_URL, false);
   EXPECT_TRUE(second_reload.WaitForRequestStart());
-  speculative_rfh = static_cast<WebContentsImpl*>(shell()->web_contents())
-                        ->GetPrimaryFrameTree()
-                        .root()
-                        ->render_manager()
-                        ->speculative_frame_host();
-  if (AreAllSitesIsolatedForTesting()) {
-    EXPECT_TRUE(speculative_rfh);
+
+  RenderFrameHostImplWrapper second_speculative_rfh(
+      root->render_manager()->speculative_frame_host());
+
+  EXPECT_TRUE(second_speculative_rfh.get());
+  if (ShouldQueueNavigationsWhenPendingCommitRFHExists()) {
+    // When navigation queueing is enabled, the first speculative RFH is still
+    // kept around as it is pending commit.
+    EXPECT_TRUE(first_speculative_rfh.get());
+    EXPECT_EQ(first_speculative_rfh.get(), second_speculative_rfh.get());
   } else {
-    EXPECT_FALSE(speculative_rfh);
+    // Otherwise, the first speculative RFH will be deleted and replaced by a
+    // new speculative RFH.
+    EXPECT_FALSE(first_speculative_rfh.get());
   }
 
   // The second reload results in a 204.
@@ -1799,12 +1794,17 @@
       "Connection: close\r\n"
       "\r\n");
   ASSERT_TRUE(second_reload.WaitForNavigationFinished());
-  speculative_rfh = static_cast<WebContentsImpl*>(shell()->web_contents())
-                        ->GetPrimaryFrameTree()
-                        .root()
-                        ->render_manager()
-                        ->speculative_frame_host();
-  EXPECT_FALSE(speculative_rfh);
+
+  if (ShouldQueueNavigationsWhenPendingCommitRFHExists()) {
+    // If navigation queuing is enabled, the first reload's speculative RFH
+    // will be kept.
+    EXPECT_TRUE(root->render_manager()->speculative_frame_host());
+  } else {
+    // If navigation queueing is turned off, the second reload will delete the
+    // first reload's speculative RFH, and we end up with no speculative RFH
+    // after the second reload commits.
+    EXPECT_FALSE(root->render_manager()->speculative_frame_host());
+  }
 }
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \
@@ -1824,6 +1824,12 @@
 IN_PROC_BROWSER_TEST_P(
     RenderFrameHostManagerTest,
     MAYBE_DeleteSpeculativeRFHPendingCommitOfPendingEntryOnInterrupted2) {
+  if (ShouldQueueNavigationsWhenPendingCommitRFHExists()) {
+    // When navigation queueing is enabled, starting a new navigation won't
+    // delete an existing pending commit RFH, so this test can't run as
+    // intended.
+    return;
+  }
   const std::string kOriginalPath = "/original.html";
   const std::string kRedirectPath = "/redirect.html";
   net::test_server::ControllableHttpResponse original_response1(
diff --git a/content/browser/renderer_host/render_frame_host_manager_unittest.cc b/content/browser/renderer_host/render_frame_host_manager_unittest.cc
index 6b0afca6..8621639d 100644
--- a/content/browser/renderer_host/render_frame_host_manager_unittest.cc
+++ b/content/browser/renderer_host/render_frame_host_manager_unittest.cc
@@ -416,7 +416,7 @@
 
     // Simulates request creation that triggers the 1st internal call to
     // GetFrameHostForNavigation.
-    manager->DidCreateNavigationRequest(navigation_request.get());
+    frame_tree_node->TakeNavigationRequest(std::move(navigation_request));
 
     // And also simulates the 2nd and final call to GetFrameHostForNavigation
     // that determines the final frame that will commit the navigation.
@@ -424,7 +424,7 @@
         BrowsingContextGroupSwap::CreateDefault();
     TestRenderFrameHost* frame_host = static_cast<TestRenderFrameHost*>(
         manager
-            ->GetFrameHostForNavigation(navigation_request.get(),
+            ->GetFrameHostForNavigation(frame_tree_node->navigation_request(),
                                         &ignored_bcg_swap_info)
             .value());
     CHECK(frame_host);
@@ -3258,7 +3258,7 @@
           nullptr /* navigation_ui_data */, absl::nullopt /* impression */,
           false /* is_pdf */
       );
-  manager->DidCreateNavigationRequest(navigation_request.get());
+  frame_tree_node->TakeNavigationRequest(std::move(navigation_request));
 
   // As the initial RenderFrame was not live, the new RenderFrameHost should be
   // made as active/current immediately along with its WebUI at request time.
@@ -3274,8 +3274,9 @@
   BrowsingContextGroupSwap ignored_bcg_swap_info =
       BrowsingContextGroupSwap::CreateDefault();
   EXPECT_EQ(host, manager
-                      ->GetFrameHostForNavigation(navigation_request.get(),
-                                                  &ignored_bcg_swap_info)
+                      ->GetFrameHostForNavigation(
+                          frame_tree_node->navigation_request(),
+                          &ignored_bcg_swap_info)
                       .value());
 
   // No pending RenderFrameHost as the current one should be reused.
diff --git a/content/public/test/test_utils.cc b/content/public/test/test_utils.cc
index d24fb05..6a85216c 100644
--- a/content/public/test/test_utils.cc
+++ b/content/public/test/test_utils.cc
@@ -232,6 +232,10 @@
          IsBackForwardCacheEnabled();
 }
 
+bool IsNavigationQueueingEnabled() {
+  return ShouldQueueNavigationsWhenPendingCommitRFHExists();
+}
+
 void DisableProactiveBrowsingInstanceSwapFor(RenderFrameHost* rfh) {
   if (!CanSameSiteMainFrameNavigationsChangeSiteInstances())
     return;
@@ -486,8 +490,9 @@
 }
 
 RenderFrameHostWrapper::RenderFrameHostWrapper(RenderFrameHost* rfh)
-    : rfh_id_(rfh->GetGlobalId()),
-      deleted_observer_(std::make_unique<RenderFrameDeletedObserver>(rfh)) {}
+    : rfh_id_(rfh ? rfh->GetGlobalId() : GlobalRenderFrameHostId()),
+      deleted_observer_(rfh ? std::make_unique<RenderFrameDeletedObserver>(rfh)
+                            : nullptr) {}
 
 RenderFrameHostWrapper::RenderFrameHostWrapper(RenderFrameHostWrapper&& rfhft) =
     default;
@@ -504,10 +509,12 @@
 // See RenderFrameDeletedObserver for notes on the difference between
 // RenderFrame being deleted and RenderFrameHost being destroyed.
 bool RenderFrameHostWrapper::WaitUntilRenderFrameDeleted() const {
+  CHECK(deleted_observer_);
   return deleted_observer_->WaitUntilDeleted();
 }
 
 bool RenderFrameHostWrapper::IsRenderFrameDeleted() const {
+  CHECK(deleted_observer_);
   return deleted_observer_->deleted();
 }
 
diff --git a/content/public/test/test_utils.h b/content/public/test/test_utils.h
index f457a69..6cbd17a 100644
--- a/content/public/test/test_utils.h
+++ b/content/public/test/test_utils.h
@@ -133,6 +133,10 @@
 // above, this will not be true when RenderDocument for main-frame is enabled.
 bool CanSameSiteMainFrameNavigationsChangeSiteInstances();
 
+// Returns true if navigation queueing is fully enabled, where we will queue new
+// navigations that happen when there is an existing pending commit navigation.
+bool IsNavigationQueueingEnabled();
+
 // Makes sure that navigations that start in |rfh| won't result in a proactive
 // BrowsingInstance swap (note they might still result in a normal
 // BrowsingInstance swap, e.g. in the case of cross-site navigations).
diff --git a/services/webnn/dml/command_queue.cc b/services/webnn/dml/command_queue.cc
index 4d3c5e0..faa8310 100644
--- a/services/webnn/dml/command_queue.cc
+++ b/services/webnn/dml/command_queue.cc
@@ -12,8 +12,11 @@
 
 CommandQueue::CommandQueue(ComPtr<ID3D12CommandQueue> command_queue,
                            ComPtr<ID3D12Fence> fence)
-    : command_queue_(std::move(command_queue)), fence_(std::move(fence)) {
-  fence_event_.Set(CreateEvent(nullptr, FALSE, FALSE, nullptr));
+    : base::win::ObjectWatcher::Delegate(),
+      command_queue_(std::move(command_queue)),
+      fence_(std::move(fence)) {
+  fence_event_.Set(CreateEvent(nullptr, /*bManualReset=*/FALSE,
+                               /*bInitialState=*/FALSE, nullptr));
   CHECK(fence_event_.is_valid());
 }
 
@@ -46,11 +49,6 @@
       new CommandQueue(std::move(command_queue), std::move(fence)));
 }
 
-void CommandQueue::ReferenceUntilCompleted(ComPtr<IUnknown> object) {
-  QueuedObject queue_object = {last_fence_value_, std::move(object)};
-  queued_objects_.push_back(queue_object);
-}
-
 HRESULT CommandQueue::ExecuteCommandLists(
     const std::vector<ID3D12CommandList*>& command_lists) {
   command_queue_->ExecuteCommandLists(command_lists.size(),
@@ -59,17 +57,50 @@
   return command_queue_->Signal(fence_.Get(), last_fence_value_);
 }
 
-void CommandQueue::WaitForTesting() {
+HRESULT CommandQueue::WaitSyncForTesting() {
   CHECK_IS_TEST();
   if (fence_->GetCompletedValue() >= last_fence_value_) {
-    return;
+    return S_OK;
   }
+
   HRESULT hr =
-      fence_->SetEventOnCompletion(last_fence_value_, fence_event_.Get());
+      fence_->SetEventOnCompletion(last_fence_value_, fence_event_.get());
   if (FAILED(hr)) {
-    return;
+    DLOG(ERROR) << "Failed to set event on completion : "
+                << logging::SystemErrorCodeToString(hr);
+    return hr;
+  };
+  CHECK_EQ(WaitForSingleObject(fence_event_.get(), INFINITE), WAIT_OBJECT_0);
+  return S_OK;
+}
+
+void CommandQueue::OnObjectSignaled(HANDLE object) {
+  CHECK_EQ(object, fence_event_.get());
+  while (!queued_callbacks_.empty() &&
+         queued_callbacks_.front().fence_value <= fence_->GetCompletedValue()) {
+    std::move(queued_callbacks_.front().callback).Run();
+    queued_callbacks_.pop_front();
   }
-  CHECK_EQ(WaitForSingleObject(fence_event_.Get(), INFINITE), WAIT_OBJECT_0);
+}
+
+HRESULT CommandQueue::WaitAsync(base::OnceClosure callback) {
+  if (!object_watcher_.IsWatching()) {
+    CHECK(object_watcher_.StartWatchingMultipleTimes(fence_event_.get(), this));
+  }
+
+  HRESULT hr =
+      fence_->SetEventOnCompletion(last_fence_value_, fence_event_.get());
+  if (FAILED(hr)) {
+    DLOG(ERROR) << "Failed to set event on completion : "
+                << logging::SystemErrorCodeToString(hr);
+    return hr;
+  };
+  queued_callbacks_.push_back({last_fence_value_, std::move(callback)});
+  return S_OK;
+}
+
+void CommandQueue::ReferenceUntilCompleted(ComPtr<IUnknown> object) {
+  queued_objects_.push_back({last_fence_value_, std::move(object)});
 }
 
 void CommandQueue::ReleaseCompletedResources() {
@@ -81,14 +112,19 @@
 }
 
 CommandQueue::QueuedObject::QueuedObject(uint64_t fence_value,
-                                         ComPtr<IUnknown> object) {
-  this->fence_value = fence_value;
-  this->object = std::move(object);
-}
-
-CommandQueue::QueuedObject::QueuedObject(const QueuedObject& other) = default;
-
-CommandQueue::QueuedObject::QueuedObject() = default;
+                                         ComPtr<IUnknown> object)
+    : fence_value(fence_value), object(std::move(object)) {}
+CommandQueue::QueuedObject::QueuedObject(QueuedObject&& other) = default;
+CommandQueue::QueuedObject& CommandQueue::QueuedObject::operator=(
+    QueuedObject&& other) = default;
 CommandQueue::QueuedObject::~QueuedObject() = default;
 
+CommandQueue::QueuedCallback::QueuedCallback(uint64_t fence_value,
+                                             base::OnceClosure callback)
+    : fence_value(fence_value), callback(std::move(callback)) {}
+CommandQueue::QueuedCallback::QueuedCallback(QueuedCallback&& other) = default;
+CommandQueue::QueuedCallback& CommandQueue::QueuedCallback::operator=(
+    QueuedCallback&& other) = default;
+CommandQueue::QueuedCallback::~QueuedCallback() = default;
+
 }  // namespace webnn::dml
diff --git a/services/webnn/dml/command_queue.h b/services/webnn/dml/command_queue.h
index ae808f25..479cc4b 100644
--- a/services/webnn/dml/command_queue.h
+++ b/services/webnn/dml/command_queue.h
@@ -5,14 +5,14 @@
 #ifndef SERVICES_WEBNN_DML_COMMAND_QUEUE_H_
 #define SERVICES_WEBNN_DML_COMMAND_QUEUE_H_
 
-#include <DirectML.h>
 #include <d3d12.h>
 #include <wrl.h>
-
 #include <deque>
 #include <vector>
 
+#include "base/functional/callback_forward.h"
 #include "base/gtest_prod_util.h"
+#include "base/win/object_watcher.h"
 #include "base/win/scoped_handle.h"
 
 namespace webnn::dml {
@@ -21,25 +21,26 @@
 
 // The CommandQueue is a wrapper of an ID3D12CommandQueue and contains a fence
 // which is signaled when the execution on GPU is completed.
-class CommandQueue {
+class CommandQueue : public base::win::ObjectWatcher::Delegate {
  public:
   static std::unique_ptr<CommandQueue> Create(ID3D12Device* d3d12_device);
 
   CommandQueue(const CommandQueue&) = delete;
   CommandQueue& operator=(const CommandQueue&) = delete;
-  ~CommandQueue();
+  ~CommandQueue() override;
 
-  void ReferenceUntilCompleted(ComPtr<IUnknown> object);
   HRESULT ExecuteCommandLists(
       const std::vector<ID3D12CommandList*>& command_lists);
 
-  // It's a synchronous method only for testing, which will block the GPU until
+  // It's a synchronous method only for testing, which will block the CPU until
   // the fence is signaled with the last fence value. Calling it on the GPU main
   // thread may block the UI.
-  //
-  // TODO(crbug.com/1273291): Add asynchronous WaitAsync() by using
-  // base::WaitableEventWatcher.
-  void WaitForTesting();
+  HRESULT WaitSyncForTesting();
+  // It's an asynchronous method for DirectML graph implementation, which will
+  // not block the CPU.
+  HRESULT WaitAsync(base::OnceClosure callback);
+
+  void ReferenceUntilCompleted(ComPtr<IUnknown> object);
   void ReleaseCompletedResources();
 
  private:
@@ -49,9 +50,10 @@
                ComPtr<ID3D12Fence> fence);
 
   struct QueuedObject {
-    QueuedObject();
-    QueuedObject(const QueuedObject& other);
+    QueuedObject() = delete;
     QueuedObject(uint64_t fence_value, ComPtr<IUnknown> object);
+    QueuedObject(QueuedObject&& other);
+    QueuedObject& operator=(QueuedObject&& other);
     ~QueuedObject();
 
     uint64_t fence_value = 0;
@@ -59,6 +61,21 @@
   };
   std::deque<QueuedObject> queued_objects_;
 
+  struct QueuedCallback {
+    QueuedCallback() = delete;
+    QueuedCallback(uint64_t fence_value, base::OnceClosure callback);
+    QueuedCallback(QueuedCallback&& other);
+    QueuedCallback& operator=(QueuedCallback&& other);
+    ~QueuedCallback();
+
+    uint64_t fence_value = 0;
+    base::OnceClosure callback;
+  };
+  std::deque<QueuedCallback> queued_callbacks_;
+
+  // Implements base::win::ObjectWatcher::Delegate.
+  void OnObjectSignaled(HANDLE object) override;
+
   ComPtr<ID3D12CommandQueue> command_queue_;
 
   // The increasing fence value is used to track the progress of GPU execution
@@ -66,7 +83,9 @@
   // the work has been completed.
   uint64_t last_fence_value_ = 0;
   ComPtr<ID3D12Fence> fence_;
+
   base::win::ScopedHandle fence_event_;
+  base::win::ObjectWatcher object_watcher_;
 };
 
 }  // namespace webnn::dml
diff --git a/services/webnn/dml/command_queue_test.cc b/services/webnn/dml/command_queue_test.cc
index 3ae3a72d5..92fee72 100644
--- a/services/webnn/dml/command_queue_test.cc
+++ b/services/webnn/dml/command_queue_test.cc
@@ -5,6 +5,9 @@
 #include <d3d11.h>
 #include <wrl.h>
 
+#include "base/run_loop.h"
+#include "base/test/bind.h"
+#include "base/test/task_environment.h"
 #include "services/webnn/dml/adapter.h"
 #include "services/webnn/dml/command_queue.h"
 #include "services/webnn/dml/test_base.h"
@@ -46,7 +49,7 @@
   EXPECT_NE(CommandQueue::Create(d3d12_device_.Get()), nullptr);
 }
 
-TEST_F(WebNNCommandQueueTest, CloseExecuteWaitReset) {
+TEST_F(WebNNCommandQueueTest, WaitSyncForGpuWorkCompleted) {
   ASSERT_NE(d3d12_device_.Get(), nullptr);
   ComPtr<ID3D12CommandAllocator> command_allocator;
   ASSERT_EQ(
@@ -63,7 +66,144 @@
   ASSERT_NE(command_queue.get(), nullptr);
   ASSERT_EQ(command_list->Close(), S_OK);
   EXPECT_EQ(command_queue->ExecuteCommandLists({command_list.Get()}), S_OK);
-  command_queue->WaitForTesting();
+  EXPECT_EQ(command_queue->WaitSyncForTesting(), S_OK);
+  EXPECT_EQ(command_allocator->Reset(), S_OK);
+  EXPECT_EQ(command_list->Reset(command_allocator.Get(), nullptr), S_OK);
+}
+
+TEST_F(WebNNCommandQueueTest, WaitAsyncOnce) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+
+  ASSERT_NE(d3d12_device_.Get(), nullptr);
+  ComPtr<ID3D12CommandAllocator> command_allocator;
+  ASSERT_EQ(
+      (d3d12_device_->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT,
+                                             IID_PPV_ARGS(&command_allocator))),
+      S_OK);
+  ComPtr<ID3D12GraphicsCommandList> command_list;
+  ASSERT_EQ(d3d12_device_->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT,
+                                             command_allocator.Get(), nullptr,
+                                             IID_PPV_ARGS(&command_list)),
+            S_OK);
+  std::unique_ptr<CommandQueue> command_queue =
+      CommandQueue::Create(d3d12_device_.Get());
+  ASSERT_NE(command_queue.get(), nullptr);
+  ASSERT_EQ(command_list->Close(), S_OK);
+  EXPECT_EQ(command_queue->ExecuteCommandLists({command_list.Get()}), S_OK);
+
+  bool is_signaled = false;
+  base::RunLoop run_loop;
+  EXPECT_EQ(command_queue->WaitAsync(base::BindLambdaForTesting([&]() {
+    is_signaled = true;
+    run_loop.Quit();
+  })),
+            S_OK);
+  run_loop.Run();
+  EXPECT_TRUE(is_signaled);
+
+  EXPECT_EQ(command_allocator->Reset(), S_OK);
+  EXPECT_EQ(command_list->Reset(command_allocator.Get(), nullptr), S_OK);
+}
+
+TEST_F(WebNNCommandQueueTest, WaitAsyncMultipleTimesOnIncreasingFenceValue) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+
+  ASSERT_NE(d3d12_device_.Get(), nullptr);
+  ComPtr<ID3D12CommandAllocator> command_allocator;
+  ASSERT_EQ(
+      (d3d12_device_->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT,
+                                             IID_PPV_ARGS(&command_allocator))),
+      S_OK);
+  ComPtr<ID3D12GraphicsCommandList> command_list;
+  ASSERT_EQ(d3d12_device_->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT,
+                                             command_allocator.Get(), nullptr,
+                                             IID_PPV_ARGS(&command_list)),
+            S_OK);
+  std::unique_ptr<CommandQueue> command_queue =
+      CommandQueue::Create(d3d12_device_.Get());
+  ASSERT_NE(command_queue.get(), nullptr);
+  ASSERT_EQ(command_list->Close(), S_OK);
+  EXPECT_EQ(command_queue->ExecuteCommandLists({command_list.Get()}), S_OK);
+
+  int32_t count = 2;
+  base::RunLoop run_loop;
+
+  // Call WaitAsync for the first time with fence value 1.
+  EXPECT_EQ(command_queue->WaitAsync(base::BindLambdaForTesting([&]() {
+    if (--count) {
+      return;
+    } else {
+      run_loop.Quit();
+    }
+  })),
+            S_OK);
+
+  EXPECT_EQ(command_allocator->Reset(), S_OK);
+  EXPECT_EQ(command_list->Reset(command_allocator.Get(), nullptr), S_OK);
+
+  // Call WaitAsync for the second time with fence value 2.
+  ASSERT_EQ(command_list->Close(), S_OK);
+  EXPECT_EQ(command_queue->ExecuteCommandLists({command_list.Get()}), S_OK);
+  EXPECT_EQ(command_queue->WaitAsync(base::BindLambdaForTesting([&]() {
+    if (--count) {
+      return;
+    } else {
+      run_loop.Quit();
+    }
+  })),
+            S_OK);
+
+  run_loop.Run();
+  EXPECT_EQ(count, 0);
+  EXPECT_EQ(command_allocator->Reset(), S_OK);
+  EXPECT_EQ(command_list->Reset(command_allocator.Get(), nullptr), S_OK);
+}
+
+TEST_F(WebNNCommandQueueTest, WaitAsyncMultipleTimesOnSameFenceValue) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+
+  ASSERT_NE(d3d12_device_.Get(), nullptr);
+  ComPtr<ID3D12CommandAllocator> command_allocator;
+  ASSERT_EQ(
+      (d3d12_device_->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT,
+                                             IID_PPV_ARGS(&command_allocator))),
+      S_OK);
+  ComPtr<ID3D12GraphicsCommandList> command_list;
+  ASSERT_EQ(d3d12_device_->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT,
+                                             command_allocator.Get(), nullptr,
+                                             IID_PPV_ARGS(&command_list)),
+            S_OK);
+  std::unique_ptr<CommandQueue> command_queue =
+      CommandQueue::Create(d3d12_device_.Get());
+  ASSERT_NE(command_queue.get(), nullptr);
+  ASSERT_EQ(command_list->Close(), S_OK);
+  EXPECT_EQ(command_queue->ExecuteCommandLists({command_list.Get()}), S_OK);
+
+  int32_t count = 2;
+  base::RunLoop run_loop;
+
+  // Call WaitAsync for the first time with fence value 1.
+  EXPECT_EQ(command_queue->WaitAsync(base::BindLambdaForTesting([&]() {
+    if (--count) {
+      return;
+    } else {
+      run_loop.Quit();
+    }
+  })),
+            S_OK);
+
+  // Call WaitAsync for the second time on the same fence value 1.
+  EXPECT_EQ(command_queue->WaitAsync(base::BindLambdaForTesting([&]() {
+    if (--count) {
+      return;
+    } else {
+      run_loop.Quit();
+    }
+  })),
+            S_OK);
+
+  run_loop.Run();
+  EXPECT_EQ(count, 0);
   EXPECT_EQ(command_allocator->Reset(), S_OK);
   EXPECT_EQ(command_list->Reset(command_allocator.Get(), nullptr), S_OK);
 }
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 50489de..ddebbd3 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -5736,9 +5736,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5796.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5798.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 116.0.5796.0",
+        "description": "Run with ash-chrome version 116.0.5798.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5749,8 +5749,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v116.0.5796.0",
-              "revision": "version:116.0.5796.0"
+              "location": "lacros_version_skew_tests_v116.0.5798.0",
+              "revision": "version:116.0.5798.0"
             }
           ],
           "dimension_sets": [
@@ -5901,9 +5901,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5796.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5798.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 116.0.5796.0",
+        "description": "Run with ash-chrome version 116.0.5798.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5914,8 +5914,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v116.0.5796.0",
-              "revision": "version:116.0.5796.0"
+              "location": "lacros_version_skew_tests_v116.0.5798.0",
+              "revision": "version:116.0.5798.0"
             }
           ],
           "dimension_sets": [
@@ -6048,9 +6048,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5796.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5798.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 116.0.5796.0",
+        "description": "Run with ash-chrome version 116.0.5798.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -6061,8 +6061,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v116.0.5796.0",
-              "revision": "version:116.0.5796.0"
+              "location": "lacros_version_skew_tests_v116.0.5798.0",
+              "revision": "version:116.0.5798.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json
index 45f853c..e3a98a5 100644
--- a/testing/buildbot/chromium.coverage.json
+++ b/testing/buildbot/chromium.coverage.json
@@ -25494,9 +25494,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5796.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5798.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 116.0.5796.0",
+        "description": "Run with ash-chrome version 116.0.5798.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -25507,8 +25507,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v116.0.5796.0",
-              "revision": "version:116.0.5796.0"
+              "location": "lacros_version_skew_tests_v116.0.5798.0",
+              "revision": "version:116.0.5798.0"
             }
           ],
           "dimension_sets": [
@@ -25659,9 +25659,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5796.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5798.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 116.0.5796.0",
+        "description": "Run with ash-chrome version 116.0.5798.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -25672,8 +25672,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v116.0.5796.0",
-              "revision": "version:116.0.5796.0"
+              "location": "lacros_version_skew_tests_v116.0.5798.0",
+              "revision": "version:116.0.5798.0"
             }
           ],
           "dimension_sets": [
@@ -25806,9 +25806,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5796.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5798.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 116.0.5796.0",
+        "description": "Run with ash-chrome version 116.0.5798.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -25819,8 +25819,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v116.0.5796.0",
-              "revision": "version:116.0.5796.0"
+              "location": "lacros_version_skew_tests_v116.0.5798.0",
+              "revision": "version:116.0.5798.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index c883f50..debd3a2a 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -45686,9 +45686,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5796.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5798.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 116.0.5796.0",
+        "description": "Run with ash-chrome version 116.0.5798.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -45698,8 +45698,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v116.0.5796.0",
-              "revision": "version:116.0.5796.0"
+              "location": "lacros_version_skew_tests_v116.0.5798.0",
+              "revision": "version:116.0.5798.0"
             }
           ],
           "dimension_sets": [
@@ -45851,9 +45851,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5796.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5798.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 116.0.5796.0",
+        "description": "Run with ash-chrome version 116.0.5798.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -45863,8 +45863,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v116.0.5796.0",
-              "revision": "version:116.0.5796.0"
+              "location": "lacros_version_skew_tests_v116.0.5798.0",
+              "revision": "version:116.0.5798.0"
             }
           ],
           "dimension_sets": [
@@ -45998,9 +45998,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5796.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5798.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 116.0.5796.0",
+        "description": "Run with ash-chrome version 116.0.5798.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -46010,8 +46010,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v116.0.5796.0",
-              "revision": "version:116.0.5796.0"
+              "location": "lacros_version_skew_tests_v116.0.5798.0",
+              "revision": "version:116.0.5798.0"
             }
           ],
           "dimension_sets": [
@@ -47475,9 +47475,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5796.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5798.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 116.0.5796.0",
+        "description": "Run with ash-chrome version 116.0.5798.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -47487,8 +47487,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v116.0.5796.0",
-              "revision": "version:116.0.5796.0"
+              "location": "lacros_version_skew_tests_v116.0.5798.0",
+              "revision": "version:116.0.5798.0"
             }
           ],
           "dimension_sets": [
@@ -47640,9 +47640,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5796.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5798.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 116.0.5796.0",
+        "description": "Run with ash-chrome version 116.0.5798.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -47652,8 +47652,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v116.0.5796.0",
-              "revision": "version:116.0.5796.0"
+              "location": "lacros_version_skew_tests_v116.0.5798.0",
+              "revision": "version:116.0.5798.0"
             }
           ],
           "dimension_sets": [
@@ -47787,9 +47787,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5796.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5798.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 116.0.5796.0",
+        "description": "Run with ash-chrome version 116.0.5798.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -47799,8 +47799,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v116.0.5796.0",
-              "revision": "version:116.0.5796.0"
+              "location": "lacros_version_skew_tests_v116.0.5798.0",
+              "revision": "version:116.0.5798.0"
             }
           ],
           "dimension_sets": [
@@ -48535,9 +48535,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5796.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5798.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 116.0.5796.0",
+        "description": "Run with ash-chrome version 116.0.5798.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -48547,8 +48547,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v116.0.5796.0",
-              "revision": "version:116.0.5796.0"
+              "location": "lacros_version_skew_tests_v116.0.5798.0",
+              "revision": "version:116.0.5798.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 5b24915..1d88985 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -18080,12 +18080,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5796.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5798.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 116.0.5796.0",
+        "description": "Run with ash-chrome version 116.0.5798.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -18096,8 +18096,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v116.0.5796.0",
-              "revision": "version:116.0.5796.0"
+              "location": "lacros_version_skew_tests_v116.0.5798.0",
+              "revision": "version:116.0.5798.0"
             }
           ],
           "dimension_sets": [
@@ -18265,12 +18265,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5796.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5798.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 116.0.5796.0",
+        "description": "Run with ash-chrome version 116.0.5798.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -18281,8 +18281,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v116.0.5796.0",
-              "revision": "version:116.0.5796.0"
+              "location": "lacros_version_skew_tests_v116.0.5798.0",
+              "revision": "version:116.0.5798.0"
             }
           ],
           "dimension_sets": [
@@ -18427,12 +18427,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5796.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5798.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 116.0.5796.0",
+        "description": "Run with ash-chrome version 116.0.5798.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -18443,8 +18443,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v116.0.5796.0",
-              "revision": "version:116.0.5796.0"
+              "location": "lacros_version_skew_tests_v116.0.5798.0",
+              "revision": "version:116.0.5798.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index a474c32..c89731a 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -22,16 +22,16 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5796.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5798.0/test_ash_chrome',
     ],
-    'description': 'Run with ash-chrome version 116.0.5796.0',
+    'description': 'Run with ash-chrome version 116.0.5798.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_v116.0.5796.0',
-          'revision': 'version:116.0.5796.0',
+          'location': 'lacros_version_skew_tests_v116.0.5798.0',
+          'revision': 'version:116.0.5798.0',
         },
       ],
     },
diff --git a/third_party/blink/perf_tests/MotionMark/resources/debug-runner/tests.js b/third_party/blink/perf_tests/MotionMark/resources/debug-runner/tests.js
index ed96349..f5b0866f 100644
--- a/third_party/blink/perf_tests/MotionMark/resources/debug-runner/tests.js
+++ b/third_party/blink/perf_tests/MotionMark/resources/debug-runner/tests.js
@@ -427,10 +427,6 @@
             name: "Canvas ellipses"
         },
         {
-            url: "simple/simple-canvas-paths.html?pathType=spreadSheets",
-            name: "Canvas Spreadsheets"
-        },
-        {
             url: "simple/simple-canvas-paths.html?pathType=lineFill",
             name: "Canvas line path, fill"
         },
diff --git a/third_party/blink/perf_tests/MotionMark/tests/simple/resources/simple-canvas-paths.js b/third_party/blink/perf_tests/MotionMark/tests/simple/resources/simple-canvas-paths.js
index b7a31e2..143630d 100644
--- a/third_party/blink/perf_tests/MotionMark/tests/simple/resources/simple-canvas-paths.js
+++ b/third_party/blink/perf_tests/MotionMark/tests/simple/resources/simple-canvas-paths.js
@@ -269,51 +269,6 @@
     }
 });
 
-CanvasSpreadSheets = Utilities.createClass(
-    function(stage) {
-        // Some good dark color for writing text in spreadsheet.
-        var dark_colors = ['#000000', '#404040', '#00008B', '#442D16', '#7E0000'];
-        // Some good light color for filling cells in spreadsheet.
-        var light_colors = ['#ADFF2F', '#ADD8E6', '#FFC0CB', '#E3C8C8', '#EBEEAF'];
-        // Possible text alignment in spreadsheet.
-        var align = ['left', 'right', 'center', 'start' , 'end']
-        this._text_color = dark_colors[Stage.randomInt(0, 5)];
-        this._fill_color = light_colors[Stage.randomInt(0, 5)];
-        this._text_align = align[Stage.randomInt(0, 5)];
-        this._start = Stage.randomPosition(stage.size)
-        this._color = Stage.randomColor();
-        this._cell_width = Stage.randomInt(90, 150);
-        this._cell_height = Stage.randomInt(20, 30);
-        this._font = Stage.randomInt(10, 40) + 'px Arial';
-        this._border_style_index = Stage.randomInt(0, 3);
-        this._color = Stage.randomColor();
-    }, {
-    draw: function(context) {
-        context.save();
-        rectPath = new Path2D();
-        rectPath.rect(this._start.x, this._start.y, this._cell_width, this._cell_height);
-        context.clip(rectPath);
-        context.beginPath();
-        context.globalAlpha = 0.5;
-        context.fillStyle = this._fill_color;
-        context.fill(rectPath);
-        context.globalAlpha = 1;
-        context.font = this._font;
-        context.fillStyle = this._text_color;
-        context.textAlign = this._text_align;
-        context.fillText("hello world", (this._start.x + this._start.x + this._cell_width)/2, this._start.y + this._cell_height);
-        if (this._border_style_index === 0) {
-            context.setLineDash([5, 5]);
-        } else if (this._border_style_index === 1) {
-            context.globalAlpha = 0.5;
-        } else {
-            context.strokeStyle = "#000000";
-        }
-        context.stroke(rectPath);
-        context.restore();
-    }
-});
-
 CanvasStroke = Utilities.createClass(
     function (stage) {
         this._object = new (Stage.randomElementInArray(this.objectTypes))(stage);
@@ -505,9 +460,6 @@
         case "ellipseFill":
             stage = new SimpleCanvasStage(CanvasEllipseFill);
             break;
-        case "spreadSheets":
-            stage = new SimpleCanvasStage(CanvasSpreadSheets);
-            break;
         case "strokes":
             stage = new SimpleCanvasStage(CanvasStroke);
             break;
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_font_cache.cc b/third_party/blink/renderer/core/html/canvas/canvas_font_cache.cc
index d867623..1da846a 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_font_cache.cc
+++ b/third_party/blink/renderer/core/html/canvas/canvas_font_cache.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/platform/font_family_names.h"
 #include "third_party/blink/renderer/platform/fonts/font_cache.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h"
@@ -23,16 +24,16 @@
 const unsigned CanvasFontCacheHardMaxFontsLowEnd = 20;
 const unsigned CanvasFontCacheHiddenMaxFonts = 1;
 const int defaultFontSize = 10;
-const char defaultFontFamily[] = "sans-serif";
 }
 
 namespace blink {
 
 CanvasFontCache::CanvasFontCache(Document& document)
     : document_(&document), pruning_scheduled_(false) {
+  const AtomicString& default_font_family = font_family_names::kSansSerif;
   FontFamily font_family;
-  font_family.SetFamily(defaultFontFamily,
-                        FontFamily::InferredTypeFor(defaultFontFamily));
+  font_family.SetFamily(default_font_family,
+                        FontFamily::InferredTypeFor(default_font_family));
   FontDescription default_font_description;
   default_font_description.SetFamily(font_family);
   default_font_description.SetSpecifiedSize(defaultFontSize);
diff --git a/third_party/blink/renderer/core/html/custom/custom_element.cc b/third_party/blink/renderer/core/html/custom/custom_element.cc
index 9a72079..06b32b68 100644
--- a/third_party/blink/renderer/core/html/custom/custom_element.cc
+++ b/third_party/blink/renderer/core/html/custom/custom_element.cc
@@ -92,9 +92,14 @@
   // first.
   DEFINE_STATIC_LOCAL(HashSet<AtomicString>, hyphenated_spec_element_names,
                       ({
-                          "annotation-xml", "color-profile", "font-face",
-                          "font-face-src", "font-face-uri", "font-face-format",
-                          "font-face-name", "missing-glyph",
+                          AtomicString("annotation-xml"),
+                          AtomicString("color-profile"),
+                          AtomicString("font-face"),
+                          AtomicString("font-face-src"),
+                          AtomicString("font-face-uri"),
+                          AtomicString("font-face-format"),
+                          AtomicString("font-face-name"),
+                          AtomicString("missing-glyph"),
                       }));
   return hyphenated_spec_element_names.Contains(name);
 }
diff --git a/third_party/blink/renderer/core/html/forms/file_input_type.cc b/third_party/blink/renderer/core/html/forms/file_input_type.cc
index 7fef490..f08c58b8 100644
--- a/third_party/blink/renderer/core/html/forms/file_input_type.cc
+++ b/third_party/blink/renderer/core/html/forms/file_input_type.cc
@@ -38,6 +38,7 @@
 #include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/core/input_type_names.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/core/keywords.h"
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
 #include "third_party/blink/renderer/core/page/chrome_client.h"
 #include "third_party/blink/renderer/core/page/drag_data.h"
@@ -351,8 +352,8 @@
   // The file input element is presented to AX as one node with the role button,
   // instead of the individual button and text nodes. That's the reason we hide
   // the shadow root elements of the file input in the AX tree.
-  button->setAttribute(html_names::kAriaHiddenAttr, "true");
-  span->setAttribute(html_names::kAriaHiddenAttr, "true");
+  button->setAttribute(html_names::kAriaHiddenAttr, keywords::kTrue);
+  span->setAttribute(html_names::kAriaHiddenAttr, keywords::kTrue);
 
   UpdateView();
 }
diff --git a/third_party/blink/renderer/core/html/forms/html_form_control_element.cc b/third_party/blink/renderer/core/html/forms/html_form_control_element.cc
index cfffcf97..bec63ab1 100644
--- a/third_party/blink/renderer/core/html/forms/html_form_control_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_form_control_element.cc
@@ -213,8 +213,9 @@
 
 bool HTMLFormControlElement::IsAutocompleteEmailUrlOrPassword() const {
   DEFINE_STATIC_LOCAL(HashSet<AtomicString>, values,
-                      ({"username", "new-password", "current-password", "url",
-                        "email", "impp"}));
+                      ({AtomicString("username"), AtomicString("new-password"),
+                        AtomicString("current-password"), AtomicString("url"),
+                        AtomicString("email"), AtomicString("impp")}));
   const AtomicString& autocomplete =
       FastGetAttribute(html_names::kAutocompleteAttr);
   if (autocomplete.IsNull())
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.cc b/third_party/blink/renderer/core/html/forms/html_input_element.cc
index 45c4059d..3709a0f6 100644
--- a/third_party/blink/renderer/core/html/forms/html_input_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_input_element.cc
@@ -1141,7 +1141,7 @@
       return FastGetAttribute(html_names::kValueAttr);
     case ValueMode::kDefaultOn: {
       AtomicString value_string = FastGetAttribute(html_names::kValueAttr);
-      return value_string.IsNull() ? "on" : value_string;
+      return value_string.IsNull() ? AtomicString("on") : value_string;
     }
     case ValueMode::kValue:
       return non_attribute_value_;
diff --git a/third_party/blink/renderer/core/html/forms/html_select_menu_element.cc b/third_party/blink/renderer/core/html/forms/html_select_menu_element.cc
index 0769a9a..574a2bc 100644
--- a/third_party/blink/renderer/core/html/forms/html_select_menu_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_select_menu_element.cc
@@ -243,44 +243,48 @@
 
   Document& document = GetDocument();
 
+  AtomicString button_part(kButtonPartName);
   button_slot_ = MakeGarbageCollected<HTMLSlotElement>(document);
-  button_slot_->setAttribute(html_names::kNameAttr, kButtonPartName);
+  button_slot_->setAttribute(html_names::kNameAttr, button_part);
 
   button_part_ = MakeGarbageCollected<HTMLButtonElement>(document);
-  button_part_->setAttribute(html_names::kPartAttr, kButtonPartName);
-  button_part_->setAttribute(html_names::kBehaviorAttr, kButtonPartName);
+  button_part_->setAttribute(html_names::kPartAttr, button_part);
+  button_part_->setAttribute(html_names::kBehaviorAttr, button_part);
   button_part_->SetShadowPseudoId(AtomicString("-internal-selectmenu-button"));
   button_part_listener_ =
       MakeGarbageCollected<HTMLSelectMenuElement::ButtonPartEventListener>(
           this);
   button_part_listener_->AddEventListeners(button_part_);
 
+  AtomicString selected_value_part(kSelectedValuePartName);
   selected_value_slot_ = MakeGarbageCollected<HTMLSlotElement>(document);
   selected_value_slot_->setAttribute(html_names::kNameAttr,
-                                     kSelectedValuePartName);
+                                     selected_value_part);
 
   selected_value_part_ = MakeGarbageCollected<HTMLDivElement>(document);
   selected_value_part_->setAttribute(html_names::kPartAttr,
-                                     kSelectedValuePartName);
+                                     selected_value_part);
   selected_value_part_->setAttribute(html_names::kBehaviorAttr,
-                                     kSelectedValuePartName);
+                                     selected_value_part);
 
+  AtomicString marker_part(kMarkerPartName);
   marker_slot_ = MakeGarbageCollected<HTMLSlotElement>(document);
-  marker_slot_->setAttribute(html_names::kNameAttr, kMarkerPartName);
+  marker_slot_->setAttribute(html_names::kNameAttr, marker_part);
 
   auto* marker_icon = MakeGarbageCollected<HTMLDivElement>(document);
   marker_icon->SetShadowPseudoId(
       AtomicString("-internal-selectmenu-button-icon"));
-  marker_icon->setAttribute(html_names::kPartAttr, kMarkerPartName);
+  marker_icon->setAttribute(html_names::kPartAttr, marker_part);
 
+  AtomicString listbox_part(kListboxPartName);
   listbox_slot_ = MakeGarbageCollected<HTMLSlotElement>(document);
-  listbox_slot_->setAttribute(html_names::kNameAttr, kListboxPartName);
+  listbox_slot_->setAttribute(html_names::kNameAttr, listbox_part);
 
   HTMLElement* new_popover;
   new_popover = MakeGarbageCollected<HTMLDivElement>(document);
   new_popover->setAttribute(html_names::kPopoverAttr, keywords::kAuto);
-  new_popover->setAttribute(html_names::kPartAttr, kListboxPartName);
-  new_popover->setAttribute(html_names::kBehaviorAttr, kListboxPartName);
+  new_popover->setAttribute(html_names::kPartAttr, listbox_part);
+  new_popover->setAttribute(html_names::kBehaviorAttr, listbox_part);
   new_popover->SetShadowPseudoId(AtomicString("-internal-selectmenu-listbox"));
   SetListboxPart(new_popover);
 
diff --git a/third_party/blink/renderer/core/html/forms/image_input_type.cc b/third_party/blink/renderer/core/html/forms/image_input_type.cc
index d09f745..6e8562d 100644
--- a/third_party/blink/renderer/core/html/forms/image_input_type.cc
+++ b/third_party/blink/renderer/core/html/forms/image_input_type.cc
@@ -120,8 +120,8 @@
 
 void ImageInputType::AltAttributeChanged() {
   if (GetElement().UserAgentShadowRoot()) {
-    Element* text =
-        GetElement().UserAgentShadowRoot()->getElementById("alttext");
+    Element* text = GetElement().UserAgentShadowRoot()->getElementById(
+        AtomicString("alttext"));
     String value = GetElement().AltText();
     if (text && text->textContent() != value)
       text->setTextContent(GetElement().AltText());
diff --git a/third_party/blink/renderer/core/html/forms/picker_indicator_element.cc b/third_party/blink/renderer/core/html/forms/picker_indicator_element.cc
index 33f3e36..0bc2456 100644
--- a/third_party/blink/renderer/core/html/forms/picker_indicator_element.cc
+++ b/third_party/blink/renderer/core/html/forms/picker_indicator_element.cc
@@ -169,9 +169,9 @@
   // web tests.  Once we do have it, this early return should be removed.
   if (WebTestSupport::IsRunningWebTest())
     return;
-  setAttribute(html_names::kTabindexAttr, "0");
-  setAttribute(html_names::kAriaHaspopupAttr, "menu");
-  setAttribute(html_names::kRoleAttr, "button");
+  setAttribute(html_names::kTabindexAttr, AtomicString("0"));
+  setAttribute(html_names::kAriaHaspopupAttr, AtomicString("menu"));
+  setAttribute(html_names::kRoleAttr, AtomicString("button"));
   setAttribute(
       html_names::kAriaLabelAttr,
       AtomicString(
diff --git a/third_party/blink/renderer/core/html/forms/select_type.cc b/third_party/blink/renderer/core/html/forms/select_type.cc
index fbdc0a8..c7de99c7 100644
--- a/third_party/blink/renderer/core/html/forms/select_type.cc
+++ b/third_party/blink/renderer/core/html/forms/select_type.cc
@@ -51,6 +51,7 @@
 #include "third_party/blink/renderer/core/html/forms/popup_menu.h"
 #include "third_party/blink/renderer/core/input/event_handler.h"
 #include "third_party/blink/renderer/core/input/input_device_capabilities.h"
+#include "third_party/blink/renderer/core/keywords.h"
 #include "third_party/blink/renderer/core/layout/layout_box.h"
 #include "third_party/blink/renderer/core/page/autoscroll_controller.h"
 #include "third_party/blink/renderer/core/page/chrome_client.h"
@@ -301,7 +302,7 @@
 void MenuListSelectType::CreateShadowSubtree(ShadowRoot& root) {
   Document& doc = select_->GetDocument();
   Element* inner_element = MakeGarbageCollected<MenuListInnerElement>(doc);
-  inner_element->setAttribute(html_names::kAriaHiddenAttr, "true");
+  inner_element->setAttribute(html_names::kAriaHiddenAttr, keywords::kTrue);
   // Make sure InnerElement() always has a Text node.
   inner_element->appendChild(Text::Create(doc, g_empty_string));
   root.insertBefore(inner_element, root.firstChild());
diff --git a/third_party/blink/renderer/core/html/forms/text_field_input_type.cc b/third_party/blink/renderer/core/html/forms/text_field_input_type.cc
index afd3383..5842bb6 100644
--- a/third_party/blink/renderer/core/html/forms/text_field_input_type.cc
+++ b/third_party/blink/renderer/core/html/forms/text_field_input_type.cc
@@ -45,6 +45,7 @@
 #include "third_party/blink/renderer/core/html/forms/text_control_inner_elements.h"
 #include "third_party/blink/renderer/core/html/shadow/shadow_element_names.h"
 #include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/keywords.h"
 #include "third_party/blink/renderer/core/layout/ng/layout_ng_text_control_single_line.h"
 #include "third_party/blink/renderer/core/page/chrome_client.h"
 #include "third_party/blink/renderer/core/page/page.h"
@@ -98,13 +99,13 @@
     DCHECK(ContainingShadowRoot()->IsUserAgent());
     SetShadowPseudoId(shadow_element_names::kPseudoCalendarPickerIndicator);
     setAttribute(html_names::kIdAttr, shadow_element_names::kIdPickerIndicator);
-    setAttribute(html_names::kStyleAttr,
-                 "display:list-item; "
-                 "list-style:disclosure-open inside; "
-                 "counter-increment: list-item 0;"
-                 "block-size:1em;");
+    SetInlineStyleProperty(CSSPropertyID::kDisplay, CSSValueID::kListItem);
+    SetInlineStyleProperty(CSSPropertyID::kListStyle, "disclosure-open inside");
+    SetInlineStyleProperty(CSSPropertyID::kCounterIncrement, "list-item 0");
+    SetInlineStyleProperty(CSSPropertyID::kBlockSize, 1.0,
+                           CSSPrimitiveValue::UnitType::kEms);
     // Do not expose list-item role.
-    setAttribute(html_names::kAriaHiddenAttr, "true");
+    setAttribute(html_names::kAriaHiddenAttr, keywords::kTrue);
   }
 };
 
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 157a9b0a..490e199 100644
--- a/third_party/blink/renderer/core/html/html_anchor_element.cc
+++ b/third_party/blink/renderer/core/html/html_anchor_element.cc
@@ -369,12 +369,15 @@
   link_relations_ = 0;
   SpaceSplitString new_link_relations(value.LowerASCII());
   // FIXME: Add link relations as they are implemented
-  if (new_link_relations.Contains("noreferrer"))
+  if (new_link_relations.Contains(AtomicString("noreferrer"))) {
     link_relations_ |= kRelationNoReferrer;
-  if (new_link_relations.Contains("noopener"))
+  }
+  if (new_link_relations.Contains(AtomicString("noopener"))) {
     link_relations_ |= kRelationNoOpener;
-  if (new_link_relations.Contains("opener"))
+  }
+  if (new_link_relations.Contains(AtomicString("opener"))) {
     link_relations_ |= kRelationOpener;
+  }
 }
 
 const AtomicString& HTMLAnchorElement::GetName() const {
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc
index 4f0cc09..38eaca7 100644
--- a/third_party/blink/renderer/core/html/html_element.cc
+++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -370,12 +370,12 @@
     }
   } else if (name == html_names::kDraggableAttr) {
     UseCounter::Count(GetDocument(), WebFeature::kDraggableAttribute);
-    if (EqualIgnoringASCIICase(value, "true")) {
+    if (EqualIgnoringASCIICase(value, keywords::kTrue)) {
       AddPropertyToPresentationAttributeStyle(
           style, CSSPropertyID::kWebkitUserDrag, CSSValueID::kElement);
       AddPropertyToPresentationAttributeStyle(style, CSSPropertyID::kUserSelect,
                                               CSSValueID::kNone);
-    } else if (EqualIgnoringASCIICase(value, "false")) {
+    } else if (EqualIgnoringASCIICase(value, keywords::kFalse)) {
       AddPropertyToPresentationAttributeStyle(
           style, CSSPropertyID::kWebkitUserDrag, CSSValueID::kNone);
     }
@@ -1151,7 +1151,7 @@
   switch (value->GetContentType()) {
     case V8UnionBooleanOrStringOrUnrestrictedDouble::ContentType::kBoolean:
       if (value->GetAsBoolean()) {
-        setAttribute(html_names::kHiddenAttr, "");
+        setAttribute(html_names::kHiddenAttr, g_empty_atom);
       } else {
         removeAttribute(html_names::kHiddenAttr);
       }
@@ -1160,18 +1160,18 @@
       if (RuntimeEnabledFeatures::BeforeMatchEventEnabled(
               GetExecutionContext()) &&
           EqualIgnoringASCIICase(value->GetAsString(), "until-found")) {
-        setAttribute(html_names::kHiddenAttr, "until-found");
+        setAttribute(html_names::kHiddenAttr, AtomicString("until-found"));
       } else if (value->GetAsString() == "") {
         removeAttribute(html_names::kHiddenAttr);
       } else {
-        setAttribute(html_names::kHiddenAttr, "");
+        setAttribute(html_names::kHiddenAttr, g_empty_atom);
       }
       break;
     case V8UnionBooleanOrStringOrUnrestrictedDouble::ContentType::
         kUnrestrictedDouble:
       double double_value = value->GetAsUnrestrictedDouble();
       if (double_value && !std::isnan(double_value)) {
-        setAttribute(html_names::kHiddenAttr, "");
+        setAttribute(html_names::kHiddenAttr, g_empty_atom);
       } else {
         removeAttribute(html_names::kHiddenAttr);
       }
@@ -2310,7 +2310,8 @@
 }
 
 void HTMLElement::setDraggable(bool value) {
-  setAttribute(html_names::kDraggableAttr, value ? "true" : "false");
+  setAttribute(html_names::kDraggableAttr,
+               value ? keywords::kTrue : keywords::kFalse);
 }
 
 bool HTMLElement::spellcheck() const {
@@ -2318,7 +2319,8 @@
 }
 
 void HTMLElement::setSpellcheck(bool enable) {
-  setAttribute(html_names::kSpellcheckAttr, enable ? "true" : "false");
+  setAttribute(html_names::kSpellcheckAttr,
+               enable ? keywords::kTrue : keywords::kFalse);
 }
 
 void HTMLElement::click() {
@@ -2365,7 +2367,7 @@
 }
 
 void HTMLElement::setTranslate(bool enable) {
-  setAttribute(html_names::kTranslateAttr, enable ? "yes" : "no");
+  setAttribute(html_names::kTranslateAttr, AtomicString(enable ? "yes" : "no"));
 }
 
 // Returns the conforming 'dir' value associated with the state the attribute is
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc
index ee35fa45..ddebf07 100644
--- a/third_party/blink/renderer/core/html/html_iframe_element.cc
+++ b/third_party/blink/renderer/core/html/html_iframe_element.cc
@@ -329,7 +329,8 @@
     // proper solution.
     // To avoid polluting the console, this is being recorded only once per
     // page.
-    if (name == "gesture" && value == "media" && GetDocument().Loader() &&
+    if (name == AtomicString("gesture") && value == AtomicString("media") &&
+        GetDocument().Loader() &&
         !GetDocument().Loader()->GetUseCounter().IsCounted(
             WebFeature::kHTMLIFrameElementGestureMedia)) {
       UseCounter::Count(GetDocument(),
diff --git a/third_party/blink/renderer/core/html/html_image_element.cc b/third_party/blink/renderer/core/html/html_image_element.cc
index e71d17e..74a2925 100644
--- a/third_party/blink/renderer/core/html/html_image_element.cc
+++ b/third_party/blink/renderer/core/html/html_image_element.cc
@@ -303,7 +303,8 @@
   const QualifiedName& name = params.name;
   if (name == html_names::kAltAttr || name == html_names::kTitleAttr) {
     if (UserAgentShadowRoot()) {
-      Element* text = UserAgentShadowRoot()->getElementById("alttext");
+      Element* text =
+          UserAgentShadowRoot()->getElementById(AtomicString("alttext"));
       String alt_text_content = AltText();
       if (text && text->textContent() != alt_text_content)
         text->setTextContent(alt_text_content);
diff --git a/third_party/blink/renderer/core/html/html_image_fallback_helper.cc b/third_party/blink/renderer/core/html/html_image_fallback_helper.cc
index 6be8a9e..8067533 100644
--- a/third_party/blink/renderer/core/html/html_image_fallback_helper.cc
+++ b/third_party/blink/renderer/core/html/html_image_fallback_helper.cc
@@ -54,8 +54,10 @@
 
  public:
   ImageFallbackContentBuilder(const ShadowRoot& shadow_root)
-      : place_holder_(shadow_root.getElementById("alttext-container")),
-        broken_image_(shadow_root.getElementById("alttext-image")) {}
+      : place_holder_(
+            shadow_root.getElementById(AtomicString("alttext-container"))),
+        broken_image_(
+            shadow_root.getElementById(AtomicString("alttext-image"))) {}
 
   bool HasContentElements() const { return place_holder_ && broken_image_; }
 
diff --git a/third_party/blink/renderer/core/html/html_view_source_document.cc b/third_party/blink/renderer/core/html/html_view_source_document.cc
index bc795ffe..1a3e72d 100644
--- a/third_party/blink/renderer/core/html/html_view_source_document.cc
+++ b/third_party/blink/renderer/core/html/html_view_source_document.cc
@@ -47,6 +47,7 @@
 #include "third_party/blink/renderer/core/html/html_table_row_element.h"
 #include "third_party/blink/renderer/core/html/html_table_section_element.h"
 #include "third_party/blink/renderer/core/html/parser/html_view_source_parser.h"
+#include "third_party/blink/renderer/core/input_type_names.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/text/platform_locale.h"
@@ -60,8 +61,9 @@
 
   void Invoke(ExecutionContext*, Event* event) override {
     DCHECK_EQ(event->type(), event_type_names::kChange);
-    table_->setAttribute(html_names::kClassAttr,
-                         checkbox_->Checked() ? "line-wrap" : "");
+    table_->setAttribute(html_names::kClassAttr, checkbox_->Checked()
+                                                     ? AtomicString("line-wrap")
+                                                     : g_empty_atom);
   }
 
   void Trace(Visitor* visitor) const override {
@@ -92,8 +94,8 @@
   auto* head = MakeGarbageCollected<HTMLHeadElement>(*this);
   auto* meta =
       MakeGarbageCollected<HTMLMetaElement>(*this, CreateElementFlags());
-  meta->setAttribute(html_names::kNameAttr, "color-scheme");
-  meta->setAttribute(html_names::kContentAttr, "light dark");
+  meta->setAttribute(html_names::kNameAttr, AtomicString("color-scheme"));
+  meta->setAttribute(html_names::kContentAttr, AtomicString("light dark"));
   head->ParserAppendChild(meta);
   html->ParserAppendChild(head);
   auto* body = MakeGarbageCollected<HTMLBodyElement>(*this);
@@ -102,7 +104,8 @@
   // Create a line gutter div that can be used to make sure the gutter extends
   // down the height of the whole document.
   auto* div = MakeGarbageCollected<HTMLDivElement>(*this);
-  div->setAttribute(html_names::kClassAttr, "line-gutter-backdrop");
+  div->setAttribute(html_names::kClassAttr,
+                    AtomicString("line-gutter-backdrop"));
   body->ParserAppendChild(div);
 
   auto* table = MakeGarbageCollected<HTMLTableElement>(*this);
@@ -115,7 +118,7 @@
   // Create a checkbox to control line wrapping.
   auto* checkbox =
       MakeGarbageCollected<HTMLInputElement>(*this, CreateElementFlags());
-  checkbox->setAttribute(html_names::kTypeAttr, "checkbox");
+  checkbox->setAttribute(html_names::kTypeAttr, input_type_names::kCheckbox);
   checkbox->addEventListener(
       event_type_names::kChange,
       MakeGarbageCollected<ViewSourceEventListener>(table, checkbox),
@@ -126,12 +129,13 @@
   label->ParserAppendChild(
       Text::Create(*this, WTF::AtomicString(Locale::DefaultLocale().QueryString(
                               IDS_VIEW_SOURCE_LINE_WRAP))));
-  label->setAttribute(html_names::kClassAttr, "line-wrap-control");
+  label->setAttribute(html_names::kClassAttr,
+                      AtomicString("line-wrap-control"));
   label->ParserAppendChild(checkbox);
   // Add the checkbox to a form with autocomplete=off, to avoid form
   // restoration from changing the value of the checkbox.
   auto* form = MakeGarbageCollected<HTMLFormElement>(*this);
-  form->setAttribute(html_names::kAutocompleteAttr, "off");
+  form->setAttribute(html_names::kAutocompleteAttr, AtomicString("off"));
   form->ParserAppendChild(label);
   body->ParserAppendChild(form);
   body->ParserAppendChild(table);
@@ -170,15 +174,15 @@
 
 void HTMLViewSourceDocument::ProcessDoctypeToken(const String& source,
                                                  HTMLToken&) {
-  current_ = AddSpanWithClassName("html-doctype");
-  AddText(source, "html-doctype");
+  current_ = AddSpanWithClassName(class_doctype_);
+  AddText(source, class_doctype_);
   current_ = td_;
 }
 
 void HTMLViewSourceDocument::ProcessEndOfFileToken(const String& source,
                                                    HTMLToken&) {
-  current_ = AddSpanWithClassName("html-end-of-file");
-  AddText(source, "html-end-of-file");
+  current_ = AddSpanWithClassName(class_end_of_file_);
+  AddText(source, class_end_of_file_);
   current_ = td_;
 }
 
@@ -187,7 +191,7 @@
     const HTMLToken& token,
     const HTMLAttributesRanges& attributes_ranges,
     int token_start) {
-  current_ = AddSpanWithClassName("html-tag");
+  current_ = AddSpanWithClassName(class_tag_);
 
   AtomicString tag_name = token.GetName().AsAtomicString();
 
@@ -214,7 +218,7 @@
                  g_empty_atom);
     index =
         AddRange(source, index, attribute_range.name_range.end - token_start,
-                 "html-attribute-name");
+                 class_attribute_name_);
 
     if (tag_name == html_names::kBaseTag && name == html_names::kHrefAttr)
       AddBase(value);
@@ -231,7 +235,7 @@
           name == html_names::kSrcAttr || name == html_names::kHrefAttr;
       index =
           AddRange(source, index, attribute_range.value_range.end - token_start,
-                   "html-attribute-value", is_link,
+                   class_attribute_value_, is_link,
                    tag_name == html_names::kATag, value);
     }
 
@@ -242,14 +246,14 @@
 
 void HTMLViewSourceDocument::ProcessCommentToken(const String& source,
                                                  HTMLToken&) {
-  current_ = AddSpanWithClassName("html-comment");
-  AddText(source, "html-comment");
+  current_ = AddSpanWithClassName(class_comment_);
+  AddText(source, class_comment_);
   current_ = td_;
 }
 
 void HTMLViewSourceDocument::ProcessCharacterToken(const String& source,
                                                    HTMLToken&) {
-  AddText(source, "");
+  AddText(source, g_empty_atom);
 }
 
 Element* HTMLViewSourceDocument::AddSpanWithClassName(
@@ -274,13 +278,13 @@
   // stylesheet using counters).
   auto* td =
       MakeGarbageCollected<HTMLTableCellElement>(html_names::kTdTag, *this);
-  td->setAttribute(html_names::kClassAttr, "line-number");
+  td->setAttribute(html_names::kClassAttr, AtomicString("line-number"));
   td->SetIntegralAttribute(html_names::kValueAttr, ++line_number_);
   trow->ParserAppendChild(td);
 
   // Create a second cell for the line contents
   td = MakeGarbageCollected<HTMLTableCellElement>(html_names::kTdTag, *this);
-  td->setAttribute(html_names::kClassAttr, "line-content");
+  td->setAttribute(html_names::kClassAttr, AtomicString("line-content"));
   trow->ParserAppendChild(td);
   current_ = td_ = td;
 
@@ -288,7 +292,7 @@
   if (!class_name.empty()) {
     if (class_name == "html-attribute-name" ||
         class_name == "html-attribute-value")
-      current_ = AddSpanWithClassName("html-tag");
+      current_ = AddSpanWithClassName(class_tag_);
     current_ = AddSpanWithClassName(class_name);
   }
 }
@@ -362,7 +366,7 @@
 Element* HTMLViewSourceDocument::AddLink(const AtomicString& url,
                                          bool is_anchor) {
   if (current_ == tbody_)
-    AddLine("html-tag");
+    AddLine(class_tag_);
 
   // Now create a link for the attribute value instead of a span.
   auto* anchor = MakeGarbageCollected<HTMLAnchorElement>(*this);
@@ -371,13 +375,14 @@
     class_value = "html-attribute-value html-external-link";
   else
     class_value = "html-attribute-value html-resource-link";
-  anchor->setAttribute(html_names::kClassAttr, class_value);
-  anchor->setAttribute(html_names::kTargetAttr, "_blank");
+  anchor->setAttribute(html_names::kClassAttr, AtomicString(class_value));
+  anchor->setAttribute(html_names::kTargetAttr, AtomicString("_blank"));
   anchor->setAttribute(html_names::kHrefAttr, url);
-  anchor->setAttribute(html_names::kRelAttr, "noreferrer noopener");
+  anchor->setAttribute(html_names::kRelAttr,
+                       AtomicString("noreferrer noopener"));
   // Disallow JavaScript hrefs. https://crbug.com/808407
   if (anchor->Url().ProtocolIsJavaScript())
-    anchor->setAttribute(html_names::kHrefAttr, "about:blank");
+    anchor->setAttribute(html_names::kHrefAttr, AtomicString("about:blank"));
   current_->ParserAppendChild(anchor);
   return anchor;
 }
@@ -395,13 +400,13 @@
     if (tmp.size() > 0) {
       AtomicString link(tmp[0]);
       current_ = AddLink(link, false);
-      AddText(srclist[i], "html-attribute-value");
+      AddText(srclist[i], class_attribute_value_);
       current_ = To<Element>(current_->parentNode());
     } else {
-      AddText(srclist[i], "html-attribute-value");
+      AddText(srclist[i], class_attribute_value_);
     }
     if (i + 1 < size)
-      AddText(",", "html-attribute-value");
+      AddText(",", class_attribute_value_);
   }
   return end;
 }
diff --git a/third_party/blink/renderer/core/html/html_view_source_document.h b/third_party/blink/renderer/core/html/html_view_source_document.h
index cb814f2e..1fff430 100644
--- a/third_party/blink/renderer/core/html/html_view_source_document.h
+++ b/third_party/blink/renderer/core/html/html_view_source_document.h
@@ -81,6 +81,13 @@
   Member<HTMLTableSectionElement> tbody_;
   Member<HTMLTableCellElement> td_;
   int line_number_;
+
+  const AtomicString class_doctype_{"html-doctype"};
+  const AtomicString class_end_of_file_{"html-end-of-file"};
+  const AtomicString class_tag_{"html-tag"};
+  const AtomicString class_attribute_name_{"html-attribute-name"};
+  const AtomicString class_attribute_value_{"html-attribute-value"};
+  const AtomicString class_comment_{"html-comment"};
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/image_document.cc b/third_party/blink/renderer/core/html/image_document.cc
index 1475324..f74672d6 100644
--- a/third_party/blink/renderer/core/html/image_document.cc
+++ b/third_party/blink/renderer/core/html/image_document.cc
@@ -27,6 +27,7 @@
 #include <limits>
 
 #include "third_party/blink/public/platform/web_content_settings_client.h"
+#include "third_party/blink/renderer/core/css/css_color.h"
 #include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
 #include "third_party/blink/renderer/core/dom/raw_data_document_parser.h"
 #include "third_party/blink/renderer/core/dom/shadow_root.h"
@@ -237,28 +238,39 @@
   auto* head = MakeGarbageCollected<HTMLHeadElement>(*this);
   auto* meta =
       MakeGarbageCollected<HTMLMetaElement>(*this, CreateElementFlags());
-  meta->setAttribute(html_names::kNameAttr, "viewport");
+  meta->setAttribute(html_names::kNameAttr, AtomicString("viewport"));
   meta->setAttribute(html_names::kContentAttr,
-                     "width=device-width, minimum-scale=0.1");
+                     AtomicString("width=device-width, minimum-scale=0.1"));
   head->AppendChild(meta);
 
   auto* body = MakeGarbageCollected<HTMLBodyElement>(*this);
 
+  body->SetInlineStyleProperty(CSSPropertyID::kMargin, 0.0,
+                               CSSPrimitiveValue::UnitType::kPixels);
+  body->SetInlineStyleProperty(CSSPropertyID::kHeight, 100.0,
+                               CSSPrimitiveValue::UnitType::kPercentage);
   if (ShouldShrinkToFit()) {
     // Display the image prominently centered in the frame.
-    body->setAttribute(html_names::kStyleAttr,
-                       "margin: 0px; background: #0e0e0e; height: 100%");
+    body->SetInlineStyleProperty(
+        CSSPropertyID::kBackgroundColor,
+        *cssvalue::CSSColor::Create(Color::FromRGB(14, 14, 14)));
 
     // See w3c example on how to center an element:
     // https://www.w3.org/Style/Examples/007/center.en.html
     div_element_ = MakeGarbageCollected<HTMLDivElement>(*this);
-    div_element_->setAttribute(html_names::kStyleAttr,
-                               "display: flex;"
-                               "flex-direction: column;"
-                               "align-items: flex-start;"
-                               "min-width: min-content;"
-                               "height: 100%;"
-                               "width: 100%;");
+    div_element_->SetInlineStyleProperty(CSSPropertyID::kDisplay,
+                                         CSSValueID::kFlex);
+    div_element_->SetInlineStyleProperty(CSSPropertyID::kFlexDirection,
+                                         CSSValueID::kColumn);
+    div_element_->SetInlineStyleProperty(CSSPropertyID::kAlignItems,
+                                         CSSValueID::kFlexStart);
+    div_element_->SetInlineStyleProperty(CSSPropertyID::kMinWidth,
+                                         CSSValueID::kMinContent);
+    div_element_->SetInlineStyleProperty(
+        CSSPropertyID::kHeight, 100.0,
+        CSSPrimitiveValue::UnitType::kPercentage);
+    div_element_->SetInlineStyleProperty(
+        CSSPropertyID::kWidth, 100.0, CSSPrimitiveValue::UnitType::kPercentage);
     HTMLSlotElement* slot = MakeGarbageCollected<HTMLSlotElement>(*this);
     div_element_->AppendChild(slot);
 
@@ -268,8 +280,6 @@
     // https://html.spec.whatwg.org/C/#read-media
     ShadowRoot& shadow_root = body->EnsureUserAgentShadowRoot();
     shadow_root.AppendChild(div_element_);
-  } else {
-    body->setAttribute(html_names::kStyleAttr, "margin: 0px; height: 100%");
   }
 
   WillInsertBody();
diff --git a/third_party/blink/renderer/core/html/media/html_media_element_controls_list.cc b/third_party/blink/renderer/core/html/media/html_media_element_controls_list.cc
index 1d6d3e7..c8582583 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element_controls_list.cc
+++ b/third_party/blink/renderer/core/html/media/html_media_element_controls_list.cc
@@ -28,6 +28,7 @@
     const AtomicString& token_value,
     ExceptionState&) const {
   for (const char* supported_token : kSupportedTokens) {
+    // TODO(crbug.com/1444094): Avoid AtomicString-char[] comparisons.
     if (token_value == supported_token)
       return true;
   }
@@ -35,19 +36,19 @@
 }
 
 bool HTMLMediaElementControlsList::ShouldHideDownload() const {
-  return contains(kNoDownload);
+  return contains(AtomicString(kNoDownload));
 }
 
 bool HTMLMediaElementControlsList::ShouldHideFullscreen() const {
-  return contains(kNoFullscreen);
+  return contains(AtomicString(kNoFullscreen));
 }
 
 bool HTMLMediaElementControlsList::ShouldHidePlaybackRate() const {
-  return contains(kNoPlaybackRate);
+  return contains(AtomicString(kNoPlaybackRate));
 }
 
 bool HTMLMediaElementControlsList::ShouldHideRemotePlayback() const {
-  return contains(kNoRemotePlayback);
+  return contains(AtomicString(kNoRemotePlayback));
 }
 
 bool HTMLMediaElementControlsList::CanShowAllControls() const {
diff --git a/third_party/blink/renderer/core/html/media/media_controls.cc b/third_party/blink/renderer/core/html/media/media_controls.cc
index fe0b9df..2061964 100644
--- a/third_party/blink/renderer/core/html/media/media_controls.cc
+++ b/third_party/blink/renderer/core/html/media/media_controls.cc
@@ -31,11 +31,11 @@
     MediaControlsSizingClass sizing_class) {
   switch (sizing_class) {
     case MediaControlsSizingClass::kSmall:
-      return kMediaControlsSizingSmallCSSClass;
+      return AtomicString(kMediaControlsSizingSmallCSSClass);
     case MediaControlsSizingClass::kMedium:
-      return kMediaControlsSizingMediumCSSClass;
+      return AtomicString(kMediaControlsSizingMediumCSSClass);
     case MediaControlsSizingClass::kLarge:
-      return kMediaControlsSizingLargeCSSClass;
+      return AtomicString(kMediaControlsSizingLargeCSSClass);
   }
 
   NOTREACHED();
diff --git a/third_party/blink/renderer/core/html/media/media_document.cc b/third_party/blink/renderer/core/html/media/media_document.cc
index cd5c64b..dee5f6d5 100644
--- a/third_party/blink/renderer/core/html/media/media_document.cc
+++ b/third_party/blink/renderer/core/html/media/media_document.cc
@@ -84,14 +84,15 @@
   auto* head = MakeGarbageCollected<HTMLHeadElement>(*GetDocument());
   auto* meta = MakeGarbageCollected<HTMLMetaElement>(*GetDocument(),
                                                      CreateElementFlags());
-  meta->setAttribute(html_names::kNameAttr, "viewport");
-  meta->setAttribute(html_names::kContentAttr, "width=device-width");
+  meta->setAttribute(html_names::kNameAttr, AtomicString("viewport"));
+  meta->setAttribute(html_names::kContentAttr,
+                     AtomicString("width=device-width"));
   head->AppendChild(meta);
 
   auto* media = MakeGarbageCollected<HTMLVideoElement>(*GetDocument());
-  media->setAttribute(html_names::kControlsAttr, "");
-  media->setAttribute(html_names::kAutoplayAttr, "");
-  media->setAttribute(html_names::kNameAttr, "media");
+  media->setAttribute(html_names::kControlsAttr, g_empty_atom);
+  media->setAttribute(html_names::kAutoplayAttr, g_empty_atom);
+  media->setAttribute(html_names::kNameAttr, AtomicString("media"));
 
   auto* source = MakeGarbageCollected<HTMLSourceElement>(*GetDocument());
   source->setAttribute(html_names::kSrcAttr,
diff --git a/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.cc b/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.cc
index 72bebf3..61c4410 100644
--- a/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.cc
+++ b/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.cc
@@ -145,8 +145,9 @@
 void PictureInPictureInterstitial::NotifyElementSizeChanged(
     const DOMRectReadOnly& new_size) {
   message_element_->setAttribute(
-      "class", MediaControls::GetSizingCSSClass(
-                   MediaControls::GetSizingClass(new_size.width())));
+      html_names::kClassAttr,
+      MediaControls::GetSizingCSSClass(
+          MediaControls::GetSizingClass(new_size.width())));
 
   // Force a layout since |LayoutMedia::UpdateLayout()| will sometimes miss a
   // layout otherwise.
diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser.cc b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
index 7166d5ac..d4c06269 100644
--- a/third_party/blink/renderer/core/html/parser/html_document_parser.cc
+++ b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
@@ -1263,9 +1263,9 @@
   DCHECK(document);
   DCHECK(document->documentElement());
   Element* documentElement = GetDocument()->documentElement();
-  if (documentElement->hasAttribute(u"\u26A1") ||
-      documentElement->hasAttribute("amp") ||
-      documentElement->hasAttribute("i-amphtml-layout")) {
+  if (documentElement->hasAttribute(AtomicString(u"\u26A1")) ||
+      documentElement->hasAttribute(AtomicString("amp")) ||
+      documentElement->hasAttribute(AtomicString("i-amphtml-layout"))) {
     // The DocumentLoader fetches a main resource and handles the result.
     // But it may not be available if JavaScript appends HTML to the page later
     // in the page's lifetime. This can happen both from in-page JavaScript and
diff --git a/third_party/blink/renderer/core/html/parser/html_tree_builder.cc b/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
index 7266d14..c623902 100644
--- a/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
+++ b/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
@@ -521,7 +521,7 @@
 }
 
 void AddManualLocalName(PrefixedNameToQualifiedNameMap* map, const char* name) {
-  const QualifiedName item(g_null_atom, name, g_null_atom);
+  const QualifiedName item(g_null_atom, AtomicString(name), g_null_atom);
   const blink::QualifiedName* const names = &item;
   MapLoweredLocalNameToName<QualifiedName>(map, &names, 1);
 }
@@ -613,8 +613,9 @@
                        xml_names::kAttrsCount);
 
     map->insert(WTF::g_xmlns_atom, xmlns_names::kXmlnsAttr);
-    map->insert("xmlns:xlink", QualifiedName(g_xmlns_atom, g_xlink_atom,
-                                             xmlns_names::kNamespaceURI));
+    map->insert(
+        AtomicString("xmlns:xlink"),
+        QualifiedName(g_xmlns_atom, g_xlink_atom, xmlns_names::kNamespaceURI));
   }
 
   for (unsigned i = 0; i < token->Attributes().size(); ++i) {
diff --git a/third_party/blink/renderer/core/html/parser/text_document_parser.cc b/third_party/blink/renderer/core/html/parser/text_document_parser.cc
index eb0bc33..52d557c6 100644
--- a/third_party/blink/renderer/core/html/parser/text_document_parser.cc
+++ b/third_party/blink/renderer/core/html/parser/text_document_parser.cc
@@ -56,16 +56,19 @@
 
   // Allow the browser to display the text file in dark mode if it is set as
   // the preferred color scheme.
-  attributes.push_back(Attribute(html_names::kNameAttr, "color-scheme"));
-  attributes.push_back(Attribute(html_names::kContentAttr, "light dark"));
+  attributes.push_back(
+      Attribute(html_names::kNameAttr, AtomicString("color-scheme")));
+  attributes.push_back(
+      Attribute(html_names::kContentAttr, AtomicString("light dark")));
   AtomicHTMLToken fake_meta(HTMLToken::kStartTag, html_names::HTMLTag::kMeta,
                             attributes);
   TreeBuilder()->ConstructTree(&fake_meta);
   attributes.clear();
 
   // Wrap the actual contents of the text file in <pre>.
-  attributes.push_back(Attribute(
-      html_names::kStyleAttr, "word-wrap: break-word; white-space: pre-wrap;"));
+  attributes.push_back(
+      Attribute(html_names::kStyleAttr,
+                AtomicString("word-wrap: break-word; white-space: pre-wrap;")));
   AtomicHTMLToken fake_pre(HTMLToken::kStartTag, html_names::HTMLTag::kPre,
                            attributes);
   TreeBuilder()->ConstructTree(&fake_pre);
diff --git a/third_party/blink/renderer/core/html/plugin_document.cc b/third_party/blink/renderer/core/html/plugin_document.cc
index fe3a1c4..89f9e639 100644
--- a/third_party/blink/renderer/core/html/plugin_document.cc
+++ b/third_party/blink/renderer/core/html/plugin_document.cc
@@ -106,8 +106,13 @@
     return;  // runScriptsAtDocumentElementAvailable can detach the frame.
 
   auto* body = MakeGarbageCollected<HTMLBodyElement>(*GetDocument());
-  body->setAttribute(html_names::kStyleAttr,
-                     "height: 100%; width: 100%; overflow: hidden; margin: 0");
+  body->SetInlineStyleProperty(CSSPropertyID::kHeight, 100.0,
+                               CSSPrimitiveValue::UnitType::kPercentage);
+  body->SetInlineStyleProperty(CSSPropertyID::kWidth, 100.0,
+                               CSSPrimitiveValue::UnitType::kPercentage);
+  body->SetInlineStyleProperty(CSSPropertyID::kOverflow, CSSValueID::kHidden);
+  body->SetInlineStyleProperty(CSSPropertyID::kMargin, 0.0,
+                               CSSPrimitiveValue::UnitType::kPixels);
   body->SetInlineStyleProperty(CSSPropertyID::kBackgroundColor,
                                *cssvalue::CSSColor::Create(background_color_));
   root_element->AppendChild(body);
@@ -117,11 +122,13 @@
     return;
   }
 
+  AtomicString hundred_percent("100%");
+  AtomicString plugin("plugin");
   embed_element_ = MakeGarbageCollected<HTMLEmbedElement>(*GetDocument());
-  embed_element_->setAttribute(html_names::kWidthAttr, "100%");
-  embed_element_->setAttribute(html_names::kHeightAttr, "100%");
-  embed_element_->setAttribute(html_names::kNameAttr, "plugin");
-  embed_element_->setAttribute(html_names::kIdAttr, "plugin");
+  embed_element_->setAttribute(html_names::kWidthAttr, hundred_percent);
+  embed_element_->setAttribute(html_names::kHeightAttr, hundred_percent);
+  embed_element_->setAttribute(html_names::kNameAttr, plugin);
+  embed_element_->setAttribute(html_names::kIdAttr, plugin);
   embed_element_->setAttribute(html_names::kSrcAttr,
                                AtomicString(GetDocument()->Url().GetString()));
   embed_element_->setAttribute(html_names::kTypeAttr,
diff --git a/third_party/blink/renderer/core/html/rel_list.cc b/third_party/blink/renderer/core/html/rel_list.cc
index d0a101d..96625f5 100644
--- a/third_party/blink/renderer/core/html/rel_list.cc
+++ b/third_party/blink/renderer/core/html/rel_list.cc
@@ -24,21 +24,21 @@
   // clang-format off
   DEFINE_STATIC_LOCAL(HashSet<AtomicString>, tokens,
                       ({
-                          "preload",
-                          "preconnect",
-                          "dns-prefetch",
-                          "stylesheet",
-                          "icon",
-                          "alternate",
-                          "prefetch",
-                          "prerender",
-                          "next",
-                          "manifest",
-                          "apple-touch-icon",
-                          "apple-touch-icon-precomposed",
-                          "canonical",
-                          "modulepreload",
-                          "allowed-alt-sxg",
+                          AtomicString("preload"),
+                          AtomicString("preconnect"),
+                          AtomicString("dns-prefetch"),
+                          AtomicString("stylesheet"),
+                          AtomicString("icon"),
+                          AtomicString("alternate"),
+                          AtomicString("prefetch"),
+                          AtomicString("prerender"),
+                          AtomicString("next"),
+                          AtomicString("manifest"),
+                          AtomicString("apple-touch-icon"),
+                          AtomicString("apple-touch-icon-precomposed"),
+                          AtomicString("canonical"),
+                          AtomicString("modulepreload"),
+                          AtomicString("allowed-alt-sxg"),
                       }));
   // clang-format on
 
@@ -48,9 +48,9 @@
 static HashSet<AtomicString>& SupportedTokensAnchorAndAreaAndForm() {
   DEFINE_STATIC_LOCAL(HashSet<AtomicString>, tokens,
                       ({
-                          "noreferrer",
-                          "noopener",
-                          "opener",
+                          AtomicString("noreferrer"),
+                          AtomicString("noopener"),
+                          AtomicString("opener"),
                       }));
 
   return tokens;
diff --git a/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc b/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc
index 47d3a9c..f1abce3 100644
--- a/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc
+++ b/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc
@@ -34,16 +34,30 @@
 namespace blink {
 
 static const QualifiedName& NodeTypeToTagName(VTTNodeType node_type) {
-  DEFINE_STATIC_LOCAL(QualifiedName, c_tag, (g_null_atom, "c", g_null_atom));
-  DEFINE_STATIC_LOCAL(QualifiedName, v_tag, (g_null_atom, "v", g_null_atom));
-  DEFINE_STATIC_LOCAL(QualifiedName, lang_tag,
-                      (g_null_atom, "lang", g_null_atom));
-  DEFINE_STATIC_LOCAL(QualifiedName, b_tag, (g_null_atom, "b", g_null_atom));
-  DEFINE_STATIC_LOCAL(QualifiedName, u_tag, (g_null_atom, "u", g_null_atom));
-  DEFINE_STATIC_LOCAL(QualifiedName, i_tag, (g_null_atom, "i", g_null_atom));
-  DEFINE_STATIC_LOCAL(QualifiedName, ruby_tag,
-                      (g_null_atom, "ruby", g_null_atom));
-  DEFINE_STATIC_LOCAL(QualifiedName, rt_tag, (g_null_atom, "rt", g_null_atom));
+  // Use predefined AtomicStrings in html_names to reduce AtomicString
+  // creation cost.
+  DEFINE_STATIC_LOCAL(QualifiedName, c_tag,
+                      (g_null_atom, AtomicString("c"), g_null_atom));
+  DEFINE_STATIC_LOCAL(QualifiedName, v_tag,
+                      (g_null_atom, AtomicString("v"), g_null_atom));
+  DEFINE_STATIC_LOCAL(
+      QualifiedName, lang_tag,
+      (g_null_atom, html_names::kLangAttr.LocalName(), g_null_atom));
+  DEFINE_STATIC_LOCAL(
+      QualifiedName, b_tag,
+      (g_null_atom, html_names::kBTag.LocalName(), g_null_atom));
+  DEFINE_STATIC_LOCAL(
+      QualifiedName, u_tag,
+      (g_null_atom, html_names::kUTag.LocalName(), g_null_atom));
+  DEFINE_STATIC_LOCAL(
+      QualifiedName, i_tag,
+      (g_null_atom, html_names::kITag.LocalName(), g_null_atom));
+  DEFINE_STATIC_LOCAL(
+      QualifiedName, ruby_tag,
+      (g_null_atom, html_names::kRubyTag.LocalName(), g_null_atom));
+  DEFINE_STATIC_LOCAL(
+      QualifiedName, rt_tag,
+      (g_null_atom, html_names::kRtTag.LocalName(), g_null_atom));
   switch (node_type) {
     case kVTTNodeTypeClass:
       return c_tag;
diff --git a/third_party/blink/renderer/core/html/track/vtt/vtt_element.h b/third_party/blink/renderer/core/html/track/vtt/vtt_element.h
index 37d4126..65247819 100644
--- a/third_party/blink/renderer/core/html/track/vtt/vtt_element.h
+++ b/third_party/blink/renderer/core/html/track/vtt/vtt_element.h
@@ -69,14 +69,14 @@
 
   static const QualifiedName& VoiceAttributeName() {
     DEFINE_STATIC_LOCAL(QualifiedName, voice_attr,
-                        (g_null_atom, "voice", g_null_atom));
+                        (g_null_atom, AtomicString("voice"), g_null_atom));
     return voice_attr;
   }
 
   static const QualifiedName& LangAttributeName() {
-    DEFINE_STATIC_LOCAL(QualifiedName, voice_attr,
-                        (g_null_atom, "lang", g_null_atom));
-    return voice_attr;
+    DEFINE_STATIC_LOCAL(QualifiedName, attr,
+                        (g_null_atom, AtomicString("lang"), g_null_atom));
+    return attr;
   }
 
   const TextTrack* GetTrack() const { return track_; }
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests
index 91936a01..c445669 100644
--- a/third_party/blink/web_tests/SlowTests
+++ b/third_party/blink/web_tests/SlowTests
@@ -432,7 +432,6 @@
 crbug.com/866850 [ Linux ] virtual/gpu/fast/canvas/canvas-blending-gradient-over-image.html [ Slow ]
 crbug.com/866850 [ Debug Mac12 ] virtual/gpu/fast/canvas/canvas-blending-gradient-over-image.html [ Slow ]
 crbug.com/866850 [ Debug Mac13 ] virtual/gpu/fast/canvas/canvas-blending-gradient-over-image.html [ Slow ]
-crbug.com/866850 [ Mac10.15 Release ] virtual/gpu/fast/canvas/canvas-blending-gradient-over-image.html [ Slow ]
 crbug.com/866850 [ Linux ] virtual/gpu/fast/canvas/canvas-blending-image-over-gradient.html [ Slow ]
 crbug.com/866850 [ Mac12 Release ] virtual/gpu/fast/canvas/canvas-blending-image-over-gradient.html [ Slow ]
 crbug.com/866850 [ Linux ] virtual/gpu/fast/canvas/canvas-blending-image-over-image.html [ Slow ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 297dedc..cc5b1921 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -875,8 +875,6 @@
 # Passes with the WPT runner but not the internal one. (???)
 crbug.com/1175040 external/wpt/css/css-backgrounds/background-repeat-space-4.html [ Failure Pass ]
 
-# Off-by-one in some components.
-crbug.com/1175040 [ Mac10.15 Release ] external/wpt/css/css-backgrounds/background-repeat-space-7.html [ Failure Pass ]
 
 # Failures due to pointerMove building synthetic events without button information (main thread only).
 crbug.com/1056778 fast/scrolling/scrollbars/scrollbar-thumb-snapping.html [ Failure ]
@@ -1156,7 +1154,6 @@
 crbug.com/722287 crbug.com/886585 external/wpt/css/css-flexbox/abspos/flex-abspos-staticpos-align-self-safe-001.html [ Failure ]
 crbug.com/1121601 external/wpt/css/css-align/self-alignment/self-align-safe-unsafe-flex-002.html [ Failure ]
 crbug.com/1121601 external/wpt/css/css-align/self-alignment/self-align-safe-unsafe-flex-001.html [ Failure ]
-crbug.com/1121601 external/wpt/css/css-align/self-alignment/self-align-safe-unsafe-flex-003.html [ Failure ]
 
 # [css-ui]
 # The `input-security` property not implemented yet.
@@ -6602,8 +6599,6 @@
 # Re-enable test after adding support for component ads in frame contexts
 crbug.com/1427455 virtual/fenced-frame-mparch/external/wpt/fenced-frame/nested-opaque-ad-sizes.https.html [ Failure Pass Timeout ]
 
-# Sheriff 2023-03-27
-crbug.com/1427936 external/wpt/js-self-profiling/function-expression-names.https.html [ Crash Failure Pass ]
 
 
 # TODO(crbug.com/1428795): Re-enable this test
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 998b246..43b4a22 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
@@ -272890,11 +272890,11 @@
   "support": {
    ".cache": {
     "gitignore2.json": [
-     "ab5b31046cd5a92258550d65f296280e2cc71c4d",
+     "2c7019a1937f4c361646d0fba0e58db04295b8eb",
      []
     ],
     "mtime.json": [
-     "d760b5880ecca34a1ead9a42a30d4268e8600064",
+     "3e8a650b88e50532983cea00308679d9ce067578",
      []
     ]
    },
@@ -275682,12 +275682,12 @@
       "71064a90c5b04ce6fa7f154da440c2dcc62a3602",
       []
      ],
-     "intercept-request.js": [
-      "c19efb5f2f3fe5469b63b5772c875d9e62fb47b5",
+     "header-util.sub.js": [
+      "c38e5aa59d8b2a995f907aeb91ef7e971104b7d9",
       []
      ],
-     "navigation-header-util.sub.js": [
-      "b3bec79651d0cfca140176a5527327d86d780ad5",
+     "intercept-request.js": [
+      "c19efb5f2f3fe5469b63b5772c875d9e62fb47b5",
       []
      ],
      "permissions-policy-util.sub.js": [
@@ -307264,6 +307264,10 @@
         "610b2ad0a11ff010e30fc9c8d8a532c5e8c7c973",
         []
        ],
+       "grid-self-baseline-006.html.ini": [
+        "1a56e1d10e38875f885dbdb955fddd490292141b",
+        []
+       ],
        "grid-self-baseline-007-ref.html": [
         "59a0e339598b4c6e0f9b604636c9199826c45f2d",
         []
@@ -312130,7 +312134,7 @@
        []
       ],
       "clip-path-svg-invalidate.html.ini": [
-       "3b8b2259c6085f785bf1d9ebc95d8568830df26c",
+       "326830b521c7479f12a44a37d3733133f3f54ab1",
        []
       ],
       "clip-path-svg-text-backdrop-filter-ref.html": [
@@ -327487,7 +327491,7 @@
       []
      ],
      "preserve3d-and-flattening-z-order-003.html.ini": [
-      "a7f8e81851d827783b2e26e6484b419a5e998e91",
+      "0dcf0a35e1ac307ae8911c6855132e3c35bee95c",
       []
      ],
      "preserve3d-and-flattening-z-order-004.html.ini": [
@@ -381034,7 +381038,7 @@
      []
     ],
     "modulepreload-as.html.ini": [
-     "8e5c861c04a8a452d6ceb1719139b3c3920d26ac",
+     "5f0071d9b73f13b10f5c26893cb0d8fd6bbd17e0",
      []
     ],
     "modulepreload-expected.txt": [
@@ -384407,7 +384411,7 @@
       []
      ],
      "animation-range-visual-test.html.ini": [
-      "441e720c8d178f0c3183a33664d374a379501475",
+      "dbb5570ba3cc4419ee54e8e9b79a0b53c1a951c3",
       []
      ],
      "animation-shorthand-expected.txt": [
@@ -393315,7 +393319,7 @@
       []
      ],
      "percent-encoding.json": [
-      "bd81edbdc35ee3201d781278e64d5ea2db6b160b",
+      "eccd1db62fe60131fb12cbdf8c16e0354bcf7a98",
       []
      ],
      "percent-encoding.py": [
@@ -393331,7 +393335,7 @@
       []
      ],
      "urltestdata.json": [
-      "1aa42a514555dfa6c1007a2fa0b309fc3cc8b0ac",
+      "ce2c8c061f7ce7bdb602d6a4051362742166d39d",
       []
      ]
     },
@@ -399311,6 +399315,10 @@
      "reject_opaque_origin.https.html.headers": [
       "1efcf8c226fac074c98d0a5a747856f532e5d84e",
       []
+     ],
+     "sandboxed_iframe.https.window.js.ini": [
+      "1bfdbbd8441ef221b91074fec62f898ad38b9137",
+      []
      ]
     },
     "idlharness.https.any-expected.txt": [
@@ -426580,21 +426588,21 @@
    },
    "browsing-topics": {
     "browsing-topics-permissions-policy-default.tentative.https.sub.html": [
-     "884ad9276a1d087684d06ed1b03bbdc57d3f7d8c",
+     "8467ab656919e95c8d3b31e352c28a6aa5117740",
      [
       null,
       {}
      ]
     ],
     "browsing-topics-permissions-policy-none.tentative.https.sub.html": [
-     "2f80daa27142c6a2ccd7b0e33005a4659180bf1b",
+     "23bac4381f0956824775403b8cfe1717e42c4123",
      [
       null,
       {}
      ]
     ],
     "browsing-topics-permissions-policy-self.tentative.https.sub.html": [
-     "601266794797ebf8b7a7bdacfd3b3c5cb1c92f2c",
+     "91ee4f05f3a64b5f990f66481d77f0087c4e2a32",
      [
       null,
       {}
@@ -426629,7 +426637,7 @@
      ]
     ],
     "fetch-topics.tentative.https.html": [
-     "e5dd1d9b98688637ce96230a10aaa9a66212eaf6",
+     "c33d4dd11d8788ec3dd584e6b8c83befbd8ce011",
      [
       null,
       {}
@@ -426643,14 +426651,14 @@
      ]
     ],
     "iframe-topics-attribute-insecure-context.tentative.http.sub.html": [
-     "19c79e0d7f001b592a93214ee89dcdf15afbe5dc",
+     "8e25b769cecedbda90d1b250ec62901bf9639711",
      [
       null,
       {}
      ]
     ],
     "iframe-topics-attribute.tentative.https.html": [
-     "b90f967146ce49235d216ef7a18056b1b282d263",
+     "7b3b6c70450dfb83cb07b6c36443de63d474da2b",
      [
       null,
       {}
@@ -426671,7 +426679,7 @@
      ]
     ],
     "xhr-topics.tentative.https.html": [
-     "532a0404240593173a79b0d1009bacc1d85ff02d",
+     "fcca74a1ce5888bb2930c4001733588cef6c4f30",
      [
       null,
       {}
@@ -458797,6 +458805,13 @@
        {}
       ]
      ],
+     "scrollbar-width-009.html": [
+      "494ffe344693ad80568d4513643e28eae13aad5e",
+      [
+       null,
+       {}
+      ]
+     ],
      "scrollbar-width-keywords.html": [
       "94ccd6ef6d550c83c97ba9525135cc309cc35842",
       [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/self-baseline/grid-self-baseline-006.html.ini b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/self-baseline/grid-self-baseline-006.html.ini
new file mode 100644
index 0000000..1a56e1d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/self-baseline/grid-self-baseline-006.html.ini
@@ -0,0 +1,3 @@
+[grid-self-baseline-006.html]
+  expected:
+    if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-svg-invalidate.html.ini b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-svg-invalidate.html.ini
index 3b8b225..326830b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-svg-invalidate.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-svg-invalidate.html.ini
@@ -1,6 +1,7 @@
 [clip-path-svg-invalidate.html]
   expected:
-    if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
     if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
-    if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
+    if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
     if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
+    if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
+    if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scrollbars/scrollbar-width-009.html b/third_party/blink/web_tests/external/wpt/css/css-scrollbars/scrollbar-width-009.html
new file mode 100644
index 0000000..494ffe34
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-scrollbars/scrollbar-width-009.html
@@ -0,0 +1,60 @@
+<meta charset="utf-8">
+<title>CSS Scrollbars: scrollbar-width on the body is not propagated quirks mode</title>
+<link rel="author" title="Luke Warlow" href="mailto:luke@warlow.dev" />
+<link rel="help" href="https://drafts.csswg.org/css-scrollbars-1/" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+  :root {
+    /* CSS scrollbar properties applied to the root element
+       will be propagated to the viewport. */
+    scrollbar-width: thin;
+    overflow: visible;
+  }
+
+  body {
+    /* overflow is propagated as well */
+    overflow: scroll;
+    /* but CSS scrollbar properties applied to the body are not propagated */
+    scrollbar-width: none;
+  }
+
+  :root,
+  body {
+    margin: 0;
+    padding: 0;
+  }
+
+  #content {
+    height: 10vh;
+    width: 100%;
+    background: lightsalmon;
+  }
+
+  #expander {
+    /* force vertical scroll */
+    height: 200vh;
+    width: 300px;
+    background: gray;
+  }
+</style>
+
+<body>
+
+  <div id="content"></div>
+
+  <div id="expander"></div>
+
+  <script>
+    test(function () {
+      let root = document.documentElement;
+      let body = document.body;
+      let content = document.getElementById('content');
+
+      assert_less_than(root.offsetWidth, window.innerWidth, "viewport has a scrollbar");
+      assert_equals(body.offsetWidth, root.offsetWidth, "body matches root");
+      assert_equals(content.offsetWidth, body.offsetWidth, "content matches body");
+    }, "viewport displays a scrollbar");
+  </script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/preserve3d-and-flattening-z-order-003.html.ini b/third_party/blink/web_tests/external/wpt/css/css-transforms/preserve3d-and-flattening-z-order-003.html.ini
index a7f8e818..0dcf0a35 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/preserve3d-and-flattening-z-order-003.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/preserve3d-and-flattening-z-order-003.html.ini
@@ -1,4 +1,5 @@
 [preserve3d-and-flattening-z-order-003.html]
   expected:
-    if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
+    if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
     if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+    if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/preload/modulepreload-as.html.ini b/third_party/blink/web_tests/external/wpt/preload/modulepreload-as.html.ini
index 8e5c861c..5f0071d9 100644
--- a/third_party/blink/web_tests/external/wpt/preload/modulepreload-as.html.ini
+++ b/third_party/blink/web_tests/external/wpt/preload/modulepreload-as.html.ini
@@ -1,17 +1,16 @@
 [modulepreload-as.html]
   expected:
     if (product == "content_shell") and (os == "linux") and (flag_specific == ""): TIMEOUT
-    if (product == "content_shell") and (os == "win") and (port == "win11"): [ERROR, TIMEOUT]
     if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): TIMEOUT
     if (product == "content_shell") and (os == "mac") and (port == "mac11"): OK
     if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): OK
     if (product == "content_shell") and (os == "mac") and (port == "mac12"): OK
+    if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [ERROR, OK]
     ERROR
   [Modulepreload with as="audio"]
     expected:
       if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS
       if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS
-      if (product == "content_shell") and (os == "win") and (port == "win11"): [FAIL, PASS]
       FAIL
 
   [Modulepreload with as="audioworklet"]
@@ -19,7 +18,6 @@
 
   [Modulepreload with as="document"]
     expected:
-      if (product == "content_shell") and (os == "win") and (port == "win11"): [FAIL, PASS]
       if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS
       if (product == "content_shell") and (os == "linux"): PASS
       FAIL
@@ -27,86 +25,84 @@
   [Modulepreload with as="embed"]
     expected:
       if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): PASS
-      if (product == "content_shell") and (os == "win") and (port == "win11"): [FAIL, PASS]
       if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS
       if product == "chrome": PASS
       FAIL
 
   [Modulepreload with as="fetch"]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
       if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
-      if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
 
   [Modulepreload with as="font"]
     expected:
       if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): PASS
-      if (product == "content_shell") and (os == "win") and (port == "win11"): [FAIL, PASS]
       if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): PASS
       if product == "chrome": PASS
       FAIL
 
   [Modulepreload with as="frame"]
     expected:
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
       if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS
-      if (product == "content_shell") and (os == "win") and (port == "win11"): [FAIL, PASS]
       if (product == "content_shell") and (os == "linux"): PASS
       if product == "chrome": PASS
       FAIL
 
   [Modulepreload with as="iMaGe"]
     expected:
-      if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL]
       if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
       if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [PASS, FAIL]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
 
   [Modulepreload with as="iframe"]
     expected:
-      if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL]
-      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS
-      if (product == "content_shell") and (os == "linux"): PASS
-      if product == "chrome": PASS
-      FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
 
   [Modulepreload with as="image"]
     expected:
-      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS
-      if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL]
-      if (product == "content_shell") and (os == "linux"): PASS
-      if product == "chrome": PASS
-      FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
 
   [Modulepreload with as="invalid-dest"]
     expected: FAIL
 
   [Modulepreload with as="manifest"]
     expected:
-      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS
-      if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL]
-      if (product == "content_shell") and (os == "linux"): PASS
-      if product == "chrome": PASS
-      FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
 
   [Modulepreload with as="object"]
     expected:
-      if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL]
       if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
       if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
 
   [Modulepreload with as="paintworklet"]
     expected: FAIL
 
   [Modulepreload with as="report"]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [PASS, FAIL]
       if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
 
   [Modulepreload with as="serviceworker"]
     expected: FAIL
@@ -117,42 +113,39 @@
   [Modulepreload with as="style"]
     expected:
       if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS
-      if (product == "content_shell") and (os == "win") and (port == "win11"): [FAIL, PASS]
       if (product == "content_shell") and (os == "linux"): PASS
       if product == "chrome": PASS
       FAIL
 
   [Modulepreload with as="track"]
     expected:
-      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS
-      if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL]
       if (product == "content_shell") and (os == "linux"): PASS
+      if (product == "content_shell") and (os == "win"): PASS
       if product == "chrome": PASS
       FAIL
 
   [Modulepreload with as="video"]
     expected:
-      if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL]
-      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS
-      if (product == "content_shell") and (os == "linux"): PASS
-      if product == "chrome": PASS
-      FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
 
   [Modulepreload with as="webidentity"]
     expected:
-      if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL]
-      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS
-      if (product == "content_shell") and (os == "linux"): PASS
-      if product == "chrome": PASS
-      FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
 
   [Modulepreload with as="worker"]
     expected: FAIL
 
   [Modulepreload with as="xslt"]
     expected:
-      if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL]
-      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS
+      if (product == "content_shell") and (os == "win"): PASS
       if (product == "content_shell") and (os == "linux"): PASS
       if product == "chrome": PASS
       FAIL
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/css/animation-range-visual-test.html.ini b/third_party/blink/web_tests/external/wpt/scroll-animations/css/animation-range-visual-test.html.ini
index 441e720..dbb5570 100644
--- a/third_party/blink/web_tests/external/wpt/scroll-animations/css/animation-range-visual-test.html.ini
+++ b/third_party/blink/web_tests/external/wpt/scroll-animations/css/animation-range-visual-test.html.ini
@@ -1,3 +1,4 @@
 [animation-range-visual-test.html]
   expected:
+    if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
     if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/url/resources/percent-encoding.json b/third_party/blink/web_tests/external/wpt/url/resources/percent-encoding.json
index bd81edbdc..eccd1db 100644
--- a/third_party/blink/web_tests/external/wpt/url/resources/percent-encoding.json
+++ b/third_party/blink/web_tests/external/wpt/url/resources/percent-encoding.json
@@ -44,13 +44,5 @@
     "output": {
       "utf-8": "%C3%A1|"
     }
-  },
-  "Surrogate!",
-  {
-    "input": "\ud800",
-    "output": {
-      "utf-8": "%EF%BF%BD",
-      "windows-1252": "%26%2365533%3B"
-    }
   }
 ]
diff --git a/third_party/blink/web_tests/external/wpt/url/resources/urltestdata.json b/third_party/blink/web_tests/external/wpt/url/resources/urltestdata.json
index 1aa42a5..ce2c8c0 100644
--- a/third_party/blink/web_tests/external/wpt/url/resources/urltestdata.json
+++ b/third_party/blink/web_tests/external/wpt/url/resources/urltestdata.json
@@ -7907,6 +7907,22 @@
     "search": "",
     "hash": ""
   },
+  "Percent-encoded http: in blob:",
+  {
+    "input": "blob:http%3a//example.org/",
+    "base": null,
+    "href": "blob:http%3a//example.org/",
+    "origin": "null",
+    "protocol": "blob:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "http%3a//example.org/",
+    "search": "",
+    "hash": ""
+  },
   "Invalid IPv4 radix digits",
   {
     "input": "http://0x7f.0.0.0x7g",
diff --git a/third_party/blink/web_tests/external/wpt/webusb/getDevices/sandboxed_iframe.https.window.js.ini b/third_party/blink/web_tests/external/wpt/webusb/getDevices/sandboxed_iframe.https.window.js.ini
new file mode 100644
index 0000000..1bfdbbd
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webusb/getDevices/sandboxed_iframe.https.window.js.ini
@@ -0,0 +1,4 @@
+[sandboxed_iframe.https.window.html]
+  [GetDevices from a sandboxed iframe is valid.]
+    expected:
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
diff --git "a/third_party/blink/web_tests/flag-specific/highdpi/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/flag-specific/highdpi/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
index c547991..936d5fe 100644
--- "a/third_party/blink/web_tests/flag-specific/highdpi/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/flag-specific/highdpi/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 670 tests; 356 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 671 tests; 357 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -551,6 +551,7 @@
 PASS Parsing: <blob:ftp://host/path> against <about:blank>
 PASS Parsing: <blob:ws://example.org/> against <about:blank>
 PASS Parsing: <blob:wss://example.org/> against <about:blank>
+PASS Parsing: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
 PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
 FAIL Parsing: <http://[::127.0.0.0.1]> against <about:blank> assert_equals: failure should set href to input expected "http://[::127.0.0.0.1]" but got "http://[::127.0.0.0.1]/"
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/image-document-default-src-none-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/image-document-default-src-none-expected.txt
index 4cf2e97f..be51287 100644
--- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/image-document-default-src-none-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/image-document-default-src-none-expected.txt
@@ -1,5 +1,3 @@
-CONSOLE ERROR: Refused to apply inline style because it violates the following Content Security Policy directive: "default-src 'none'". Either the 'unsafe-inline' keyword, a hash ('sha256-irYXJOS8dfWxS3v4lGnL1OcyQjamq/FGUi7NhXhtBOk='), or a nonce ('nonce-...') is required to enable inline execution. Note that hashes do not apply to event handlers, style attributes and javascript: navigations unless the 'unsafe-hashes' keyword is present. Note also that 'style-src' was not explicitly set, so 'default-src' is used as a fallback.
-
 CONSOLE ERROR: Refused to apply inline style because it violates the following Content Security Policy directive: "default-src 'none'". Either the 'unsafe-inline' keyword, a hash ('sha256-mqLU0Zw7B/c6fYkvbRoA2V1jZ1apgellJyv17d18uTs='), or a nonce ('nonce-...') is required to enable inline execution. Note that hashes do not apply to event handlers, style attributes and javascript: navigations unless the 'unsafe-hashes' keyword is present. Note also that 'style-src' was not explicitly set, so 'default-src' is used as a fallback.
 
 Ensure that we don't crash when loading an ImageDocument that sets CSP headers 
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-origin-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-origin-expected.txt
index 33e192e..c7c3dab 100644
--- a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-origin-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-origin-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 354 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 355 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing origin: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Parsing origin: <blob:ftp://host/path> against <about:blank> assert_equals: origin expected "null" but got "ftp://host"
 FAIL Parsing origin: <blob:ws://example.org/> against <about:blank> assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Parsing origin: <blob:wss://example.org/> against <about:blank> assert_equals: origin expected "null" but got "wss://example.org"
+PASS Parsing origin: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing origin: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
 PASS Parsing origin: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
 PASS Parsing origin: <https://user:pass[@foo/bar> against <http://example.org>
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-origin-xhtml-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-origin-xhtml-expected.txt
index 33e192e..c7c3dab 100644
--- a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-origin-xhtml-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-origin-xhtml-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 354 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 355 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing origin: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Parsing origin: <blob:ftp://host/path> against <about:blank> assert_equals: origin expected "null" but got "ftp://host"
 FAIL Parsing origin: <blob:ws://example.org/> against <about:blank> assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Parsing origin: <blob:wss://example.org/> against <about:blank> assert_equals: origin expected "null" but got "wss://example.org"
+PASS Parsing origin: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing origin: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
 PASS Parsing origin: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
 PASS Parsing origin: <https://user:pass[@foo/bar> against <http://example.org>
diff --git "a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
index c547991..936d5fe 100644
--- "a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 670 tests; 356 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 671 tests; 357 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -551,6 +551,7 @@
 PASS Parsing: <blob:ftp://host/path> against <about:blank>
 PASS Parsing: <blob:ws://example.org/> against <about:blank>
 PASS Parsing: <blob:wss://example.org/> against <about:blank>
+PASS Parsing: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
 PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
 FAIL Parsing: <http://[::127.0.0.0.1]> against <about:blank> assert_equals: failure should set href to input expected "http://[::127.0.0.0.1]" but got "http://[::127.0.0.0.1]/"
diff --git "a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
index c547991..936d5fe 100644
--- "a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 670 tests; 356 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 671 tests; 357 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -551,6 +551,7 @@
 PASS Parsing: <blob:ftp://host/path> against <about:blank>
 PASS Parsing: <blob:ws://example.org/> against <about:blank>
 PASS Parsing: <blob:wss://example.org/> against <about:blank>
+PASS Parsing: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
 PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
 FAIL Parsing: <http://[::127.0.0.0.1]> against <about:blank> assert_equals: failure should set href to input expected "http://[::127.0.0.0.1]" but got "http://[::127.0.0.0.1]/"
diff --git "a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
index c256ceea..2dbf9862 100644
--- "a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 671 tests; 491 PASS, 180 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 672 tests; 492 PASS, 180 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -643,6 +643,7 @@
 PASS Parsing: <blob:ftp://host/path> without base
 PASS Parsing: <blob:ws://example.org/> without base
 PASS Parsing: <blob:wss://example.org/> without base
+PASS Parsing: <blob:http%3a//example.org/> without base
 PASS Parsing: <http://0x7f.0.0.0x7g> without base
 PASS Parsing: <http://0X7F.0.0.0X7G> without base
 PASS Parsing: <http://[::127.0.0.0.1]> without base
diff --git "a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
index c256ceea..2dbf9862 100644
--- "a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 671 tests; 491 PASS, 180 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 672 tests; 492 PASS, 180 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -643,6 +643,7 @@
 PASS Parsing: <blob:ftp://host/path> without base
 PASS Parsing: <blob:ws://example.org/> without base
 PASS Parsing: <blob:wss://example.org/> without base
+PASS Parsing: <blob:http%3a//example.org/> without base
 PASS Parsing: <http://0x7f.0.0.0x7g> without base
 PASS Parsing: <http://0X7F.0.0.0X7G> without base
 PASS Parsing: <http://[::127.0.0.0.1]> without base
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin.any-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin.any-expected.txt
index 28f2cf2..b02597d 100644
--- a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin.any-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin.any-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 351 PASS, 11 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 352 PASS, 11 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Origin parsing: <blob:ftp://host/path> without base assert_equals: origin expected "null" but got "ftp://host"
 FAIL Origin parsing: <blob:ws://example.org/> without base assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Origin parsing: <blob:wss://example.org/> without base assert_equals: origin expected "null" but got "wss://example.org"
+PASS Origin parsing: <blob:http%3a//example.org/> without base
 PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
 PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin.any.worker-expected.txt
index 28f2cf2..b02597d 100644
--- a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin.any.worker-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin.any.worker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 351 PASS, 11 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 352 PASS, 11 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Origin parsing: <blob:ftp://host/path> without base assert_equals: origin expected "null" but got "ftp://host"
 FAIL Origin parsing: <blob:ws://example.org/> without base assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Origin parsing: <blob:wss://example.org/> without base assert_equals: origin expected "null" but got "wss://example.org"
+PASS Origin parsing: <blob:http%3a//example.org/> without base
 PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
 PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
diff --git a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element-origin-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element-origin-expected.txt
index 16c7d9c..dd78bf05d 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element-origin-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element-origin-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 353 PASS, 9 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 354 PASS, 9 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing origin: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Parsing origin: <blob:ftp://host/path> against <about:blank> assert_equals: origin expected "null" but got "ftp://host"
 FAIL Parsing origin: <blob:ws://example.org/> against <about:blank> assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Parsing origin: <blob:wss://example.org/> against <about:blank> assert_equals: origin expected "null" but got "wss://example.org"
+PASS Parsing origin: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing origin: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
 PASS Parsing origin: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
 PASS Parsing origin: <https://user:pass[@foo/bar> against <http://example.org>
diff --git a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element-origin-xhtml-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element-origin-xhtml-expected.txt
index 16c7d9c..dd78bf05d 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element-origin-xhtml-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element-origin-xhtml-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 353 PASS, 9 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 354 PASS, 9 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing origin: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Parsing origin: <blob:ftp://host/path> against <about:blank> assert_equals: origin expected "null" but got "ftp://host"
 FAIL Parsing origin: <blob:ws://example.org/> against <about:blank> assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Parsing origin: <blob:wss://example.org/> against <about:blank> assert_equals: origin expected "null" but got "wss://example.org"
+PASS Parsing origin: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing origin: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
 PASS Parsing origin: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
 PASS Parsing origin: <https://user:pass[@foo/bar> against <http://example.org>
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
index 8ea5813f0..79e038c 100644
--- "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 670 tests; 355 PASS, 315 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 671 tests; 356 PASS, 315 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -551,6 +551,7 @@
 PASS Parsing: <blob:ftp://host/path> against <about:blank>
 PASS Parsing: <blob:ws://example.org/> against <about:blank>
 PASS Parsing: <blob:wss://example.org/> against <about:blank>
+PASS Parsing: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
 PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
 FAIL Parsing: <http://[::127.0.0.0.1]> against <about:blank> assert_equals: failure should set href to input expected "http://[::127.0.0.0.1]" but got "http://[::127.0.0.0.1]/"
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
index 8ea5813f0..79e038c 100644
--- "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 670 tests; 355 PASS, 315 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 671 tests; 356 PASS, 315 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -551,6 +551,7 @@
 PASS Parsing: <blob:ftp://host/path> against <about:blank>
 PASS Parsing: <blob:ws://example.org/> against <about:blank>
 PASS Parsing: <blob:wss://example.org/> against <about:blank>
+PASS Parsing: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
 PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
 FAIL Parsing: <http://[::127.0.0.0.1]> against <about:blank> assert_equals: failure should set href to input expected "http://[::127.0.0.0.1]" but got "http://[::127.0.0.0.1]/"
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
index e525812d..ee67c7d 100644
--- "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 671 tests; 490 PASS, 181 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 672 tests; 491 PASS, 181 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -643,6 +643,7 @@
 PASS Parsing: <blob:ftp://host/path> without base
 PASS Parsing: <blob:ws://example.org/> without base
 PASS Parsing: <blob:wss://example.org/> without base
+PASS Parsing: <blob:http%3a//example.org/> without base
 PASS Parsing: <http://0x7f.0.0.0x7g> without base
 PASS Parsing: <http://0X7F.0.0.0X7G> without base
 PASS Parsing: <http://[::127.0.0.0.1]> without base
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
index e525812d..ee67c7d 100644
--- "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 671 tests; 490 PASS, 181 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 672 tests; 491 PASS, 181 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -643,6 +643,7 @@
 PASS Parsing: <blob:ftp://host/path> without base
 PASS Parsing: <blob:ws://example.org/> without base
 PASS Parsing: <blob:wss://example.org/> without base
+PASS Parsing: <blob:http%3a//example.org/> without base
 PASS Parsing: <http://0x7f.0.0.0x7g> without base
 PASS Parsing: <http://0X7F.0.0.0X7G> without base
 PASS Parsing: <http://[::127.0.0.0.1]> without base
diff --git a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-origin.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-origin.any-expected.txt
index 6b1fcc92..ec74742 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-origin.any-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-origin.any-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 350 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 351 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Origin parsing: <blob:ftp://host/path> without base assert_equals: origin expected "null" but got "ftp://host"
 FAIL Origin parsing: <blob:ws://example.org/> without base assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Origin parsing: <blob:wss://example.org/> without base assert_equals: origin expected "null" but got "wss://example.org"
+PASS Origin parsing: <blob:http%3a//example.org/> without base
 PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
 PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
diff --git a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-origin.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-origin.any.worker-expected.txt
index 6b1fcc92..ec74742 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-origin.any.worker-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-origin.any.worker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 350 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 351 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Origin parsing: <blob:ftp://host/path> without base assert_equals: origin expected "null" but got "ftp://host"
 FAIL Origin parsing: <blob:ws://example.org/> without base assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Origin parsing: <blob:wss://example.org/> without base assert_equals: origin expected "null" but got "wss://example.org"
+PASS Origin parsing: <blob:http%3a//example.org/> without base
 PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
 PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
diff --git a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element-origin-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element-origin-expected.txt
index 33e192e..c7c3dab 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element-origin-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element-origin-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 354 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 355 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing origin: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Parsing origin: <blob:ftp://host/path> against <about:blank> assert_equals: origin expected "null" but got "ftp://host"
 FAIL Parsing origin: <blob:ws://example.org/> against <about:blank> assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Parsing origin: <blob:wss://example.org/> against <about:blank> assert_equals: origin expected "null" but got "wss://example.org"
+PASS Parsing origin: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing origin: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
 PASS Parsing origin: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
 PASS Parsing origin: <https://user:pass[@foo/bar> against <http://example.org>
diff --git a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element-origin-xhtml-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element-origin-xhtml-expected.txt
index 33e192e..c7c3dab 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element-origin-xhtml-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element-origin-xhtml-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 354 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 355 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing origin: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Parsing origin: <blob:ftp://host/path> against <about:blank> assert_equals: origin expected "null" but got "ftp://host"
 FAIL Parsing origin: <blob:ws://example.org/> against <about:blank> assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Parsing origin: <blob:wss://example.org/> against <about:blank> assert_equals: origin expected "null" but got "wss://example.org"
+PASS Parsing origin: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing origin: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
 PASS Parsing origin: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
 PASS Parsing origin: <https://user:pass[@foo/bar> against <http://example.org>
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
index ca50c8b..39339d1 100644
--- "a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 670 tests; 356 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 671 tests; 357 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -551,6 +551,7 @@
 PASS Parsing: <blob:ftp://host/path> against <about:blank>
 PASS Parsing: <blob:ws://example.org/> against <about:blank>
 PASS Parsing: <blob:wss://example.org/> against <about:blank>
+PASS Parsing: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
 PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
 FAIL Parsing: <http://[::127.0.0.0.1]> against <about:blank> assert_equals: failure should set href to input expected "http://[::127.0.0.0.1]" but got "http://[::127.0.0.0.1]/"
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
index ca50c8b..39339d1 100644
--- "a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 670 tests; 356 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 671 tests; 357 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -551,6 +551,7 @@
 PASS Parsing: <blob:ftp://host/path> against <about:blank>
 PASS Parsing: <blob:ws://example.org/> against <about:blank>
 PASS Parsing: <blob:wss://example.org/> against <about:blank>
+PASS Parsing: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
 PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
 FAIL Parsing: <http://[::127.0.0.0.1]> against <about:blank> assert_equals: failure should set href to input expected "http://[::127.0.0.0.1]" but got "http://[::127.0.0.0.1]/"
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
index f340fb6..d60c9ff6 100644
--- "a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 671 tests; 495 PASS, 176 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 672 tests; 496 PASS, 176 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -635,6 +635,7 @@
 PASS Parsing: <blob:ftp://host/path> without base
 PASS Parsing: <blob:ws://example.org/> without base
 PASS Parsing: <blob:wss://example.org/> without base
+PASS Parsing: <blob:http%3a//example.org/> without base
 PASS Parsing: <http://0x7f.0.0.0x7g> without base
 PASS Parsing: <http://0X7F.0.0.0X7G> without base
 PASS Parsing: <http://[::127.0.0.0.1]> without base
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
index f340fb6..d60c9ff6 100644
--- "a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 671 tests; 495 PASS, 176 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 672 tests; 496 PASS, 176 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -635,6 +635,7 @@
 PASS Parsing: <blob:ftp://host/path> without base
 PASS Parsing: <blob:ws://example.org/> without base
 PASS Parsing: <blob:wss://example.org/> without base
+PASS Parsing: <blob:http%3a//example.org/> without base
 PASS Parsing: <http://0x7f.0.0.0x7g> without base
 PASS Parsing: <http://0X7F.0.0.0X7G> without base
 PASS Parsing: <http://[::127.0.0.0.1]> without base
diff --git a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-origin.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-origin.any-expected.txt
index 28f2cf2..b02597d 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-origin.any-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-origin.any-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 351 PASS, 11 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 352 PASS, 11 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Origin parsing: <blob:ftp://host/path> without base assert_equals: origin expected "null" but got "ftp://host"
 FAIL Origin parsing: <blob:ws://example.org/> without base assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Origin parsing: <blob:wss://example.org/> without base assert_equals: origin expected "null" but got "wss://example.org"
+PASS Origin parsing: <blob:http%3a//example.org/> without base
 PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
 PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
diff --git a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-origin.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-origin.any.worker-expected.txt
index 28f2cf2..b02597d 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-origin.any.worker-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/strict-ipv4-embedded-ipv6/external/wpt/url/url-origin.any.worker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 351 PASS, 11 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 352 PASS, 11 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Origin parsing: <blob:ftp://host/path> without base assert_equals: origin expected "null" but got "ftp://host"
 FAIL Origin parsing: <blob:ws://example.org/> without base assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Origin parsing: <blob:wss://example.org/> without base assert_equals: origin expected "null" but got "wss://example.org"
+PASS Origin parsing: <blob:http%3a//example.org/> without base
 PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
 PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
diff --git "a/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
index c547991..936d5fe 100644
--- "a/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 670 tests; 356 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 671 tests; 357 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -551,6 +551,7 @@
 PASS Parsing: <blob:ftp://host/path> against <about:blank>
 PASS Parsing: <blob:ws://example.org/> against <about:blank>
 PASS Parsing: <blob:wss://example.org/> against <about:blank>
+PASS Parsing: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
 PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
 FAIL Parsing: <http://[::127.0.0.0.1]> against <about:blank> assert_equals: failure should set href to input expected "http://[::127.0.0.0.1]" but got "http://[::127.0.0.0.1]/"
diff --git "a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
index c547991..936d5fe 100644
--- "a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 670 tests; 356 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 671 tests; 357 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -551,6 +551,7 @@
 PASS Parsing: <blob:ftp://host/path> against <about:blank>
 PASS Parsing: <blob:ws://example.org/> against <about:blank>
 PASS Parsing: <blob:wss://example.org/> against <about:blank>
+PASS Parsing: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
 PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
 FAIL Parsing: <http://[::127.0.0.0.1]> against <about:blank> assert_equals: failure should set href to input expected "http://[::127.0.0.0.1]" but got "http://[::127.0.0.0.1]/"
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-origin-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-origin-expected.txt
index 33e192e..c7c3dab 100644
--- a/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-origin-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-origin-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 354 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 355 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing origin: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Parsing origin: <blob:ftp://host/path> against <about:blank> assert_equals: origin expected "null" but got "ftp://host"
 FAIL Parsing origin: <blob:ws://example.org/> against <about:blank> assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Parsing origin: <blob:wss://example.org/> against <about:blank> assert_equals: origin expected "null" but got "wss://example.org"
+PASS Parsing origin: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing origin: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
 PASS Parsing origin: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
 PASS Parsing origin: <https://user:pass[@foo/bar> against <http://example.org>
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-origin-xhtml-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-origin-xhtml-expected.txt
index 33e192e..c7c3dab 100644
--- a/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-origin-xhtml-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-origin-xhtml-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 354 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 355 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing origin: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Parsing origin: <blob:ftp://host/path> against <about:blank> assert_equals: origin expected "null" but got "ftp://host"
 FAIL Parsing origin: <blob:ws://example.org/> against <about:blank> assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Parsing origin: <blob:wss://example.org/> against <about:blank> assert_equals: origin expected "null" but got "wss://example.org"
+PASS Parsing origin: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing origin: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
 PASS Parsing origin: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
 PASS Parsing origin: <https://user:pass[@foo/bar> against <http://example.org>
diff --git "a/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
index c547991..936d5fe 100644
--- "a/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 670 tests; 356 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 671 tests; 357 PASS, 314 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -551,6 +551,7 @@
 PASS Parsing: <blob:ftp://host/path> against <about:blank>
 PASS Parsing: <blob:ws://example.org/> against <about:blank>
 PASS Parsing: <blob:wss://example.org/> against <about:blank>
+PASS Parsing: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
 PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
 FAIL Parsing: <http://[::127.0.0.0.1]> against <about:blank> assert_equals: failure should set href to input expected "http://[::127.0.0.0.1]" but got "http://[::127.0.0.0.1]/"
diff --git "a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
index c256ceea..2dbf9862 100644
--- "a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 671 tests; 491 PASS, 180 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 672 tests; 492 PASS, 180 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -643,6 +643,7 @@
 PASS Parsing: <blob:ftp://host/path> without base
 PASS Parsing: <blob:ws://example.org/> without base
 PASS Parsing: <blob:wss://example.org/> without base
+PASS Parsing: <blob:http%3a//example.org/> without base
 PASS Parsing: <http://0x7f.0.0.0x7g> without base
 PASS Parsing: <http://0X7F.0.0.0X7G> without base
 PASS Parsing: <http://[::127.0.0.0.1]> without base
diff --git "a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
index c256ceea..2dbf9862 100644
--- "a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 671 tests; 491 PASS, 180 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 672 tests; 492 PASS, 180 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -643,6 +643,7 @@
 PASS Parsing: <blob:ftp://host/path> without base
 PASS Parsing: <blob:ws://example.org/> without base
 PASS Parsing: <blob:wss://example.org/> without base
+PASS Parsing: <blob:http%3a//example.org/> without base
 PASS Parsing: <http://0x7f.0.0.0x7g> without base
 PASS Parsing: <http://0X7F.0.0.0X7G> without base
 PASS Parsing: <http://[::127.0.0.0.1]> without base
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin.any-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin.any-expected.txt
index 28f2cf2..b02597d 100644
--- a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin.any-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin.any-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 351 PASS, 11 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 352 PASS, 11 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Origin parsing: <blob:ftp://host/path> without base assert_equals: origin expected "null" but got "ftp://host"
 FAIL Origin parsing: <blob:ws://example.org/> without base assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Origin parsing: <blob:wss://example.org/> without base assert_equals: origin expected "null" but got "wss://example.org"
+PASS Origin parsing: <blob:http%3a//example.org/> without base
 PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
 PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin.any.worker-expected.txt
index 28f2cf2..b02597d 100644
--- a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin.any.worker-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin.any.worker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 351 PASS, 11 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 352 PASS, 11 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Origin parsing: <blob:ftp://host/path> without base assert_equals: origin expected "null" but got "ftp://host"
 FAIL Origin parsing: <blob:ws://example.org/> without base assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Origin parsing: <blob:wss://example.org/> without base assert_equals: origin expected "null" but got "wss://example.org"
+PASS Origin parsing: <blob:http%3a//example.org/> without base
 PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
 PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-origin-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-origin-expected.txt
index 81a6d763..666edbd 100644
--- a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-origin-expected.txt
+++ b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-origin-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 350 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 351 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing origin: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Parsing origin: <blob:ftp://host/path> against <about:blank> assert_equals: origin expected "null" but got "ftp://host"
 FAIL Parsing origin: <blob:ws://example.org/> against <about:blank> assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Parsing origin: <blob:wss://example.org/> against <about:blank> assert_equals: origin expected "null" but got "wss://example.org"
+PASS Parsing origin: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing origin: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
 PASS Parsing origin: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
 PASS Parsing origin: <https://user:pass[@foo/bar> against <http://example.org>
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-origin-xhtml-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-origin-xhtml-expected.txt
index 81a6d763..666edbd 100644
--- a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-origin-xhtml-expected.txt
+++ b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-origin-xhtml-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 350 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 351 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing origin: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Parsing origin: <blob:ftp://host/path> against <about:blank> assert_equals: origin expected "null" but got "ftp://host"
 FAIL Parsing origin: <blob:ws://example.org/> against <about:blank> assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Parsing origin: <blob:wss://example.org/> against <about:blank> assert_equals: origin expected "null" but got "wss://example.org"
+PASS Parsing origin: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing origin: <non-special:cannot-be-a-base-url-\0~€> against <about:blank>
 PASS Parsing origin: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank>
 PASS Parsing origin: <https://user:pass[@foo/bar> against <http://example.org>
diff --git "a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
index f090a6dd..1cbf14b 100644
--- "a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-xhtml_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 670 tests; 351 PASS, 319 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 671 tests; 352 PASS, 319 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -551,6 +551,7 @@
 PASS Parsing: <blob:ftp://host/path> against <about:blank>
 PASS Parsing: <blob:ws://example.org/> against <about:blank>
 PASS Parsing: <blob:wss://example.org/> against <about:blank>
+PASS Parsing: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
 PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
 FAIL Parsing: <http://[::127.0.0.0.1]> against <about:blank> assert_equals: failure should set href to input expected "http://[::127.0.0.0.1]" but got "http://[::127.0.0.0.1]/"
diff --git "a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
index f090a6dd..1cbf14b 100644
--- "a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 670 tests; 351 PASS, 319 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 671 tests; 352 PASS, 319 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -551,6 +551,7 @@
 PASS Parsing: <blob:ftp://host/path> against <about:blank>
 PASS Parsing: <blob:ws://example.org/> against <about:blank>
 PASS Parsing: <blob:wss://example.org/> against <about:blank>
+PASS Parsing: <blob:http%3a//example.org/> against <about:blank>
 PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank>
 PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank>
 FAIL Parsing: <http://[::127.0.0.0.1]> against <about:blank> assert_equals: failure should set href to input expected "http://[::127.0.0.0.1]" but got "http://[::127.0.0.0.1]/"
diff --git "a/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
index 4dd2b886..4c5b670 100644
--- "a/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 671 tests; 482 PASS, 189 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 672 tests; 483 PASS, 189 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -647,6 +647,7 @@
 PASS Parsing: <blob:ftp://host/path> without base
 PASS Parsing: <blob:ws://example.org/> without base
 PASS Parsing: <blob:wss://example.org/> without base
+PASS Parsing: <blob:http%3a//example.org/> without base
 PASS Parsing: <http://0x7f.0.0.0x7g> without base
 PASS Parsing: <http://0X7F.0.0.0X7G> without base
 PASS Parsing: <http://[::127.0.0.0.1]> without base
diff --git "a/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
index 4dd2b886..4c5b670 100644
--- "a/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
+++ "b/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor.any_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 671 tests; 482 PASS, 189 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 672 tests; 483 PASS, 189 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -647,6 +647,7 @@
 PASS Parsing: <blob:ftp://host/path> without base
 PASS Parsing: <blob:ws://example.org/> without base
 PASS Parsing: <blob:wss://example.org/> without base
+PASS Parsing: <blob:http%3a//example.org/> without base
 PASS Parsing: <http://0x7f.0.0.0x7g> without base
 PASS Parsing: <http://0X7F.0.0.0X7G> without base
 PASS Parsing: <http://[::127.0.0.0.1]> without base
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin.any-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin.any-expected.txt
index b414878..1256683 100644
--- a/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin.any-expected.txt
+++ b/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin.any-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 347 PASS, 15 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 348 PASS, 15 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Origin parsing: <blob:ftp://host/path> without base assert_equals: origin expected "null" but got "ftp://host"
 FAIL Origin parsing: <blob:ws://example.org/> without base assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Origin parsing: <blob:wss://example.org/> without base assert_equals: origin expected "null" but got "wss://example.org"
+PASS Origin parsing: <blob:http%3a//example.org/> without base
 PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
 PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin.any.worker-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin.any.worker-expected.txt
index b414878..1256683 100644
--- a/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin.any.worker-expected.txt
+++ b/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin.any.worker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 362 tests; 347 PASS, 15 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 363 tests; 348 PASS, 15 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS Origin parsing: <http://example	.
 org> against <http://example.org/foo/bar>
@@ -333,6 +333,7 @@
 FAIL Origin parsing: <blob:ftp://host/path> without base assert_equals: origin expected "null" but got "ftp://host"
 FAIL Origin parsing: <blob:ws://example.org/> without base assert_equals: origin expected "null" but got "ws://example.org"
 FAIL Origin parsing: <blob:wss://example.org/> without base assert_equals: origin expected "null" but got "wss://example.org"
+PASS Origin parsing: <blob:http%3a//example.org/> without base
 PASS Origin parsing: <non-special:cannot-be-a-base-url-\0~€> without base
 PASS Origin parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> without base
 PASS Origin parsing: <https://user:pass[@foo/bar> against <http://example.org>
diff --git a/third_party/wayland-protocols/unstable/text-input/text-input-extension-unstable-v1.xml b/third_party/wayland-protocols/unstable/text-input/text-input-extension-unstable-v1.xml
index ff200b9..a25eaac5 100644
--- a/third_party/wayland-protocols/unstable/text-input/text-input-extension-unstable-v1.xml
+++ b/third_party/wayland-protocols/unstable/text-input/text-input-extension-unstable-v1.xml
@@ -24,7 +24,7 @@
     DEALINGS IN THE SOFTWARE.
   </copyright>
 
-  <interface name="zcr_text_input_extension_v1" version="10">
+  <interface name="zcr_text_input_extension_v1" version="11">
     <description summary="extends text_input to support richer operations">
       Allows a text_input to sends more variation of operations to support
       richer features, such as set_preedit_region.
@@ -57,7 +57,7 @@
 
   </interface>
 
-  <interface name="zcr_extended_text_input_v1" version="10">
+  <interface name="zcr_extended_text_input_v1" version="11">
     <description summary="extension of text_input protocol">
       The zcr_extended_text_input_v1 interface extends the text_input interface
       to support more rich operations on text_input.
@@ -392,5 +392,21 @@
       <arg name="offset_utf16" type="uint"/>
     </request>
 
+    <!-- Version 11 -->
+
+    <enum name="confirm_preedit_selection_behavior" since="11">
+      <description summary="How the selection range is affected by confirm_preedit"></description>
+      <entry name="after_preedit" value="0" summary="The cursor is moved to the end of the committed preedit text, if any."/>
+      <entry name="unchanged" value="1" summary="The selection range is not affected at all."/>
+    </enum>
+
+    <event name="confirm_preedit" since="11">
+      <description summary="Commits the current preedit">
+        Commits the current preedit and modify the selection range according to selection_behavior.
+        Has no effect if there's no preedit text.
+      </description>
+      <arg name="selection_behavior" type="uint" enum="confirm_preedit_selection_behavior" />
+    </event>
+
   </interface>
 </protocol>
diff --git a/tools/clang/plugins/RawPtrManualPathsToIgnore.h b/tools/clang/plugins/RawPtrManualPathsToIgnore.h
index f98305b..b50c4b2 100644
--- a/tools/clang/plugins/RawPtrManualPathsToIgnore.h
+++ b/tools/clang/plugins/RawPtrManualPathsToIgnore.h
@@ -46,10 +46,12 @@
     "net/tools/",
     "chrome/chrome_elf/",
     "chrome/installer/mini_installer/",
+    "testing/platform_test.h",
 
     // DEPS prohibits includes from base/
     "chrome/install_static",
     "net/cert/pki",
+    "sandbox/mac/",
 
     // Exclude pocdll.dll as it doesn't depend on //base and only used for
     // testing.
diff --git a/tools/metrics/histograms/metadata/input/histograms.xml b/tools/metrics/histograms/metadata/input/histograms.xml
index 97369d8..f3a3dd9c 100644
--- a/tools/metrics/histograms/metadata/input/histograms.xml
+++ b/tools/metrics/histograms/metadata/input/histograms.xml
@@ -657,6 +657,19 @@
   </summary>
 </histogram>
 
+<histogram name="InputMethod.Assistive.MultiWord.EmptyCandidate"
+    enum="IMEAssistiveMultiWordSuggestionType" expires_after="2023-10-01">
+  <owner>curtismcmullan@google.com</owner>
+  <owner>essential-inputs-team@google.com</owner>
+  <summary>
+    This histogram records when an empty completion candidate is added to a
+    suggestion generation request to the machine learning service. An empty
+    completion candidate in this context means a candidate with an empty string.
+    This is an invalid state and should never happen. The metric is recorded
+    once per empty candidate found.
+  </summary>
+</histogram>
+
 <histogram name="InputMethod.Assistive.MultiWord.ImplicitAcceptance"
     enum="IMEAssistiveMultiWordSuggestionType" expires_after="2023-10-01">
   <owner>curtismcmullan@google.com</owner>
diff --git a/ui/base/ime/linux/input_method_auralinux_unittest.cc b/ui/base/ime/linux/input_method_auralinux_unittest.cc
index f30d857..e04caf60 100644
--- a/ui/base/ime/linux/input_method_auralinux_unittest.cc
+++ b/ui/base/ime/linux/input_method_auralinux_unittest.cc
@@ -1214,6 +1214,28 @@
   RemoveLastClient(client.get());
 }
 
+TEST_F(InputMethodAuraLinuxTest, OnConfirmCompositionText) {
+  auto client =
+      std::make_unique<TextInputClientForTesting>(TEXT_INPUT_TYPE_TEXT);
+  InstallFirstClient(client.get());
+
+  input_method_auralinux_->OnPreeditStart();
+  CompositionText comp;
+  comp.text = u"a";
+  input_method_auralinux_->OnPreeditChanged(comp);
+
+  test_result_->ExpectAction("compositionstart");
+  test_result_->ExpectAction("compositionupdate:a");
+  test_result_->Verify();
+
+  input_method_auralinux_->OnConfirmCompositionText(/*keep_selection=*/true);
+
+  test_result_->ExpectAction("compositionend");
+  test_result_->ExpectAction("textinput:a");
+
+  RemoveLastClient(client.get());
+}
+
 TEST_F(InputMethodAuraLinuxTest, GetVirtualKeyboardController) {
   EXPECT_EQ(input_method_auralinux_->GetVirtualKeyboardController(),
             context_->GetVirtualKeyboardController());
diff --git a/ui/chromeos/styles/cros_sys_colors.json5 b/ui/chromeos/styles/cros_sys_colors.json5
index 6761361..51b9246 100644
--- a/ui/chromeos/styles/cros_sys_colors.json5
+++ b/ui/chromeos/styles/cros_sys_colors.json5
@@ -94,6 +94,7 @@
     'on-primary': {
       light: '$cros.ref.primary100',
       dark:  '$cros.ref.primary20',
+      generate_per_mode: true,
     },
     /* If this is changed, please also update SampleColorScheme */
     'primary-container': {
diff --git a/ui/file_manager/.eslintrc.js b/ui/file_manager/.eslintrc.js
index 986293b..be87144 100644
--- a/ui/file_manager/.eslintrc.js
+++ b/ui/file_manager/.eslintrc.js
@@ -14,9 +14,7 @@
       '@typescript-eslint',
     ],
     'rules': {
-      // TODO(b/265863256): Re-enable when TypeScript annotations complication
-      // has been fixed.
-      '@typescript-eslint/no-unused-vars': 'off',
+      // rule override goes here.
     },
   }],
 };
diff --git a/ui/file_manager/file_manager/containers/nudge_container.ts b/ui/file_manager/file_manager/containers/nudge_container.ts
index 331788d..c8ef11c 100644
--- a/ui/file_manager/file_manager/containers/nudge_container.ts
+++ b/ui/file_manager/file_manager/containers/nudge_container.ts
@@ -465,7 +465,8 @@
     dismissOnKeyDown: treeDismissOnKeyDownOnTreeItem,
   },
   [NudgeType['SEARCH_V2_EDUCATION_NUDGE']]: {
-    anchor: () => document.querySelector<HTMLSpanElement>('#search-wrapper'),
+    anchor: () =>
+        document.querySelector<HTMLDivElement>('#search-button > .icon'),
     content: () => str('SEARCH_V2_EDUCATION_NUDGE'),
     direction: NudgeDirection.BOTTOM_STARTWARD,
     // Expire after 4 releases (expires when M120 hits Stable).
diff --git a/ui/file_manager/file_manager/foreground/images/files/ui/cloud_done.svg b/ui/file_manager/file_manager/foreground/images/files/ui/cloud_done.svg
index 0383d03..8411584 100644
--- a/ui/file_manager/file_manager/foreground/images/files/ui/cloud_done.svg
+++ b/ui/file_manager/file_manager/foreground/images/files/ui/cloud_done.svg
@@ -1 +1 @@
-<svg id="cloud_done" width="12" height="12" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip)"><path d="M6 1a5 5 0 110 10A5 5 0 016 1zm0-1a6 6 0 100 12A6 6 0 006 0z" fill="#FEFBFF"/><path d="M6 11A5 5 0 106 1a5 5 0 000 10z" fill="#00885E"/><path d="M5.269 7.93a.58.58 0 01-.42-.18l-1.2-1.2a.6.6 0 01.84-.85l.78.78 2.24-2.23a.594.594 0 11.84.84l-2.65 2.66a.61.61 0 01-.43.18z" fill="#FEFBFF"/></g><defs><clipPath id="clip"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath></defs></svg>
+<svg id="cloud_done" width="12" height="12" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip)"><path d="M6 1a5 5 0 110 10A5 5 0 016 1zm0-1a6 6 0 100 12A6 6 0 006 0z" fill="var(--xf-icon-base-color, #fff)"/><path d="M6 11A5 5 0 106 1a5 5 0 000 10z" fill="#00885E"/><path d="M5.269 7.93a.58.58 0 01-.42-.18l-1.2-1.2a.6.6 0 01.84-.85l.78.78 2.24-2.23a.594.594 0 11.84.84l-2.65 2.66a.61.61 0 01-.43.18z" fill="#FEFBFF"/></g><defs><clipPath id="clip"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath></defs></svg>
diff --git a/ui/file_manager/file_manager/foreground/images/files/ui/cloud_error.svg b/ui/file_manager/file_manager/foreground/images/files/ui/cloud_error.svg
index 82b0c58..861a78ea 100644
--- a/ui/file_manager/file_manager/foreground/images/files/ui/cloud_error.svg
+++ b/ui/file_manager/file_manager/foreground/images/files/ui/cloud_error.svg
@@ -1 +1 @@
-<svg id="cloud_error" width="12" height="12" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip)"><path d="M6 1a5 5 0 110 10A5 5 0 016 1zm0-1a6 6 0 100 12A6 6 0 006 0z" fill="#FEFBFF"/><path d="M6 11A5 5 0 106 1a5 5 0 000 10z" fill="#E02E4E"/><path d="M5.398 3.31h1.2v3h-1.2v-3zM5.398 7.35h1.2V8.7h-1.2V7.35z" fill="#FEFBFF"/></g><defs><clipPath id="clip"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath></defs></svg>
+<svg id="cloud_error" width="12" height="12" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip)"><path d="M6 1a5 5 0 110 10A5 5 0 016 1zm0-1a6 6 0 100 12A6 6 0 006 0z" fill="var(--xf-icon-base-color, #fff)"/><path d="M6 11A5 5 0 106 1a5 5 0 000 10z" fill="#E02E4E"/><path d="M5.398 3.31h1.2v3h-1.2v-3zM5.398 7.35h1.2V8.7h-1.2V7.35z" fill="#FEFBFF"/></g><defs><clipPath id="clip"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath></defs></svg>
diff --git a/ui/file_manager/file_manager/foreground/images/files/ui/cloud_sync.svg b/ui/file_manager/file_manager/foreground/images/files/ui/cloud_sync.svg
index 1d625d7..4f6b7b1c 100644
--- a/ui/file_manager/file_manager/foreground/images/files/ui/cloud_sync.svg
+++ b/ui/file_manager/file_manager/foreground/images/files/ui/cloud_sync.svg
@@ -1 +1 @@
-<svg id="cloud_sync" width="12" height="12" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip)"><path d="M6 1a5 5 0 110 10A5 5 0 016 1zm0-1a6 6 0 100 12A6 6 0 006 0z" fill="#FEFBFF"/><path d="M6 11A5 5 0 106 1a5 5 0 000 10z" fill="#5973C4"/><path d="M3.325 8.285A3.49 3.49 0 012.47 6a3.5 3.5 0 013.03-3.42v1a2.49 2.49 0 00-.8 4.6V7.11h.77v2.34a3.49 3.49 0 01-2.144-1.165zM6.499 5V2.66a3.48 3.48 0 010 6.89v-1a2.49 2.49 0 00.8-4.55v1h-.8z" fill="#FEFBFF"/></g><defs><clipPath id="clip"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath></defs></svg>
+<svg id="cloud_sync" width="12" height="12" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip)"><path d="M6 1a5 5 0 110 10A5 5 0 016 1zm0-1a6 6 0 100 12A6 6 0 006 0z" fill="var(--xf-icon-base-color, #fff)"/><path d="M6 11A5 5 0 106 1a5 5 0 000 10z" fill="#5973C4"/><path d="M3.325 8.285A3.49 3.49 0 012.47 6a3.5 3.5 0 013.03-3.42v1a2.49 2.49 0 00-.8 4.6V7.11h.77v2.34a3.49 3.49 0 01-2.144-1.165zM6.499 5V2.66a3.48 3.48 0 010 6.89v-1a2.49 2.49 0 00.8-4.55v1h-.8z" fill="#FEFBFF"/></g><defs><clipPath id="clip"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath></defs></svg>
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
index 8c8a9dc6..315e6be 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -1485,11 +1485,6 @@
  */
 CommandHandler.COMMANDS_['empty-trash'] = new (class extends FilesCommand {
   execute(event, fileManager) {
-    const numEntries = fileManager.directoryModel.getFileList().length;
-    if (numEntries === 0) {
-      return;
-    }
-
     fileManager.ui.emptyTrashConfirmDialog.showWithTitle(
         str('CONFIRM_EMPTY_TRASH_TITLE'), str('CONFIRM_EMPTY_TRASH_DESC'),
         () => {
diff --git a/ui/file_manager/file_manager/widgets/xf_cloud_panel.ts b/ui/file_manager/file_manager/widgets/xf_cloud_panel.ts
index 591d480..05fa172 100644
--- a/ui/file_manager/file_manager/widgets/xf_cloud_panel.ts
+++ b/ui/file_manager/file_manager/widgets/xf_cloud_panel.ts
@@ -324,7 +324,7 @@
     }
 
     progress::-webkit-progress-bar {
-      background-color: var(--cros-sys-primary_container);
+      background-color: var(--cros-sys-highlight_shape);
       border-radius: 10px;
     }
 
@@ -343,10 +343,10 @@
       background-color: var(--cros-sys-base_elevated);
       border: 0;
       font: var(--cros-button-2-font);
-      height: 52px;
-      padding-bottom: 8px;
+      height: 36px;
+      margin-bottom: 8px;
+      margin-top: 8px;
       padding-inline: 16px;
-      padding-top: 8px;
       text-align: left;
     }
 
diff --git a/ui/file_manager/file_manager/widgets/xf_icon.ts b/ui/file_manager/file_manager/widgets/xf_icon.ts
index c7239a3e..2b0d0a0 100644
--- a/ui/file_manager/file_manager/widgets/xf_icon.ts
+++ b/ui/file_manager/file_manager/widgets/xf_icon.ts
@@ -112,6 +112,7 @@
   return css`
     :host {
       --xf-icon-color: var(--cros-sys-on_surface);
+      --xf-icon-base-color: var(--cros-sys-app_base);
       display: inline-block;
     }
 
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.cc b/ui/ozone/platform/wayland/host/wayland_connection.cc
index 72ef342..a828c79 100644
--- a/ui/ozone/platform/wayland/host/wayland_connection.cc
+++ b/ui/ozone/platform/wayland/host/wayland_connection.cc
@@ -80,7 +80,7 @@
 constexpr uint32_t kMaxWpPresentationVersion = 1;
 constexpr uint32_t kMaxWpViewporterVersion = 1;
 constexpr uint32_t kMaxTextInputManagerVersion = 1;
-constexpr uint32_t kMaxTextInputExtensionVersion = 10;
+constexpr uint32_t kMaxTextInputExtensionVersion = 11;
 constexpr uint32_t kMaxExplicitSyncVersion = 2;
 constexpr uint32_t kMaxAlphaCompositingVersion = 1;
 constexpr uint32_t kMaxXdgDecorationVersion = 1;
diff --git a/ui/ozone/platform/wayland/host/wayland_input_method_context.cc b/ui/ozone/platform/wayland/host/wayland_input_method_context.cc
index d45293a..a11b029 100644
--- a/ui/ozone/platform/wayland/host/wayland_input_method_context.cc
+++ b/ui/ozone/platform/wayland/host/wayland_input_method_context.cc
@@ -844,6 +844,11 @@
     past_clients_.clear();
 }
 
+void WaylandInputMethodContext::OnConfirmPreedit(bool keep_selection) {
+  surrounding_text_tracker_.OnConfirmCompositionText(keep_selection);
+  ime_delegate_->OnConfirmCompositionText(keep_selection);
+}
+
 void WaylandInputMethodContext::OnInputPanelState(uint32_t state) {
   virtual_keyboard_visible_ = (state & 1) != 0;
   // Note: Currently there's no support of VirtualKeyboardControllerObserver.
diff --git a/ui/ozone/platform/wayland/host/wayland_input_method_context.h b/ui/ozone/platform/wayland/host/wayland_input_method_context.h
index 2298c659..e0272c0 100644
--- a/ui/ozone/platform/wayland/host/wayland_input_method_context.h
+++ b/ui/ozone/platform/wayland/host/wayland_input_method_context.h
@@ -96,6 +96,7 @@
   void OnSetAutocorrectRange(const gfx::Range& range) override;
   void OnSetVirtualKeyboardOccludedBounds(
       const gfx::Rect& screen_bounds) override;
+  void OnConfirmPreedit(bool keep_selection) override;
   void OnInputPanelState(uint32_t state) override;
   void OnModifiersMap(std::vector<std::string> modifiers_map) override;
 
diff --git a/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc b/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc
index ce9132a..b13e2e83 100644
--- a/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc
+++ b/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc
@@ -34,6 +34,7 @@
 using ::testing::DoAll;
 using ::testing::InSequence;
 using ::testing::Mock;
+using ::testing::Optional;
 using ::testing::SaveArg;
 using ::testing::Values;
 
@@ -153,7 +154,7 @@
     was_on_commit_called_ = true;
   }
   void OnConfirmCompositionText(bool keep_selection) override {
-    was_on_confirm_composition_text_called_ = true;
+    last_on_confirm_composition_arg_ = keep_selection;
   }
   void OnPreeditChanged(const ui::CompositionText& composition_text) override {
     was_on_preedit_changed_called_ = true;
@@ -185,8 +186,8 @@
 
   bool was_on_commit_called() const { return was_on_commit_called_; }
 
-  bool was_on_confirm_composition_text_called() const {
-    return was_on_confirm_composition_text_called_;
+  const absl::optional<bool>& last_on_confirm_composition_arg() const {
+    return last_on_confirm_composition_arg_;
   }
 
   bool was_on_preedit_changed_called() const {
@@ -220,7 +221,7 @@
 
  private:
   bool was_on_commit_called_ = false;
-  bool was_on_confirm_composition_text_called_ = false;
+  absl::optional<bool> last_on_confirm_composition_arg_;
   bool was_on_preedit_changed_called_ = false;
   bool was_on_set_preedit_region_called_ = false;
   bool was_on_clear_grammar_fragments_called_ = false;
@@ -1203,8 +1204,8 @@
                                          "ab😀cあdef");
   });
 
-  EXPECT_TRUE(
-      input_method_context_delegate_->was_on_confirm_composition_text_called());
+  EXPECT_THAT(input_method_context_delegate_->last_on_confirm_composition_arg(),
+              Optional(true));
   EXPECT_EQ(
       input_method_context_->predicted_state_for_testing().surrounding_text,
       text);
@@ -1216,6 +1217,94 @@
 }
 
 TEST_P(WaylandInputMethodContextTest,
+       MAYBE(OnConfirmCompositionTextExtendedKeepSelectionNoComposition)) {
+  input_method_context_->SetSurroundingText(u"abcd", gfx::Range(0, 4),
+                                            gfx::Range(0, 4), absl::nullopt,
+                                            absl::nullopt);
+  connection_->Flush();
+
+  PostToServerAndWait([](wl::TestWaylandServerThread* server) {
+    zcr_extended_text_input_v1_send_confirm_preedit(
+        server->text_input_extension_v1()->extended_text_input()->resource(),
+        /*selection_behavior=*/
+        ZCR_EXTENDED_TEXT_INPUT_V1_CONFIRM_PREEDIT_SELECTION_BEHAVIOR_UNCHANGED);
+  });
+
+  EXPECT_THAT(input_method_context_delegate_->last_on_confirm_composition_arg(),
+              Optional(true));
+  // Selection range should not be changed.
+  EXPECT_EQ(input_method_context_->predicted_state_for_testing().selection,
+            gfx::Range(0, 4));
+}
+
+TEST_P(WaylandInputMethodContextTest,
+       MAYBE(OnConfirmCompositionTextExtendedKeepSelectionComposition)) {
+  input_method_context_->SetSurroundingText(
+      u"abcd", gfx::Range(0, 4), gfx::Range(2), absl::nullopt, absl::nullopt);
+  input_method_context_->OnPreeditString("xyz", {}, 1);
+  connection_->Flush();
+
+  PostToServerAndWait([](wl::TestWaylandServerThread* server) {
+    zcr_extended_text_input_v1_send_confirm_preedit(
+        server->text_input_extension_v1()->extended_text_input()->resource(),
+        /*selection_behavior=*/
+        ZCR_EXTENDED_TEXT_INPUT_V1_CONFIRM_PREEDIT_SELECTION_BEHAVIOR_UNCHANGED);
+  });
+
+  EXPECT_THAT(input_method_context_delegate_->last_on_confirm_composition_arg(),
+              Optional(true));
+  // Selection range should not be changed.
+  EXPECT_EQ(input_method_context_->predicted_state_for_testing().selection,
+            gfx::Range(3));
+}
+
+TEST_P(WaylandInputMethodContextTest,
+       MAYBE(OnConfirmCompositionTextExtendedDontKeepSelectionNoComposition)) {
+  input_method_context_->SetSurroundingText(u"abcd", gfx::Range(0, 4),
+                                            gfx::Range(0, 4), absl::nullopt,
+                                            absl::nullopt);
+  connection_->Flush();
+
+  PostToServerAndWait([](wl::TestWaylandServerThread* server) {
+    zcr_extended_text_input_v1_send_confirm_preedit(
+        server->text_input_extension_v1()->extended_text_input()->resource(),
+        /*selection_behavior=*/
+        ZCR_EXTENDED_TEXT_INPUT_V1_CONFIRM_PREEDIT_SELECTION_BEHAVIOR_AFTER_PREEDIT);
+  });
+
+  EXPECT_THAT(input_method_context_delegate_->last_on_confirm_composition_arg(),
+              Optional(false));
+  // Selection range should not be changed.
+  EXPECT_EQ(input_method_context_->predicted_state_for_testing().selection,
+            gfx::Range(0, 4));
+  EXPECT_EQ(input_method_context_->predicted_state_for_testing().composition,
+            gfx::Range(0));
+}
+
+TEST_P(WaylandInputMethodContextTest,
+       MAYBE(OnConfirmCompositionTextExtendedDontKeepSelectionComposition)) {
+  input_method_context_->SetSurroundingText(
+      u"abcd", gfx::Range(0, 4), gfx::Range(2), absl::nullopt, absl::nullopt);
+  input_method_context_->OnPreeditString("xyz", {}, 1);
+  connection_->Flush();
+
+  PostToServerAndWait([](wl::TestWaylandServerThread* server) {
+    zcr_extended_text_input_v1_send_confirm_preedit(
+        server->text_input_extension_v1()->extended_text_input()->resource(),
+        /*selection_behavior=*/
+        ZCR_EXTENDED_TEXT_INPUT_V1_CONFIRM_PREEDIT_SELECTION_BEHAVIOR_AFTER_PREEDIT);
+  });
+
+  EXPECT_THAT(input_method_context_delegate_->last_on_confirm_composition_arg(),
+              Optional(false));
+  // Selection range should move to the end of commit.
+  EXPECT_EQ(input_method_context_->predicted_state_for_testing().selection,
+            gfx::Range(5));
+  EXPECT_EQ(input_method_context_->predicted_state_for_testing().composition,
+            gfx::Range(0));
+}
+
+TEST_P(WaylandInputMethodContextTest,
        MAYBE(OnConfirmCompositionTextForLongRange)) {
   const std::u16string text(5000, u'あ');
   constexpr gfx::Range range(4000, 4500);
@@ -1268,8 +1357,8 @@
                                          expected_sent_text.c_str());
   });
 
-  EXPECT_TRUE(
-      input_method_context_delegate_->was_on_confirm_composition_text_called());
+  EXPECT_THAT(input_method_context_delegate_->last_on_confirm_composition_arg(),
+              Optional(true));
   EXPECT_EQ(
       input_method_context_->predicted_state_for_testing().surrounding_text,
       text);
diff --git a/ui/ozone/platform/wayland/host/zwp_text_input_wrapper.h b/ui/ozone/platform/wayland/host/zwp_text_input_wrapper.h
index 2181aa7..58460b5 100644
--- a/ui/ozone/platform/wayland/host/zwp_text_input_wrapper.h
+++ b/ui/ozone/platform/wayland/host/zwp_text_input_wrapper.h
@@ -92,6 +92,9 @@
   virtual void OnSetVirtualKeyboardOccludedBounds(
       const gfx::Rect& screen_bounds) = 0;
 
+  // Called when confirming the preedit.
+  virtual void OnConfirmPreedit(bool keep_selection) = 0;
+
   // Called when the visibility state of the input panel changed.
   // There's no detailed spec of |state|, and no actual implementor except
   // components/exo is found in the world at this moment.
diff --git a/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.cc b/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.cc
index 4c036fa7..3a1b4ac 100644
--- a/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.cc
+++ b/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.cc
@@ -129,6 +129,7 @@
           &OnAddGrammarFragment,   // extended_text_input_add_grammar_fragment,
           &OnSetAutocorrectRange,  // extended_text_input_set_autocorrect_range,
           &OnSetVirtualKeyboardOccludedBounds,  // extended_text_input_set_virtual_keyboard_occluded_bounds,
+          &OnConfirmPreedit,  // extended_text_input_confirm_preedit,
       };
 
   obj_ = wl::Object<zwp_text_input_v1>(
@@ -513,4 +514,23 @@
   self->client_->OnSetVirtualKeyboardOccludedBounds(screen_bounds);
 }
 
+// static
+void ZWPTextInputWrapperV1::OnConfirmPreedit(
+    void* data,
+    struct zcr_extended_text_input_v1* extended_text_input,
+    uint32_t selection_behavior) {
+  auto* self = static_cast<ZWPTextInputWrapperV1*>(data);
+  switch (selection_behavior) {
+    case ZCR_EXTENDED_TEXT_INPUT_V1_CONFIRM_PREEDIT_SELECTION_BEHAVIOR_AFTER_PREEDIT:
+      self->client_->OnConfirmPreedit(/*keep_selection=*/false);
+      break;
+    case ZCR_EXTENDED_TEXT_INPUT_V1_CONFIRM_PREEDIT_SELECTION_BEHAVIOR_UNCHANGED:
+      self->client_->OnConfirmPreedit(/*keep_selection=*/true);
+      break;
+    default:
+      self->client_->OnConfirmPreedit(/*keep_selection=*/false);
+      break;
+  }
+}
+
 }  // namespace ui
diff --git a/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.h b/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.h
index 45cf5f3..fa7dc891 100644
--- a/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.h
+++ b/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.h
@@ -147,6 +147,10 @@
       int32_t y,
       int32_t width,
       int32_t height);
+  static void OnConfirmPreedit(
+      void* data,
+      struct zcr_extended_text_input_v1* extended_text_input,
+      uint32_t selection_behavior);
 
   const raw_ptr<WaylandConnection> connection_;
   wl::Object<zwp_text_input_v1> obj_;