diff --git a/DEPS b/DEPS
index 004b9a6..7acef5c5 100644
--- a/DEPS
+++ b/DEPS
@@ -304,15 +304,15 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'ccd5d27fd4bee5c9a7bd52d8f81b1ef4913eb4eb',
+  'skia_revision': 'e910b73230f69c659acb209018fa7b0c4d92df5a',
   # 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': '69535c29d7908813c24b0e778b05868b515c7dc8',
+  'v8_revision': 'f51e77140f646a5c7e5013472d56eb51641be715',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '1f8bc491082d1059284183c094e9c7aead4bac81',
+  'angle_revision': '9de913077a5fcc3d2f2e327b56bbe30efe2fde96',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -355,7 +355,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
-  'freetype_revision': '6a179ff7d55714501c5efce85e2a47de6055a07a',
+  'freetype_revision': 'f80be4e959a5d41688dd6e257497e2627ae2d967',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
@@ -383,7 +383,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': '4b0603be0585b48597644e0767f9767d24695a5c',
+  'devtools_frontend_revision': 'adccf1afe5d585b294dee247f5a4982aca8f5f1e',
   # 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.
@@ -443,7 +443,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling nearby
   # and whatever else without interference from each other.
-  'nearby_revision': '589829f9470d656695938b725c53c4c29f754f86',
+  'nearby_revision': 'ea3fa0e3924c9e4be23504cbde398cef305d3197',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling securemessage
   # and whatever else without interference from each other.
@@ -775,7 +775,7 @@
   },
 
   'src/docs/website': {
-    'url': Var('chromium_git') + '/website.git' + '@' + '331c66794c361d3e976a4f1d7b914e3d9438d494',
+    'url': Var('chromium_git') + '/website.git' + '@' + '2dbe8f2580d39a915540bd86e79a645a1b523d48',
   },
 
   'src/ios/third_party/earl_grey2/src': {
@@ -1204,13 +1204,13 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '7879da9e9dfc4ee3c44b7a52f446bb52de83a9a1',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '4f50adb3325cbc0eb19ad3d94fd63a3dc4418817',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + '36d3a77cc050023459fd304ddf1317058e2675ec',
+      'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + 'fed2a37435f19bd1322341a98d61f60d15a31052',
     'condition': 'checkout_src_internal',
   },
 
@@ -1218,7 +1218,7 @@
     Var('chromium_git') + '/chromium/dom-distiller/dist.git' + '@' + '199de96b345ada7c6e7e6ba3d2fa7a6911b8767d',
 
   'src/third_party/eigen3/src':
-    Var('chromium_git') + '/external/gitlab.com/libeigen/eigen.git' + '@' + '3564668908afc66351c1c3cc47dca2fcdb91dc12',
+    Var('chromium_git') + '/external/gitlab.com/libeigen/eigen.git' + '@' + '6156797016164b87b3e360e02d0e4107f7f66fbc',
 
   'src/third_party/emoji-metadata/src': {
     'url': Var('chromium_git') + '/external/github.com/googlefonts/emoji-metadata' + '@' + '045f146fca682a836e01cd265171312bfb300e06',
@@ -1776,7 +1776,7 @@
     Var('chromium_git') + '/external/github.com/GoogleChromeLabs/text-fragments-polyfill.git' + '@' + 'c036420683f672d685e27415de0a5f5e85bdc23f',
 
   'src/third_party/tflite/src':
-    Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + '74caf3d43b7036464e7d1fb972a8b021e6856d1f',
+    Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + 'e6ad9bf9bcd3f33783f4363984f4b24adfd8a469',
 
   'src/third_party/turbine': {
       'packages': [
@@ -1899,7 +1899,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@460aec5276861d65d3bb9fc5afb6a472badb49b2',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@1d2598a8e3ad087738cfac16dcdff3be0217c2a4',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 1bb5141..e1a48d4 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1629,6 +1629,8 @@
     "system/phonehub/phone_hub_interstitial_view.h",
     "system/phonehub/phone_hub_metrics.cc",
     "system/phonehub/phone_hub_metrics.h",
+    "system/phonehub/phone_hub_more_apps_button.cc",
+    "system/phonehub/phone_hub_more_apps_button.h",
     "system/phonehub/phone_hub_notification_controller.cc",
     "system/phonehub/phone_hub_notification_controller.h",
     "system/phonehub/phone_hub_nudge.cc",
@@ -3464,7 +3466,6 @@
     "//components/prefs:test_support",
     "//components/quirks",
     "//components/services/app_service/public/cpp:app_update",
-    "//components/services/app_service/public/mojom",
     "//components/session_manager/core",
     "//components/soda",
     "//components/sync_preferences:test_support",
diff --git a/ash/accessibility/ui/focus_ring_layer.cc b/ash/accessibility/ui/focus_ring_layer.cc
index 7fcbc4a5..6c97a9b 100644
--- a/ash/accessibility/ui/focus_ring_layer.cc
+++ b/ash/accessibility/ui/focus_ring_layer.cc
@@ -60,7 +60,7 @@
   int r = kShadowRadius;
   for (int i = 0; i < r; i++) {
     // Fade out alpha quadratically.
-    flags.setAlpha((kShadowAlpha * (r - i) * (r - i)) / (r * r));
+    flags.setAlphaf((kShadowAlpha * (r - i) * (r - i)) / (r * r) / 255.0f);
     gfx::Rect outsetRect = bounds;
     outsetRect.Inset(-i);
     recorder.canvas()->DrawRect(outsetRect, flags);
diff --git a/ash/app_list/views/ghost_image_view.cc b/ash/app_list/views/ghost_image_view.cc
index 22ee1258..a14ae8f5 100644
--- a/ash/app_list/views/ghost_image_view.cc
+++ b/ash/app_list/views/ghost_image_view.cc
@@ -78,7 +78,7 @@
   flags.setColor(DarkLightModeControllerImpl::Get()->IsDarkModeEnabled()
                      ? gfx::kGoogleGrey200
                      : gfx::kGoogleGrey900);
-  flags.setAlpha(kGhostColorOpacity);
+  flags.setAlphaf(kGhostColorOpacity / 255.0f);
   flags.setStyle(cc::PaintFlags::kStroke_Style);
   flags.setStrokeWidth(kGhostCircleStrokeWidth);
   gfx::Rect bounds = GetContentsBounds();
diff --git a/ash/app_list/views/paged_apps_grid_view.cc b/ash/app_list/views/paged_apps_grid_view.cc
index 21ddc44..6a46b4d6 100644
--- a/ash/app_list/views/paged_apps_grid_view.cc
+++ b/ash/app_list/views/paged_apps_grid_view.cc
@@ -167,7 +167,7 @@
       const bool dark_mode =
           DarkLightModeControllerImpl::Get()->IsDarkModeEnabled();
       flags.setColor(dark_mode ? SK_ColorWHITE : SK_ColorBLACK);
-      flags.setAlpha(dark_mode ? 0x29 /*16%*/ : 0x1F /*12%*/);
+      flags.setAlphaf(dark_mode ? 0.16f : 0.12f);
       flags.setStyle(cc::PaintFlags::kStroke_Style);
       flags.setStrokeWidth(kBackgroundCardBorderStrokeWidth);
       flags.setAntiAlias(true);
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index 56c691d..d78fdd6 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -1487,6 +1487,9 @@
       <message name="IDS_ASH_VIDEO_CONFERENCE_BUBBLE_PORTRAIT_RELIGHT_NAME" desc="Text for name of the portrait relight effect in the VC bubble.">
         Portrait Relighting
       </message>
+      <message name="IDS_ASH_VIDEO_CONFERENCE_TOAST_SPEAK_ON_MUTE_DETECTED" desc="A toast message that we show when user tries to speak while muted on system-level.">
+        Are you speaking? You are on mute. Learn more
+      </message>
 
       <!-- Phone Hub tray-->
       <message name="IDS_ASH_PHONE_HUB_TRAY_ACCESSIBLE_NAME" desc="The accessible name of the Phone Hub tray bubble for screen readers.">
diff --git a/ash/ash_strings_grd/IDS_ASH_VIDEO_CONFERENCE_TOAST_SPEAK_ON_MUTE_DETECTED.png.sha1 b/ash/ash_strings_grd/IDS_ASH_VIDEO_CONFERENCE_TOAST_SPEAK_ON_MUTE_DETECTED.png.sha1
new file mode 100644
index 0000000..4fc985f
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_VIDEO_CONFERENCE_TOAST_SPEAK_ON_MUTE_DETECTED.png.sha1
@@ -0,0 +1 @@
+0f23ba722725e7528fe3f608f9a3dfe6de45d5ea
\ No newline at end of file
diff --git a/ash/assistant/ui/logo_view/logo_view_impl.cc b/ash/assistant/ui/logo_view/logo_view_impl.cc
index 78a87c5..60eaea2c 100644
--- a/ash/assistant/ui/logo_view/logo_view_impl.cc
+++ b/ash/assistant/ui/logo_view/logo_view_impl.cc
@@ -28,10 +28,6 @@
   return (timestamp - base::TimeTicks()).InMilliseconds();
 }
 
-int32_t GetLogoAlpha(const LogoViewImpl::Logo& logo) {
-  return logo.GetAlpha() * 255;
-}
-
 }  // namespace
 
 LogoViewImpl::LogoViewImpl()
@@ -148,7 +144,7 @@
   cc::PaintFlags paint_flags;
   paint_flags.setAntiAlias(true);
   paint_flags.setColor(color);
-  paint_flags.setAlpha(GetLogoAlpha(logo_));
+  paint_flags.setAlphaf(logo_.GetAlpha());
   paint_flags.setStyle(cc::PaintFlags::kStroke_Style);
   paint_flags.setStrokeCap(shape->cap());
 
@@ -164,7 +160,7 @@
   cc::PaintFlags paint_flags;
   paint_flags.setAntiAlias(true);
   paint_flags.setColor(dot->color());
-  paint_flags.setAlpha(GetLogoAlpha(logo_));
+  paint_flags.setAlphaf(logo_.GetAlpha());
   paint_flags.setStrokeWidth(stroke_width);
   paint_flags.setStyle(cc::PaintFlags::kStroke_Style);
   paint_flags.setStrokeCap(cc::PaintFlags::kRound_Cap);
@@ -182,7 +178,7 @@
   cc::PaintFlags paint_flags;
   paint_flags.setAntiAlias(true);
   paint_flags.setColor(dot->color());
-  paint_flags.setAlpha(GetLogoAlpha(logo_));
+  paint_flags.setAlphaf(logo_.GetAlpha());
   paint_flags.setStyle(cc::PaintFlags::kFill_Style);
   canvas->DrawCircle(gfx::PointF(x * dots_scale_, y * dots_scale_),
                      radius * dots_scale_, paint_flags);
diff --git a/ash/components/arc/mojom/BUILD.gn b/ash/components/arc/mojom/BUILD.gn
index d1b0be7..37dfd71 100644
--- a/ash/components/arc/mojom/BUILD.gn
+++ b/ash/components/arc/mojom/BUILD.gn
@@ -22,7 +22,6 @@
     "bluetooth.mojom",
     "boot_phase_monitor.mojom",
     "camera.mojom",
-    "cert_store.mojom",
     "clipboard.mojom",
     "compatibility_mode.mojom",
     "crash_collector.mojom",
diff --git a/ash/components/arc/mojom/arc_bridge.mojom b/ash/components/arc/mojom/arc_bridge.mojom
index cf122023..25eae9d 100644
--- a/ash/components/arc/mojom/arc_bridge.mojom
+++ b/ash/components/arc/mojom/arc_bridge.mojom
@@ -15,7 +15,6 @@
 import "ash/components/arc/mojom/bluetooth.mojom";
 import "ash/components/arc/mojom/boot_phase_monitor.mojom";
 import "ash/components/arc/mojom/camera.mojom";
-import "ash/components/arc/mojom/cert_store.mojom";
 import "ash/components/arc/mojom/clipboard.mojom";
 import "ash/components/arc/mojom/compatibility_mode.mojom";
 import "ash/components/arc/mojom/crash_collector.mojom";
@@ -64,7 +63,7 @@
 import "ash/components/arc/mojom/webapk.mojom";
 
 // Next MinVersion: 63
-// Deprecated method IDs: 101, 105, 121, 132, 154, 160
+// Deprecated method IDs: 101, 105, 121, 132, 136, 153, 154, 160
 // Next method ID: 168
 interface ArcBridgeHost {
   // Keep the entries alphabetical. In order to do so without breaking
@@ -114,10 +113,6 @@
   [MinVersion=46] OnCameraInstanceReady@151(
       pending_remote<CameraInstance> instance_remote);
 
-  // Notifies Chrome that the CertStoreInstance interface is ready.
-  [MinVersion=31] OnCertStoreInstanceReady@136(
-      pending_remote<CertStoreInstance> instance_remote);
-
   // Notifies Chrome that the ClipboardInstance interface is ready.
   [MinVersion=2] OnClipboardInstanceReady@109(
       pending_remote<ClipboardInstance> instance_remote);
@@ -256,10 +251,6 @@
   [MinVersion=52] OnSharesheetInstanceReady@157(
       pending_remote<SharesheetInstance> instance_remote);
 
-  // Notifies Chrome that the SmartCardManagerInstance interface is ready.
-  [MinVersion=48] OnSmartCardManagerInstanceReady@153(
-      pending_remote<SmartCardManagerInstance> instance_remote);
-
   // Notifies Chrome that the StorageManagerInstance interface is ready.
   [MinVersion=12] OnStorageManagerInstanceReady@118(
       pending_remote<StorageManagerInstance> instance_remote);
diff --git a/ash/components/arc/mojom/cert_store.mojom b/ash/components/arc/mojom/cert_store.mojom
deleted file mode 100644
index 795ceb8..0000000
--- a/ash/components/arc/mojom/cert_store.mojom
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2017 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Next MinVersion: 2
-
-//
-// CertStoreHost is modeled after Android keymaster interface
-// hardware/libhardware/include/hardware/keymaster2.h
-//
-// and must follow the concept if extended in the future.
-// Please keep names in sync as far as it is possible.
-//
-// Enums/structures are modeled after structures from
-// hardware/libhardware/include/hardware/keymaster_defs.h
-//
-
-module arc.mojom;
-
-// Describes a keymaster operation result.
-[Extensible]
-enum KeymasterError {
-  ERROR_OK = 0,
-  ERROR_INVALID_OPERATION_HANDLE = -28,
-  ERROR_INVALID_KEY_BLOB = -33,
-  ERROR_UNIMPLEMENTED = -100,
-  ERROR_UNKNOWN_ERROR = -1000,
-};
-
-// Enumerates the crypto algorithms supported by Host.
-[Extensible]
-enum Algorithm {
-  ALGORITHM_RSA = 1,
-  ALGORITHM_EC = 3,
-};
-
-// Enumerates the digests supported by Host.
-[Extensible]
-enum Digest {
-  DIGEST_NONE = 0,
-  DIGEST_SHA1 = 2,
-  DIGEST_SHA_2_224 = 3,
-  DIGEST_SHA_2_256 = 4,
-  DIGEST_SHA_2_384 = 5,
-  DIGEST_SHA_2_512 = 6,
-};
-
-// Enumerates the paddings supported by Host.
-[Extensible]
-enum Padding {
-  PAD_NONE = 1,
-  PAD_RSA_PKCS1_1_5_SIGN = 5,
-};
-
-// Describes a parameter of client certificate provided by Host.
-union KeyParam {
-  Algorithm algorithm;
-  Digest digest;
-  Padding padding;
-};
-
-// Describes a client certificate provided by Host.
-// Does not correspond to keymaster type.
-struct Certificate {
-  // Nickname/alias of the certificate.
-  string alias;
-
-  // PEM-encoded client certificate.
-  string cert;
-};
-
-// Next method ID: 6
-// The interface is modeled after keymaster interface and must follow the format
-// if extended in the future.
-interface CertStoreHost {
-  // The helper method, which does not correspond to keymaster interface.
-  // It returns a list of Chrome OS corporate usage client certificates if
-  // any Android app is allowlisted to use them, otherwise returns an
-  // empty list.
-  ListCertificates@0() => (array<Certificate> certs);
-
-  // Retrieves key characteristics for the specified key with alias.
-  // params is null if any error occurred during retrieval.
-  GetKeyCharacteristics@1(string alias)
-      => (KeymasterError error, array<KeyParam>? params);
-
-  // Begins the operation using the specified key with alias and operation
-  // parameters (such as algorithm, digest, padding).
-  // If all is well, returns ERROR_OK and creates an operation handle which
-  // must be passed to subsequent calls to Update(), Finish() or Abort().
-  // Currently only signature operations are supported.
-  Begin@2(string alias, array<KeyParam> params)
-      => (KeymasterError error, uint64 operation_handle);
-
-  // Provides data to an ongoing cryptographic operation begun with Begin().
-  // Returns an amount of data consumed by Update().
-  Update@3(uint64 operation_handle, array<uint8> data)
-      => (KeymasterError error, uint32 input_consumed);
-
-  // Finalizes a cryptographic operation begun with Begin() and invalidates
-  // operation handle. Retrieves the result (signature). In case of any error,
-  // signed_data is null.
-  Finish@4(uint64 operation_handle)
-      => (KeymasterError error, array<uint8>? signed_data);
-
-  // Aborts a cryptographic operation begun with Begin(), freeing all internal
-  // resources and invalidating operation handle.
-  Abort@5(uint64 operation_handle) => (KeymasterError error);
-};
-
-// Deprecated method IDs: 0
-// Next method ID: 4
-interface CertStoreInstance {
-  // Establishes full-duplex communication with the host.
-  [MinVersion=1] Init@3(pending_remote<CertStoreHost> host_remote) => ();
-
-  // Informs the key permissions are changed: only listed packages are allowed
-  // to use exposed certificates.
-  OnKeyPermissionsChanged@1(array<string> permissions);
-
-  // Informs the certificates are changed (added, removed or updated):
-  // CertStoreInstance must call ListCertficates to update its database.
-  OnCertificatesChanged@2();
-};
-
-// Next method ID: 1
-interface SmartCardManagerHost {
-  // Refreshes smart card certificates available to Android apps.
-  Refresh@0() => (bool result);
-};
-
-// Next method ID: 1
-interface SmartCardManagerInstance {
-  // Establishes full-duplex communication with the host.
-  Init@0(pending_remote<SmartCardManagerHost> host_remote) => ();
-};
diff --git a/ash/components/arc/session/arc_bridge_host_impl.cc b/ash/components/arc/session/arc_bridge_host_impl.cc
index 15b5b0d..9e9a76c4 100644
--- a/ash/components/arc/session/arc_bridge_host_impl.cc
+++ b/ash/components/arc/session/arc_bridge_host_impl.cc
@@ -152,12 +152,6 @@
   OnInstanceReady(arc_bridge_service_->camera(), std::move(camera_remote));
 }
 
-void ArcBridgeHostImpl::OnCertStoreInstanceReady(
-    mojo::PendingRemote<mojom::CertStoreInstance> instance_remote) {
-  OnInstanceReady(arc_bridge_service_->cert_store(),
-                  std::move(instance_remote));
-}
-
 void ArcBridgeHostImpl::OnClipboardInstanceReady(
     mojo::PendingRemote<mojom::ClipboardInstance> clipboard_remote) {
   OnInstanceReady(arc_bridge_service_->clipboard(),
@@ -371,13 +365,6 @@
                   std::move(sharesheet_remote));
 }
 
-void ArcBridgeHostImpl::OnSmartCardManagerInstanceReady(
-    mojo::PendingRemote<mojom::SmartCardManagerInstance>
-        smart_card_manager_remote) {
-  OnInstanceReady(arc_bridge_service_->smart_card_manager(),
-                  std::move(smart_card_manager_remote));
-}
-
 void ArcBridgeHostImpl::OnStorageManagerInstanceReady(
     mojo::PendingRemote<mojom::StorageManagerInstance> storage_manager_remote) {
   OnInstanceReady(arc_bridge_service_->storage_manager(),
diff --git a/ash/components/arc/session/arc_bridge_host_impl.h b/ash/components/arc/session/arc_bridge_host_impl.h
index 3b794710..3fe2f94a 100644
--- a/ash/components/arc/session/arc_bridge_host_impl.h
+++ b/ash/components/arc/session/arc_bridge_host_impl.h
@@ -69,8 +69,6 @@
           boot_phase_monitor_remote) override;
   void OnCameraInstanceReady(
       mojo::PendingRemote<mojom::CameraInstance> camera_remote) override;
-  void OnCertStoreInstanceReady(
-      mojo::PendingRemote<mojom::CertStoreInstance> instance_remote) override;
   void OnClipboardInstanceReady(
       mojo::PendingRemote<mojom::ClipboardInstance> clipboard_remote) override;
   void OnCompatibilityModeInstanceReady(
@@ -155,9 +153,6 @@
       override;
   void OnSharesheetInstanceReady(mojo::PendingRemote<mojom::SharesheetInstance>
                                      sharesheet_remote) override;
-  void OnSmartCardManagerInstanceReady(
-      mojo::PendingRemote<mojom::SmartCardManagerInstance>
-          smart_card_manager_remote) override;
   void OnStorageManagerInstanceReady(
       mojo::PendingRemote<mojom::StorageManagerInstance> storage_manager_remote)
       override;
diff --git a/ash/components/arc/session/arc_bridge_host_impl_unittest.cc b/ash/components/arc/session/arc_bridge_host_impl_unittest.cc
index 5052f0b..c3aef4f7 100644
--- a/ash/components/arc/session/arc_bridge_host_impl_unittest.cc
+++ b/ash/components/arc/session/arc_bridge_host_impl_unittest.cc
@@ -118,7 +118,6 @@
     MAKE_INSTANCE_READY(Bluetooth);
     MAKE_INSTANCE_READY(BootPhaseMonitor);
     MAKE_INSTANCE_READY(Camera);
-    MAKE_INSTANCE_READY(CertStore);
     MAKE_INSTANCE_READY(Clipboard);
     MAKE_INSTANCE_READY(CompatibilityMode);
     MAKE_INSTANCE_READY(CrashCollector);
@@ -153,7 +152,6 @@
     MAKE_INSTANCE_READY(RotationLock);
     MAKE_INSTANCE_READY(ScreenCapture);
     MAKE_INSTANCE_READY(Sharesheet);
-    MAKE_INSTANCE_READY(SmartCardManager);
     MAKE_INSTANCE_READY(StorageManager);
     MAKE_INSTANCE_READY(Timer);
     MAKE_INSTANCE_READY(Tracing);
diff --git a/ash/components/arc/session/arc_bridge_service.cc b/ash/components/arc/session/arc_bridge_service.cc
index ee58c6c..587bbc60 100644
--- a/ash/components/arc/session/arc_bridge_service.cc
+++ b/ash/components/arc/session/arc_bridge_service.cc
@@ -17,7 +17,6 @@
 #include "ash/components/arc/mojom/bluetooth.mojom.h"
 #include "ash/components/arc/mojom/boot_phase_monitor.mojom.h"
 #include "ash/components/arc/mojom/camera.mojom.h"
-#include "ash/components/arc/mojom/cert_store.mojom.h"
 #include "ash/components/arc/mojom/clipboard.mojom.h"
 #include "ash/components/arc/mojom/crash_collector.mojom.h"
 #include "ash/components/arc/mojom/digital_goods.mojom.h"
diff --git a/ash/components/arc/session/arc_bridge_service.h b/ash/components/arc/session/arc_bridge_service.h
index 2c9fba5a..8661e2a 100644
--- a/ash/components/arc/session/arc_bridge_service.h
+++ b/ash/components/arc/session/arc_bridge_service.h
@@ -35,8 +35,6 @@
 class CameraHost;
 class CameraInstance;
 class CastReceiverInstance;
-class CertStoreHost;
-class CertStoreInstance;
 class ClipboardHost;
 class ClipboardInstance;
 class CompatibilityModeInstance;
@@ -96,8 +94,6 @@
 class ScreenCaptureInstance;
 class SharesheetHost;
 class SharesheetInstance;
-class SmartCardManagerHost;
-class SmartCardManagerInstance;
 class StorageManagerInstance;
 class SystemUiInstance;
 class TimerHost;
@@ -190,10 +186,6 @@
   ConnectionHolder<mojom::CastReceiverInstance>* cast_receiver() {
     return &cast_receiver_;
   }
-  ConnectionHolder<mojom::CertStoreInstance, mojom::CertStoreHost>*
-  cert_store() {
-    return &cert_store_;
-  }
   ConnectionHolder<mojom::ClipboardInstance, mojom::ClipboardHost>*
   clipboard() {
     return &clipboard_;
@@ -304,11 +296,6 @@
   sharesheet() {
     return &sharesheet_;
   }
-  ConnectionHolder<mojom::SmartCardManagerInstance,
-                   mojom::SmartCardManagerHost>*
-  smart_card_manager() {
-    return &smart_card_manager_;
-  }
 
   ConnectionHolder<mojom::StorageManagerInstance>* storage_manager() {
     return &storage_manager_;
@@ -357,7 +344,6 @@
       boot_phase_monitor_;
   ConnectionHolder<mojom::CameraInstance, mojom::CameraHost> camera_;
   ConnectionHolder<mojom::CastReceiverInstance> cast_receiver_;
-  ConnectionHolder<mojom::CertStoreInstance, mojom::CertStoreHost> cert_store_;
   ConnectionHolder<mojom::ClipboardInstance, mojom::ClipboardHost> clipboard_;
   ConnectionHolder<mojom::CompatibilityModeInstance> compatibility_mode_;
   ConnectionHolder<mojom::CrashCollectorInstance, mojom::CrashCollectorHost>
@@ -406,8 +392,6 @@
       screen_capture_;
   ConnectionHolder<mojom::SharesheetInstance, mojom::SharesheetHost>
       sharesheet_;
-  ConnectionHolder<mojom::SmartCardManagerInstance, mojom::SmartCardManagerHost>
-      smart_card_manager_;
   ConnectionHolder<mojom::StorageManagerInstance> storage_manager_;
   ConnectionHolder<mojom::SystemUiInstance> system_ui_;
   ConnectionHolder<mojom::TimerInstance, mojom::TimerHost> timer_;
diff --git a/ash/components/arc/test/fake_arc_bridge_host.cc b/ash/components/arc/test/fake_arc_bridge_host.cc
index bdfe59e..883b8e2 100644
--- a/ash/components/arc/test/fake_arc_bridge_host.cc
+++ b/ash/components/arc/test/fake_arc_bridge_host.cc
@@ -16,7 +16,6 @@
 #include "ash/components/arc/mojom/bluetooth.mojom.h"
 #include "ash/components/arc/mojom/boot_phase_monitor.mojom.h"
 #include "ash/components/arc/mojom/camera.mojom.h"
-#include "ash/components/arc/mojom/cert_store.mojom.h"
 #include "ash/components/arc/mojom/clipboard.mojom.h"
 #include "ash/components/arc/mojom/compatibility_mode.mojom.h"
 #include "ash/components/arc/mojom/crash_collector.mojom.h"
@@ -103,9 +102,6 @@
 void FakeArcBridgeHost::OnCameraInstanceReady(
     mojo::PendingRemote<mojom::CameraInstance> camera_remote) {}
 
-void FakeArcBridgeHost::OnCertStoreInstanceReady(
-    mojo::PendingRemote<mojom::CertStoreInstance> instance_remote) {}
-
 void FakeArcBridgeHost::OnClipboardInstanceReady(
     mojo::PendingRemote<mojom::ClipboardInstance> clipboard_remote) {}
 
@@ -216,10 +212,6 @@
 void FakeArcBridgeHost::OnSharesheetInstanceReady(
     mojo::PendingRemote<mojom::SharesheetInstance> sharesheet_remote) {}
 
-void FakeArcBridgeHost::OnSmartCardManagerInstanceReady(
-    mojo::PendingRemote<mojom::SmartCardManagerInstance>
-        smart_cardManager_remote) {}
-
 void FakeArcBridgeHost::OnStorageManagerInstanceReady(
     mojo::PendingRemote<mojom::StorageManagerInstance> storage_manager_remote) {
 }
diff --git a/ash/components/arc/test/fake_arc_bridge_host.h b/ash/components/arc/test/fake_arc_bridge_host.h
index fb92ad2f..e238bb87 100644
--- a/ash/components/arc/test/fake_arc_bridge_host.h
+++ b/ash/components/arc/test/fake_arc_bridge_host.h
@@ -47,8 +47,6 @@
           boot_phase_monitor_remote) override;
   void OnCameraInstanceReady(
       mojo::PendingRemote<mojom::CameraInstance> camera_remote) override;
-  void OnCertStoreInstanceReady(
-      mojo::PendingRemote<mojom::CertStoreInstance> instance_remote) override;
   void OnClipboardInstanceReady(
       mojo::PendingRemote<mojom::ClipboardInstance> clipboard_remote) override;
   void OnCompatibilityModeInstanceReady(
@@ -133,9 +131,6 @@
       override;
   void OnSharesheetInstanceReady(mojo::PendingRemote<mojom::SharesheetInstance>
                                      sharesheet_remote) override;
-  void OnSmartCardManagerInstanceReady(
-      mojo::PendingRemote<mojom::SmartCardManagerInstance>
-          smart_card_manager_remote) override;
   void OnStorageManagerInstanceReady(
       mojo::PendingRemote<mojom::StorageManagerInstance> storage_manager_remote)
       override;
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 9a9940e..4acc0ad 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -877,6 +877,11 @@
 // Enables the Fast Pair feature.
 BASE_FEATURE(kFastPair, "FastPair", base::FEATURE_DISABLED_BY_DEFAULT);
 
+// Enables using new Handshake retry logic for Fast Pair.
+BASE_FEATURE(kFastPairHandshakeRefactor,
+             "FastPairHandshakeRefactor",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 // The amount of minutes we should wait before allowing notifications for a
 // recently lost device.
 const base::FeatureParam<double> kFastPairDeviceLostNotificationTimeoutMinutes{
@@ -1229,6 +1234,9 @@
              "InternalServerSideSpeechRecognition",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+// Enables sending `client-info` values to IPP printers on ChromeOS.
+BASE_FEATURE(kIppClientInfo, "IppClientInfo", base::FEATURE_ENABLED_BY_DEFAULT);
+
 // Enables Jelly features.
 BASE_FEATURE(kJelly, "Jelly", base::FEATURE_DISABLED_BY_DEFAULT);
 
@@ -2548,6 +2556,10 @@
   return base::FeatureList::IsEnabled(kFastPair);
 }
 
+bool IsFastPairHandshakeRefactorEnabled() {
+  return base::FeatureList::IsEnabled(kFastPairHandshakeRefactor);
+}
+
 bool IsFastPairLowPowerEnabled() {
   return base::FeatureList::IsEnabled(kFastPairLowPower);
 }
@@ -2713,6 +2725,10 @@
 #endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
 }
 
+bool IsIppClientInfoEnabled() {
+  return base::FeatureList::IsEnabled(kIppClientInfo);
+}
+
 bool IsJellyEnabled() {
   return base::FeatureList::IsEnabled(kJelly);
 }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index 7161c87..debcb08 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -260,6 +260,8 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kFamilyLinkOnSchoolDevice);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kFastPair);
 COMPONENT_EXPORT(ASH_CONSTANTS)
+BASE_DECLARE_FEATURE(kFastPairHandshakeRefactor);
+COMPONENT_EXPORT(ASH_CONSTANTS)
 BASE_DECLARE_FEATURE(kFastPairPreventNotificationsForRecentlyLostDevice);
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::FeatureParam<double>
@@ -357,6 +359,7 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kInstantTethering);
 COMPONENT_EXPORT(ASH_CONSTANTS)
 BASE_DECLARE_FEATURE(kInternalServerSideSpeechRecognition);
+COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kIppClientInfo);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kJelly);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kJellyroll);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kKioskEnableImeButton);
@@ -696,6 +699,7 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFaceMLSwaEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFamilyLinkOnSchoolDeviceEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFastPairEnabled();
+COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFastPairHandshakeRefactorEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFastPairLowPowerEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS)
 bool IsFastPairPreventNotificationsForRecentlyLostDeviceEnabled();
@@ -737,6 +741,7 @@
 bool IsInstantTetheringBackgroundAdvertisingSupported();
 COMPONENT_EXPORT(ASH_CONSTANTS)
 bool IsInternalServerSideSpeechRecognitionEnabled();
+COMPONENT_EXPORT(ASH_CONSTANTS) bool IsIppClientInfoEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsJellyEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsJellyrollEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS)
diff --git a/ash/constants/notifier_catalogs.h b/ash/constants/notifier_catalogs.h
index 741522f..434a2f7 100644
--- a/ash/constants/notifier_catalogs.h
+++ b/ash/constants/notifier_catalogs.h
@@ -242,7 +242,8 @@
   kEcheTrayTabletModeNotSupported = 38,
   kNotificationCenterTrayNoNotifications = 39,
   kCopyToClipboardAction = 40,
-  kMaxValue = kCopyToClipboardAction,
+  kVideoConferenceTraySpeakOnMuteDetected = 41,
+  kMaxValue = kVideoConferenceTraySpeakOnMuteDetected,
 };
 
 }  // namespace ash
diff --git a/ash/public/cpp/wallpaper/wallpaper_controller.h b/ash/public/cpp/wallpaper/wallpaper_controller.h
index e242dd67..f1f1fd73 100644
--- a/ash/public/cpp/wallpaper/wallpaper_controller.h
+++ b/ash/public/cpp/wallpaper/wallpaper_controller.h
@@ -7,7 +7,6 @@
 
 #include <cstdint>
 #include <string>
-#include <vector>
 
 #include "ash/public/cpp/ash_public_export.h"
 #include "ash/public/cpp/wallpaper/google_photos_wallpaper_params.h"
@@ -273,14 +272,6 @@
   // |account_id|: The user's account id.
   virtual void RemovePolicyWallpaper(const AccountId& account_id) = 0;
 
-  // Returns the urls of the wallpapers that exist in local file system (i.e.
-  // |SetOnlineWallpaper| was called earlier). The url is used as id
-  // to identify which wallpapers are available to be set offline.
-  using GetOfflineWallpaperListCallback =
-      base::OnceCallback<void(const std::vector<std::string>&)>;
-  virtual void GetOfflineWallpaperList(
-      GetOfflineWallpaperListCallback callback) = 0;
-
   // Sets wallpaper animation duration. Passing an empty value disables the
   // animation.
   virtual void SetAnimationDuration(base::TimeDelta animation_duration) = 0;
diff --git a/ash/quick_pair/pairing/pairer_broker_impl.cc b/ash/quick_pair/pairing/pairer_broker_impl.cc
index 3d54198..d726b0e 100644
--- a/ash/quick_pair/pairing/pairer_broker_impl.cc
+++ b/ash/quick_pair/pairing/pairer_broker_impl.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "ash/constants/ash_features.h"
 #include "ash/quick_pair/common/account_key_failure.h"
 #include "ash/quick_pair/common/device.h"
 #include "ash/quick_pair/common/fast_pair/fast_pair_metrics.h"
@@ -33,6 +34,10 @@
 // Pair implementation.
 constexpr base::TimeDelta kCancelPairingRetryDelay = base::Seconds(1);
 
+// 1s delay after handshake failure to allow failed handshake to tear down.
+// TODO(b/265311455): implement handshake factory to handle retry logic.
+constexpr base::TimeDelta kRetryHandshakeDelay = base::Seconds(1);
+
 }  // namespace
 
 namespace ash {
@@ -187,7 +192,17 @@
                                           PairFailure failure) {
   if (num_handshake_attempts_[device->ble_address()] <
       kMaxNumHandshakeAttempts) {
-    CreateHandshake(device);
+    if (ash::features::IsFastPairHandshakeRefactorEnabled()) {
+      // Directly calling CreateHandshake() from here will cause the new
+      // handshake to be nested inside the failed handshake. Use a timer to give
+      // the failed handshake time to cleanup and avoid nesting.
+      retry_handshake_timer_.Start(
+          FROM_HERE, kRetryHandshakeDelay,
+          base::BindOnce(&PairerBrokerImpl::CreateHandshake,
+                         weak_pointer_factory_.GetWeakPtr(), device));
+    } else {
+      CreateHandshake(device);
+    }
     return;
   }
 
@@ -287,7 +302,7 @@
     cancel_pairing_timer_.Start(
         FROM_HERE, kCancelPairingRetryDelay,
         base::BindOnce(&PairerBrokerImpl::PairFastPairDevice,
-                       base::Unretained(this), device));
+                       weak_pointer_factory_.GetWeakPtr(), device));
 
     return;
   }
diff --git a/ash/quick_pair/pairing/pairer_broker_impl.h b/ash/quick_pair/pairing/pairer_broker_impl.h
index 6c07570..625daad 100644
--- a/ash/quick_pair/pairing/pairer_broker_impl.h
+++ b/ash/quick_pair/pairing/pairer_broker_impl.h
@@ -82,6 +82,8 @@
   // Timer to provide a delay after cancelling pairing.
   base::OneShotTimer cancel_pairing_timer_;
 
+  base::OneShotTimer retry_handshake_timer_;
+
   base::WeakPtrFactory<PairerBrokerImpl> weak_pointer_factory_{this};
 };
 
diff --git a/ash/quick_pair/pairing/pairer_broker_impl_unittest.cc b/ash/quick_pair/pairing/pairer_broker_impl_unittest.cc
index c95374d..c94a8553 100644
--- a/ash/quick_pair/pairing/pairer_broker_impl_unittest.cc
+++ b/ash/quick_pair/pairing/pairer_broker_impl_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "ash/quick_pair/pairing/pairer_broker_impl.h"
+#include "ash/constants/ash_features.h"
 #include "ash/quick_pair/common/account_key_failure.h"
 #include "ash/quick_pair/common/device.h"
 #include "ash/quick_pair/common/fake_bluetooth_adapter.h"
@@ -26,6 +27,7 @@
 #include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/mock_callback.h"
+#include "base/test/scoped_feature_list.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
@@ -38,6 +40,7 @@
 constexpr char kDeviceName[] = "test_device_name";
 constexpr char kBluetoothCanonicalizedAddress[] = "0C:0E:4C:C8:05:08";
 constexpr base::TimeDelta kCancelPairingRetryDelay = base::Seconds(1);
+constexpr base::TimeDelta kRetryHandshakeDelay = base::Seconds(1);
 
 const char kFastPairRetryCountMetricName[] =
     "Bluetooth.ChromeOS.FastPair.PairRetry.Count";
@@ -703,6 +706,117 @@
             1);
 }
 
+TEST_F(PairerBrokerImplTest,
+       PairAfterTwoHandshakeFailuresWithHandshakeRefactor_Initial) {
+  base::test::ScopedFeatureList feature_list{
+      ash::features::kFastPairHandshakeRefactor};
+
+  histogram_tester_.ExpectTotalCount(kHandshakeEffectiveSuccessRate, 0);
+  histogram_tester_.ExpectTotalCount(kHandshakeAttemptCount, 0);
+
+  CreateMockDevice(DeviceFastPairVersion::kHigherThanV1,
+                   /*protocol=*/Protocol::kFastPairInitial);
+  pairer_broker_->PairDevice(device_);
+  fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection);
+
+  // Fast forward |kRetryHandshakeDelay| seconds to allow the retry
+  // CreateHandshake() to be called.
+  task_environment()->FastForwardBy(kRetryHandshakeDelay);
+  fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection);
+
+  // Fast forward |kRetryHandshakeDelay| seconds to allow the retry
+  // CreateHandshake() to be called.
+  task_environment()->FastForwardBy(kRetryHandshakeDelay);
+  fake_fast_pair_handshake_->InvokeCallback();
+  EXPECT_TRUE(pairer_broker_->IsPairing());
+
+  fast_pair_pairer_factory_->fake_fast_pair_pairer()->TriggerPairedCallback();
+
+  EXPECT_EQ(device_paired_count_, 1);
+  EXPECT_EQ(pair_failure_count_, 0);
+  histogram_tester_.ExpectTotalCount(kHandshakeEffectiveSuccessRate, 1);
+  histogram_tester_.ExpectTotalCount(kHandshakeAttemptCount, 1);
+  histogram_tester_.ExpectBucketCount(kHandshakeAttemptCount, 3, 1);
+
+  fast_pair_pairer_factory_->fake_fast_pair_pairer()
+      ->TriggerPairingProcedureCompleteCallback();
+  EXPECT_FALSE(pairer_broker_->IsPairing());
+}
+
+TEST_F(PairerBrokerImplTest,
+       PairAfterTwoHandshakeFailuresWithHandshakeRefactor_Subsequent) {
+  base::test::ScopedFeatureList feature_list{
+      ash::features::kFastPairHandshakeRefactor};
+
+  histogram_tester_.ExpectTotalCount(kHandshakeEffectiveSuccessRate, 0);
+  histogram_tester_.ExpectTotalCount(kHandshakeAttemptCount, 0);
+
+  CreateMockDevice(DeviceFastPairVersion::kHigherThanV1,
+                   /*protocol=*/Protocol::kFastPairSubsequent);
+  pairer_broker_->PairDevice(device_);
+  fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection);
+
+  // Fast forward |kRetryHandshakeDelay| seconds to allow the retry
+  // CreateHandshake() to be called.
+  task_environment()->FastForwardBy(kRetryHandshakeDelay);
+  fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection);
+
+  // Fast forward |kRetryHandshakeDelay| seconds to allow the retry
+  // CreateHandshake() to be called.
+  task_environment()->FastForwardBy(kRetryHandshakeDelay);
+  fake_fast_pair_handshake_->InvokeCallback();
+  EXPECT_TRUE(pairer_broker_->IsPairing());
+
+  fast_pair_pairer_factory_->fake_fast_pair_pairer()->TriggerPairedCallback();
+
+  EXPECT_EQ(device_paired_count_, 1);
+  EXPECT_EQ(pair_failure_count_, 0);
+  histogram_tester_.ExpectTotalCount(kHandshakeEffectiveSuccessRate, 1);
+  histogram_tester_.ExpectTotalCount(kHandshakeAttemptCount, 1);
+  histogram_tester_.ExpectBucketCount(kHandshakeAttemptCount, 3, 1);
+
+  fast_pair_pairer_factory_->fake_fast_pair_pairer()
+      ->TriggerPairingProcedureCompleteCallback();
+  EXPECT_FALSE(pairer_broker_->IsPairing());
+}
+
+TEST_F(PairerBrokerImplTest,
+       PairAfterTwoHandshakeFailuresWithHandshakeRefactor_Retroactive) {
+  base::test::ScopedFeatureList feature_list{
+      ash::features::kFastPairHandshakeRefactor};
+
+  histogram_tester_.ExpectTotalCount(kHandshakeEffectiveSuccessRate, 0);
+  histogram_tester_.ExpectTotalCount(kHandshakeAttemptCount, 0);
+
+  CreateMockDevice(DeviceFastPairVersion::kHigherThanV1,
+                   /*protocol=*/Protocol::kFastPairRetroactive);
+  pairer_broker_->PairDevice(device_);
+  fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection);
+
+  // Fast forward |kRetryHandshakeDelay| seconds to allow the retry
+  // CreateHandshake() to be called.
+  task_environment()->FastForwardBy(kRetryHandshakeDelay);
+  fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection);
+
+  // Fast forward |kRetryHandshakeDelay| seconds to allow the retry
+  // CreateHandshake() to be called.
+  task_environment()->FastForwardBy(kRetryHandshakeDelay);
+  fake_fast_pair_handshake_->InvokeCallback();
+  EXPECT_TRUE(pairer_broker_->IsPairing());
+
+  fast_pair_pairer_factory_->fake_fast_pair_pairer()->TriggerPairedCallback();
+
+  EXPECT_EQ(device_paired_count_, 1);
+  EXPECT_EQ(pair_failure_count_, 0);
+  histogram_tester_.ExpectTotalCount(kHandshakeEffectiveSuccessRate, 1);
+  histogram_tester_.ExpectTotalCount(kHandshakeAttemptCount, 1);
+  histogram_tester_.ExpectBucketCount(kHandshakeAttemptCount, 3, 1);
+
+  fast_pair_pairer_factory_->fake_fast_pair_pairer()
+      ->TriggerPairingProcedureCompleteCallback();
+  EXPECT_FALSE(pairer_broker_->IsPairing());
+}
+
 TEST_F(PairerBrokerImplTest, PairAfterTwoHandshakeFailures_Initial) {
   histogram_tester_.ExpectTotalCount(kHandshakeEffectiveSuccessRate, 0);
   histogram_tester_.ExpectTotalCount(kHandshakeAttemptCount, 0);
@@ -721,6 +835,7 @@
   EXPECT_EQ(pair_failure_count_, 0);
   histogram_tester_.ExpectTotalCount(kHandshakeEffectiveSuccessRate, 1);
   histogram_tester_.ExpectTotalCount(kHandshakeAttemptCount, 1);
+  histogram_tester_.ExpectBucketCount(kHandshakeAttemptCount, 3, 1);
 
   fast_pair_pairer_factory_->fake_fast_pair_pairer()
       ->TriggerPairingProcedureCompleteCallback();
@@ -745,6 +860,7 @@
   EXPECT_EQ(pair_failure_count_, 0);
   histogram_tester_.ExpectTotalCount(kHandshakeEffectiveSuccessRate, 1);
   histogram_tester_.ExpectTotalCount(kHandshakeAttemptCount, 1);
+  histogram_tester_.ExpectBucketCount(kHandshakeAttemptCount, 3, 1);
 
   fast_pair_pairer_factory_->fake_fast_pair_pairer()
       ->TriggerPairingProcedureCompleteCallback();
@@ -769,6 +885,7 @@
   EXPECT_EQ(pair_failure_count_, 0);
   histogram_tester_.ExpectTotalCount(kHandshakeEffectiveSuccessRate, 1);
   histogram_tester_.ExpectTotalCount(kHandshakeAttemptCount, 1);
+  histogram_tester_.ExpectBucketCount(kHandshakeAttemptCount, 3, 1);
 
   fast_pair_pairer_factory_->fake_fast_pair_pairer()
       ->TriggerPairingProcedureCompleteCallback();
diff --git a/ash/quick_pair/repository/fast_pair/saved_device_registry.cc b/ash/quick_pair/repository/fast_pair/saved_device_registry.cc
index b82fc61..85c28e7 100644
--- a/ash/quick_pair/repository/fast_pair/saved_device_registry.cc
+++ b/ash/quick_pair/repository/fast_pair/saved_device_registry.cc
@@ -33,19 +33,22 @@
   registry->RegisterDictionaryPref(kFastPairSavedDevicesPref);
 }
 
-void SavedDeviceRegistry::SaveAccountKey(
+bool SavedDeviceRegistry::SaveAccountAssociation(
     const std::string& mac_address,
     const std::vector<uint8_t>& account_key) {
   PrefService* pref_service =
       QuickPairBrowserDelegate::Get()->GetActivePrefService();
   if (!pref_service) {
-    QP_LOG(WARNING) << __func__ << ": No user pref service available.";
-    return;
+    QP_LOG(WARNING) << __func__
+                    << ": No user pref service available. Failed to write "
+                       "account association to Saved Device Registry.";
+    return false;
   }
   std::string encoded = base::Base64Encode(account_key);
   ScopedDictPrefUpdate update(pref_service, kFastPairSavedDevicesPref);
   update->Set(mac_address, encoded);
   QP_LOG(INFO) << __func__ << ": Saved account key.";
+  return true;
 }
 
 bool SavedDeviceRegistry::DeleteAccountKey(const std::string& mac_address) {
@@ -153,8 +156,9 @@
   // cross reference the registry for any devices that need to be removed.
   std::set<std::string> paired_devices;
   for (device::BluetoothDevice* device : adapter_->GetDevices()) {
-    if (device->IsPaired())
+    if (device->IsPaired()) {
       paired_devices.insert(device->GetAddress());
+    }
   }
 
   // Iterate over the list of devices in the registry, and if there are any in
diff --git a/ash/quick_pair/repository/fast_pair/saved_device_registry.h b/ash/quick_pair/repository/fast_pair/saved_device_registry.h
index ad35004..124aff64 100644
--- a/ash/quick_pair/repository/fast_pair/saved_device_registry.h
+++ b/ash/quick_pair/repository/fast_pair/saved_device_registry.h
@@ -35,9 +35,10 @@
   // Registers preferences used by this class in the provided |registry|.
   static void RegisterProfilePrefs(PrefRegistrySimple* registry);
 
-  // Saves an account key to disk.
-  void SaveAccountKey(const std::string& mac_address,
-                      const std::vector<uint8_t>& account_key);
+  // Saves the account association (|mac_address|, |account_key|) to disk.
+  // Returns true on success, false on failure.
+  bool SaveAccountAssociation(const std::string& mac_address,
+                              const std::vector<uint8_t>& account_key);
 
   // Deletes the |mac_address| -> account key record from prefs based on
   // |mac address|. Returns true on success, false on failure.
diff --git a/ash/quick_pair/repository/fast_pair/saved_device_registry_unittest.cc b/ash/quick_pair/repository/fast_pair/saved_device_registry_unittest.cc
index 98dd663..fa07a6b 100644
--- a/ash/quick_pair/repository/fast_pair/saved_device_registry_unittest.cc
+++ b/ash/quick_pair/repository/fast_pair/saved_device_registry_unittest.cc
@@ -62,8 +62,7 @@
     ON_CALL(*browser_delegate_, GetActivePrefService())
         .WillByDefault(testing::Return(pref_service_.get()));
 
-    saved_device_registry_ =
-        std::make_unique<SavedDeviceRegistry>(adapter_);
+    saved_device_registry_ = std::make_unique<SavedDeviceRegistry>(adapter_);
     device::BluetoothAdapterFactory::SetAdapterForTesting(adapter_);
   }
 
@@ -79,8 +78,10 @@
 };
 
 TEST_F(SavedDeviceRegistryTest, ValidLookup) {
-  saved_device_registry_->SaveAccountKey(kFirstSavedMacAddress, kAccountKey1);
-  saved_device_registry_->SaveAccountKey(kSecondSavedMacAddress, kAccountKey2);
+  bool success1 = saved_device_registry_->SaveAccountAssociation(
+      kFirstSavedMacAddress, kAccountKey1);
+  bool success2 = saved_device_registry_->SaveAccountAssociation(
+      kSecondSavedMacAddress, kAccountKey2);
 
   auto first = saved_device_registry_->GetAccountKey(kFirstSavedMacAddress);
   auto second = saved_device_registry_->GetAccountKey(kSecondSavedMacAddress);
@@ -88,6 +89,9 @@
   ASSERT_EQ(kAccountKey1, *first);
   ASSERT_EQ(kAccountKey2, *second);
 
+  EXPECT_TRUE(success1);
+  EXPECT_TRUE(success2);
+
   EXPECT_TRUE(
       saved_device_registry_->IsAccountKeySavedToRegistry(kAccountKey1));
   EXPECT_TRUE(
@@ -95,7 +99,8 @@
 }
 
 TEST_F(SavedDeviceRegistryTest, InvalidLookup) {
-  saved_device_registry_->SaveAccountKey(kFirstSavedMacAddress, kAccountKey1);
+  bool success1 = saved_device_registry_->SaveAccountAssociation(
+      kFirstSavedMacAddress, kAccountKey1);
 
   auto invalid_result =
       saved_device_registry_->GetAccountKey(kNotSavedMacAddress);
@@ -103,6 +108,7 @@
 
   EXPECT_TRUE(
       saved_device_registry_->IsAccountKeySavedToRegistry(kAccountKey1));
+  EXPECT_TRUE(success1);
   EXPECT_FALSE(
       saved_device_registry_->IsAccountKeySavedToRegistry(kAccountKey2));
 }
@@ -110,8 +116,10 @@
 TEST_F(SavedDeviceRegistryTest, MissingPrefService) {
   ON_CALL(*browser_delegate_, GetActivePrefService())
       .WillByDefault(testing::Return(nullptr));
-  saved_device_registry_->SaveAccountKey(kFirstSavedMacAddress, kAccountKey1);
-  saved_device_registry_->SaveAccountKey(kSecondSavedMacAddress, kAccountKey2);
+  bool failure1 = saved_device_registry_->SaveAccountAssociation(
+      kFirstSavedMacAddress, kAccountKey1);
+  bool failure2 = saved_device_registry_->SaveAccountAssociation(
+      kSecondSavedMacAddress, kAccountKey2);
 
   auto first = saved_device_registry_->GetAccountKey(kFirstSavedMacAddress);
   auto second = saved_device_registry_->GetAccountKey(kSecondSavedMacAddress);
@@ -123,6 +131,9 @@
   EXPECT_FALSE(
       saved_device_registry_->DeleteAccountKey(kSecondSavedMacAddress));
 
+  EXPECT_FALSE(failure1);
+  EXPECT_FALSE(failure2);
+
   EXPECT_FALSE(
       saved_device_registry_->IsAccountKeySavedToRegistry(kAccountKey1));
   EXPECT_FALSE(
@@ -130,8 +141,10 @@
 }
 
 TEST_F(SavedDeviceRegistryTest, DeleteAccountKey_MacAddress) {
-  saved_device_registry_->SaveAccountKey(kFirstSavedMacAddress, kAccountKey1);
-  saved_device_registry_->SaveAccountKey(kSecondSavedMacAddress, kAccountKey2);
+  bool success1 = saved_device_registry_->SaveAccountAssociation(
+      kFirstSavedMacAddress, kAccountKey1);
+  bool success2 = saved_device_registry_->SaveAccountAssociation(
+      kSecondSavedMacAddress, kAccountKey2);
 
   auto first = saved_device_registry_->GetAccountKey(kFirstSavedMacAddress);
   auto second = saved_device_registry_->GetAccountKey(kSecondSavedMacAddress);
@@ -139,6 +152,9 @@
   ASSERT_EQ(kAccountKey1, *first);
   ASSERT_EQ(kAccountKey2, *second);
 
+  EXPECT_TRUE(success1);
+  EXPECT_TRUE(success2);
+
   EXPECT_TRUE(
       saved_device_registry_->IsAccountKeySavedToRegistry(kAccountKey1));
   EXPECT_TRUE(
@@ -163,8 +179,10 @@
 }
 
 TEST_F(SavedDeviceRegistryTest, DeleteAccountKey_AccountKey) {
-  saved_device_registry_->SaveAccountKey(kFirstSavedMacAddress, kAccountKey1);
-  saved_device_registry_->SaveAccountKey(kSecondSavedMacAddress, kAccountKey2);
+  bool success1 = saved_device_registry_->SaveAccountAssociation(
+      kFirstSavedMacAddress, kAccountKey1);
+  bool success2 = saved_device_registry_->SaveAccountAssociation(
+      kSecondSavedMacAddress, kAccountKey2);
 
   auto first = saved_device_registry_->GetAccountKey(kFirstSavedMacAddress);
   auto second = saved_device_registry_->GetAccountKey(kSecondSavedMacAddress);
@@ -172,6 +190,9 @@
   ASSERT_EQ(kAccountKey1, *first);
   ASSERT_EQ(kAccountKey2, *second);
 
+  EXPECT_TRUE(success1);
+  EXPECT_TRUE(success2);
+
   EXPECT_TRUE(
       saved_device_registry_->IsAccountKeySavedToRegistry(kAccountKey1));
   EXPECT_TRUE(
@@ -205,8 +226,13 @@
 TEST_F(SavedDeviceRegistryTest,
        MAYBE_IsAccountKeySavedToRegistry_DeviceRemoved) {
   // Simulate a user saving devices to their account.
-  saved_device_registry_->SaveAccountKey(kFirstSavedMacAddress, kAccountKey1);
-  saved_device_registry_->SaveAccountKey(kSecondSavedMacAddress, kAccountKey2);
+  bool success1 = saved_device_registry_->SaveAccountAssociation(
+      kFirstSavedMacAddress, kAccountKey1);
+  bool success2 = saved_device_registry_->SaveAccountAssociation(
+      kSecondSavedMacAddress, kAccountKey2);
+
+  EXPECT_TRUE(success1);
+  EXPECT_TRUE(success2);
 
   // Destroy the object to simulate a user's session ending.
   saved_device_registry_.reset();
diff --git a/ash/quick_pair/repository/fast_pair_repository_impl.cc b/ash/quick_pair/repository/fast_pair_repository_impl.cc
index e310014..004f5c4 100644
--- a/ash/quick_pair/repository/fast_pair_repository_impl.cc
+++ b/ash/quick_pair/repository/fast_pair_repository_impl.cc
@@ -173,8 +173,9 @@
   // and we want to prevent showing a Subsequent pairing notification in this
   // case.
   for (device::BluetoothDevice* device : adapter_->GetDevices()) {
-    if (!device->IsPaired())
+    if (!device->IsPaired()) {
       continue;
+    }
 
     // Use the paired device's |mac_address| and the given |account_key| to
     // generate a SHA256(concat(account_key, mac_address)), and use this
@@ -193,7 +194,16 @@
             << __func__
             << ": paired device already saved to account at address = "
             << mac_address << "; adding to registry";
-        saved_device_registry_->SaveAccountKey(mac_address, account_key);
+        if (saved_device_registry_->SaveAccountAssociation(mac_address,
+                                                           account_key)) {
+          QP_LOG(VERBOSE) << __func__
+                          << ": paired device at address = " << mac_address
+                          << " added to local registry.";
+        } else {
+          QP_LOG(WARNING) << __func__
+                          << ": failed to add paired device at address = "
+                          << mac_address << " to local registry.";
+        }
 
         // We only expect there to be at most one match with |account_key| in
         // the devices saved to Footprints. An account key is uniquely written
@@ -343,10 +353,18 @@
   }
 
   DCHECK(device->classic_address());
-  saved_device_registry_->SaveAccountKey(device->classic_address().value(),
-                                         account_key.value());
-  QP_LOG(INFO) << __func__ << ": Saved account key locally.";
-  return true;
+  const std::string& mac_address = device->classic_address().value();
+  if (saved_device_registry_->SaveAccountAssociation(mac_address,
+                                                     account_key.value())) {
+    QP_LOG(VERBOSE) << __func__
+                    << ": paired device at address = " << mac_address
+                    << " added to local registry.";
+    return true;
+  }
+
+  QP_LOG(WARNING) << __func__ << ": failed to add paired device at address = "
+                  << mac_address << " to local registry.";
+  return false;
 }
 
 void FastPairRepositoryImpl::WriteDeviceToFootprints(
@@ -398,15 +416,16 @@
   pending_write_store_->OnPairedDeviceSaved(mac_address);
 
   // Save/Update account key in the saved device registry.
-  saved_device_registry_->SaveAccountKey(mac_address, account_key);
-  if (saved_device_registry_->IsAccountKeySavedToRegistry(account_key)) {
-    QP_LOG(INFO) << __func__
-                 << ": Successfully wrote device to Saved Device Registry.";
+  if (saved_device_registry_->SaveAccountAssociation(mac_address,
+                                                     account_key)) {
+    QP_LOG(VERBOSE) << __func__
+                    << ": paired device at address = " << mac_address
+                    << " added to local registry.";
     return;
   }
 
-  QP_LOG(WARNING) << __func__
-                  << ": Failed to write device to Saved Device Registry.";
+  QP_LOG(WARNING) << __func__ << ": failed to add paired device at address = "
+                  << mac_address << " to local registry.";
 }
 
 void FastPairRepositoryImpl::CheckOptInStatus(
@@ -635,16 +654,18 @@
     for (const auto& device : devices) {
       // Account key may be null for a device removed from Android Saved
       // Devices.
-      if (!device.has_account_key())
+      if (!device.has_account_key()) {
         continue;
+      }
 
       const std::string saved_account_key =
           base::HexEncode(std::vector<uint8_t>(device.account_key().begin(),
                                                device.account_key().end()));
       found_in_saved_devices =
           saved_account_key == pending_delete.hex_account_key;
-      if (found_in_saved_devices)
+      if (found_in_saved_devices) {
         break;
+      }
     }
 
     // If our failed-to-delete account key is still found in Footprints, then
@@ -788,13 +809,15 @@
   const std::string device_id = device->GetIdentifier();
   absl::optional<const std::string> hex_model_id =
       device_id_map_->GetModelIdForDeviceId(device_id);
-  if (!hex_model_id)
+  if (!hex_model_id) {
     return false;
+  }
   device_id_map_->EvictDeviceIdRecord(device_id);
 
   // Before evicting images, check if other device IDs map to this model ID.
-  if (device_id_map_->HasPersistedRecordsForModelId(hex_model_id.value()))
+  if (device_id_map_->HasPersistedRecordsForModelId(hex_model_id.value())) {
     return false;
+  }
 
   return device_image_store_->EvictDeviceImages(hex_model_id.value());
 }
diff --git a/ash/quick_pair/repository/fast_pair_repository_impl_unittest.cc b/ash/quick_pair/repository/fast_pair_repository_impl_unittest.cc
index 5e19280f..2a13a85 100644
--- a/ash/quick_pair/repository/fast_pair_repository_impl_unittest.cc
+++ b/ash/quick_pair/repository/fast_pair_repository_impl_unittest.cc
@@ -1024,7 +1024,9 @@
   // be saved in the registry even if it is not paired locally because
   // the SavedDeviceRegistry  tracks devices that have been Fast paired in the
   // past.
-  saved_device_registry_->SaveAccountKey(kTestClassicAddress1, kAccountKey1);
+  bool success = saved_device_registry_->SaveAccountAssociation(
+      kTestClassicAddress1, kAccountKey1);
+  EXPECT_TRUE(success);
   EXPECT_TRUE(
       saved_device_registry_->IsAccountKeySavedToRegistry(kAccountKey1));
 
diff --git a/ash/shelf/home_button.cc b/ash/shelf/home_button.cc
index 14cc0368..0410aa0 100644
--- a/ash/shelf/home_button.cc
+++ b/ash/shelf/home_button.cc
@@ -352,9 +352,9 @@
 
     if (controller_.IsAssistantAvailable()) {
       // active: 100% alpha, inactive: 54% alpha
-      fg_flags.setAlpha(controller_.IsAssistantVisible()
-                            ? kAssistantVisibleAlpha
-                            : kAssistantInvisibleAlpha);
+      fg_flags.setAlphaf(controller_.IsAssistantVisible()
+                             ? kAssistantVisibleAlpha / 255.0f
+                             : kAssistantInvisibleAlpha / 255.0f);
     }
 
     const float thickness = std::ceil(ring_thickness_dp * dsf);
@@ -364,7 +364,7 @@
     canvas->DrawCircle(circle_center, radius, fg_flags);
 
     if (controller_.IsAssistantAvailable()) {
-      fg_flags.setAlpha(255);
+      fg_flags.setAlphaf(1.0f);
       const float kCircleRadiusDp = 5.f;
       fg_flags.setStyle(cc::PaintFlags::kFill_Style);
       canvas->DrawCircle(circle_center, std::ceil(kCircleRadiusDp * dsf),
diff --git a/ash/system/message_center/ash_notification_view_pixeltest.cc b/ash/system/message_center/ash_notification_view_pixeltest.cc
index 69b7b87..dc7df5d 100644
--- a/ash/system/message_center/ash_notification_view_pixeltest.cc
+++ b/ash/system/message_center/ash_notification_view_pixeltest.cc
@@ -88,9 +88,6 @@
   ASSERT_TRUE(notification_view);
   EXPECT_TRUE(notification_view->GetVisible());
 
-  // Waits for the message popup animation to complete.
-  base::RunLoop().RunUntilIdle();
-
   // Compare pixels.
   const std::string screenshot = GetParam().second;
   EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
diff --git a/ash/system/phonehub/phone_hub_more_apps_button.cc b/ash/system/phonehub/phone_hub_more_apps_button.cc
new file mode 100644
index 0000000..4b313510
--- /dev/null
+++ b/ash/system/phonehub/phone_hub_more_apps_button.cc
@@ -0,0 +1,75 @@
+// 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/phonehub/phone_hub_more_apps_button.h"
+
+#include "ash/style/ash_color_provider.h"
+#include "ash/system/phonehub/phone_hub_small_app_icon.h"
+#include "chromeos/ash/components/phonehub/app_stream_launcher_data_model.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/views/background.h"
+#include "ui/views/layout/table_layout.h"
+
+namespace ash {
+
+// Appearance constants in DIPs
+constexpr int kMoreAppsButtonRowPadding = 20;
+constexpr int kMoreAppsButtonColumnPadding = 2;
+constexpr int kMoreAppsButtonBackgroundRadius = 16;
+
+PhoneHubMoreAppsButton::PhoneHubMoreAppsButton(
+    phonehub::AppStreamLauncherDataModel* app_stream_launcher_data_model)
+    : app_stream_launcher_data_model_(app_stream_launcher_data_model) {
+  InitLayout();
+  app_stream_launcher_data_model_->AddObserver(this);
+}
+
+PhoneHubMoreAppsButton::~PhoneHubMoreAppsButton() {
+  app_stream_launcher_data_model_->RemoveObserver(this);
+}
+
+// TODO: Add a loading state before all apps loads
+void PhoneHubMoreAppsButton::InitLayout() {
+  table_layout_ = SetLayoutManager(std::make_unique<views::TableLayout>());
+  table_layout_->AddColumn(views::LayoutAlignment::kStretch,
+                           views::LayoutAlignment::kStretch, 1.0,
+                           views::TableLayout::ColumnSize::kUsePreferred, 0, 0);
+  table_layout_->AddPaddingColumn(views::TableLayout::kFixedSize,
+                                  kMoreAppsButtonColumnPadding);
+  table_layout_->AddColumn(views::LayoutAlignment::kStretch,
+                           views::LayoutAlignment::kStretch, 1.0,
+                           views::TableLayout::ColumnSize::kUsePreferred, 0, 0);
+  table_layout_->AddRows(1, kMoreAppsButtonRowPadding);
+  table_layout_->AddPaddingRow(views::TableLayout::kFixedSize,
+                               kMoreAppsButtonColumnPadding);
+  table_layout_->AddRows(1, kMoreAppsButtonRowPadding);
+
+  SetBackground(views::CreateRoundedRectBackground(
+      AshColorProvider::Get()->GetControlsLayerColor(
+          AshColorProvider::ControlsLayerType::kControlBackgroundColorInactive),
+      kMoreAppsButtonBackgroundRadius));
+}
+
+void PhoneHubMoreAppsButton::OnShouldShowMiniLauncherChanged() {}
+
+void PhoneHubMoreAppsButton::OnAppListChanged() {
+  LoadAppList();
+}
+
+void PhoneHubMoreAppsButton::LoadAppList() {
+  RemoveAllChildViews();
+  const std::vector<phonehub::Notification::AppMetadata>* app_list =
+      app_stream_launcher_data_model_->GetAppsList();
+  if (!app_list->empty()) {
+    auto app_count = std::min(app_list->size(), size_t{4});
+    for (size_t i = 0; i < app_count; i++) {
+      AddChildView(std::make_unique<SmallAppIcon>(app_list->at(i).icon));
+    }
+  }
+}
+
+BEGIN_METADATA(PhoneHubMoreAppsButton, views::View)
+END_METADATA
+
+}  // namespace ash
\ No newline at end of file
diff --git a/ash/system/phonehub/phone_hub_more_apps_button.h b/ash/system/phonehub/phone_hub_more_apps_button.h
new file mode 100644
index 0000000..bcf0f8c
--- /dev/null
+++ b/ash/system/phonehub/phone_hub_more_apps_button.h
@@ -0,0 +1,41 @@
+// 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_PHONEHUB_PHONE_HUB_MORE_APPS_BUTTON_H_
+#define ASH_SYSTEM_PHONEHUB_PHONE_HUB_MORE_APPS_BUTTON_H_
+
+#include "chromeos/ash/components/phonehub/app_stream_launcher_data_model.h"
+#include "ui/views/layout/table_layout.h"
+#include "ui/views/view.h"
+
+namespace ash {
+
+// A view in phone hub that displays the first three apps in a user's app
+// drawer, as well as a count of how many apps they have on their phone.
+class VIEWS_EXPORT PhoneHubMoreAppsButton
+    : public views::View,
+      phonehub::AppStreamLauncherDataModel::Observer {
+ public:
+  METADATA_HEADER(PhoneHubMoreAppsButton);
+
+  explicit PhoneHubMoreAppsButton(
+      phonehub::AppStreamLauncherDataModel* app_stream_launcher_data_model);
+  PhoneHubMoreAppsButton(const PhoneHubMoreAppsButton&) = delete;
+  PhoneHubMoreAppsButton& operator=(const PhoneHubMoreAppsButton&) = delete;
+  ~PhoneHubMoreAppsButton() override;
+
+  // phonehub::AppStreamLauncherDataModel
+  void OnShouldShowMiniLauncherChanged() override;
+  void OnAppListChanged() override;
+
+ private:
+  void InitLayout();
+  void LoadAppList();
+
+  views::TableLayout* table_layout_ = nullptr;
+  phonehub::AppStreamLauncherDataModel* app_stream_launcher_data_model_;
+};
+}  // namespace ash
+
+#endif  // ASH_SYSTEM_PHONEHUB_PHONE_HUB_MORE_APPS_BUTTON_H_
\ No newline at end of file
diff --git a/ash/system/video_conference/bubble/bubble_view.cc b/ash/system/video_conference/bubble/bubble_view.cc
index bf6af16..09b2544 100644
--- a/ash/system/video_conference/bubble/bubble_view.cc
+++ b/ash/system/video_conference/bubble/bubble_view.cc
@@ -71,7 +71,8 @@
   // they scroll (if more effects are present than can fit in the available
   // height).
   if (controller_->effects_manager().HasToggleEffects()) {
-    layout->AddChildView(std::make_unique<ToggleEffectsView>(controller_));
+    layout->AddChildView(std::make_unique<ToggleEffectsView>(
+        controller_, GetPreferredSize().width()));
   }
   if (controller_->effects_manager().HasSetValueEffects()) {
     layout->AddChildView(std::make_unique<SetValueEffectsView>(controller_));
diff --git a/ash/system/video_conference/bubble/toggle_effects_view.cc b/ash/system/video_conference/bubble/toggle_effects_view.cc
index 13cadb9..d933b6f 100644
--- a/ash/system/video_conference/bubble/toggle_effects_view.cc
+++ b/ash/system/video_conference/bubble/toggle_effects_view.cc
@@ -7,35 +7,54 @@
 
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/style/icon_button.h"
+#include "ash/system/tray/tray_constants.h"
 #include "ash/system/video_conference/bubble/bubble_view_ids.h"
 #include "ash/system/video_conference/effects/video_conference_tray_effects_manager_types.h"
 #include "ash/system/video_conference/video_conference_tray_controller.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
+#include "ui/gfx/geometry/size.h"
 #include "ui/views/background.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/flex_layout.h"
+#include "ui/views/layout/flex_layout_types.h"
+#include "ui/views/view_class_properties.h"
 
 namespace ash {
 
 namespace {
 
+constexpr int kButtonCornerRadius = 16;
+constexpr int kButtonHeight = 64;
+
 // A single toggle button for a video conference effect, combined with a text
 // label.
 class ButtonContainer : public views::View, public IconButton::Delegate {
  public:
+  METADATA_HEADER(ButtonContainer);
+
   ButtonContainer(views::Button::PressedCallback callback,
                   const gfx::VectorIcon* icon,
                   bool toggle_state,
                   const std::u16string& label_text,
-                  const int accessible_name_id) {
+                  const int accessible_name_id,
+                  const int preferred_width) {
     views::FlexLayout* layout =
         SetLayoutManager(std::make_unique<views::FlexLayout>());
     layout->SetOrientation(views::LayoutOrientation::kVertical);
     layout->SetMainAxisAlignment(views::LayoutAlignment::kCenter);
     layout->SetCrossAxisAlignment(views::LayoutAlignment::kStretch);
 
-    AddChildView(std::make_unique<views::Label>(label_text));
+    // This makes the view the expand or contract to occupy any available space.
+    SetProperty(
+        views::kFlexBehaviorKey,
+        views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToMinimum,
+                                 views::MaximumFlexSizeRule::kUnbounded));
+
+    // `preferred_width` is assigned by the row this buttons resides in,
+    // `kButtonHeight` is from the spec.
+    SetPreferredSize(gfx::Size(preferred_width, kButtonHeight));
 
     // Construct the `IconButton`, set ID and initial toggle state (from the
     // passed-in value, which is the current state of the effect).
@@ -50,18 +69,14 @@
     // button when clicked.
     button->set_delegate(this);
 
-    // TODO(b/253249205): This is temporary, will be replaced wholesale when the
-    // effect toggle buttons are made to conform with the spec.
-    button->SetBackgroundToggledColorId(
-        cros_tokens::kCrosSysSystemNegativeContainer);
-    button->SetIconToggledColorId(
-        cros_tokens::kCrosSysSystemOnNegativeContainer);
+    // `button` is owned by the `view::View` but a pointer is saved off for
+    // logic based on its toggle state.
+    button_ = AddChildView(std::move(button));
 
-    AddChildView(std::move(button));
+    // Label is below the button.
+    AddChildView(std::make_unique<views::Label>(label_text));
 
-    SetBorder(views::CreateEmptyBorder(gfx::Insets::VH(10, 10)));
-    SetBackground(views::CreateRoundedRectBackground(gfx::kGooglePurple800,
-                                                     /*radius=*/10));
+    UpdateColorsAndBackground();
   }
 
   ButtonContainer(const ButtonContainer&) = delete;
@@ -73,15 +88,31 @@
   void OnButtonToggled(IconButton* button) override {}
   void OnButtonClicked(IconButton* button) override {
     button->SetToggled(!button->toggled());
+    UpdateColorsAndBackground();
   }
+
+  void UpdateColorsAndBackground() {
+    ui::ColorId background_color_id =
+        button_->toggled() ? cros_tokens::kCrosSysSystemPrimaryContainer
+                           : cros_tokens::kCrosSysSystemOnBase;
+
+    SetBackground(views::CreateThemedRoundedRectBackground(
+        background_color_id, kButtonCornerRadius));
+  }
+
+ private:
+  IconButton* button_ = nullptr;
 };
 
+BEGIN_METADATA(ButtonContainer, views::View);
+END_METADATA
+
 }  // namespace
 
 namespace video_conference {
 
-ToggleEffectsView::ToggleEffectsView(
-    VideoConferenceTrayController* controller) {
+ToggleEffectsView::ToggleEffectsView(VideoConferenceTrayController* controller,
+                                     const int parent_width) {
   SetID(BubbleViewID::kToggleEffectsView);
 
   // Layout for the entire toggle effects section.
@@ -104,6 +135,10 @@
     row_layout->SetCrossAxisAlignment(views::LayoutAlignment::kStretch);
     row_view->SetLayoutManager(std::move(row_layout));
 
+    // All buttons in a single row should have the same width i.e. fraction of
+    // the parent width.
+    const int button_width = parent_width / row.size();
+
     // Add a button for each item in the row.
     for (auto* tile : row) {
       DCHECK_EQ(tile->type(), VcEffectType::kToggle);
@@ -123,7 +158,7 @@
       const VcEffectState* state = tile->GetState(/*index=*/0);
       row_view->AddChildView(std::make_unique<ButtonContainer>(
           state->button_callback(), state->icon(), toggle_state,
-          state->label_text(), state->accessible_name_id()));
+          state->label_text(), state->accessible_name_id(), button_width));
     }
 
     // Add the row as a child, now that it's fully populated,
@@ -131,6 +166,9 @@
   }
 }
 
+BEGIN_METADATA(ToggleEffectsView, views::View);
+END_METADATA
+
 }  // namespace video_conference
 
 }  // namespace ash
\ No newline at end of file
diff --git a/ash/system/video_conference/bubble/toggle_effects_view.h b/ash/system/video_conference/bubble/toggle_effects_view.h
index e7d7ab8..787a297 100644
--- a/ash/system/video_conference/bubble/toggle_effects_view.h
+++ b/ash/system/video_conference/bubble/toggle_effects_view.h
@@ -22,7 +22,10 @@
 // controller.
 class ToggleEffectsView : public views::View {
  public:
-  explicit ToggleEffectsView(VideoConferenceTrayController* controller);
+  METADATA_HEADER(ToggleEffectsView);
+
+  ToggleEffectsView(VideoConferenceTrayController* controller,
+                    const int parent_width);
   ToggleEffectsView(const ToggleEffectsView&) = delete;
   ToggleEffectsView& operator=(const ToggleEffectsView&) = delete;
   ~ToggleEffectsView() override = default;
diff --git a/ash/system/video_conference/video_conference_tray_controller.cc b/ash/system/video_conference/video_conference_tray_controller.cc
index 9ed4bbf0..bedb88a3 100644
--- a/ash/system/video_conference/video_conference_tray_controller.cc
+++ b/ash/system/video_conference/video_conference_tray_controller.cc
@@ -4,8 +4,12 @@
 
 #include "ash/system/video_conference/video_conference_tray_controller.h"
 
+#include "ash/constants/notifier_catalogs.h"
+#include "ash/public/cpp/system/toast_data.h"
+#include "ash/public/cpp/system/toast_manager.h"
 #include "ash/root_window_controller.h"
 #include "ash/shell.h"
+#include "ash/strings/grit/ash_strings.h"
 #include "ash/style/icon_button.h"
 #include "ash/system/status_area_widget.h"
 #include "ash/system/video_conference/video_conference_media_state.h"
@@ -14,10 +18,18 @@
 #include "chromeos/crosapi/mojom/video_conference.mojom.h"
 #include "media/capture/video/chromeos/camera_hal_dispatcher_impl.h"
 #include "media/capture/video/chromeos/mojom/cros_camera_service.mojom-shared.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace ash {
 
 namespace {
+// The ID for the "Speak-on-mute detected" toast.
+constexpr char kVideoConferenceTraySpeakOnMuteDetectedId[] =
+    "video_conference_tray_toast_ids.speak_on_mute_detected";
+
+// The cool down duration for speak-on-mute detection notification in seconds.
+constexpr int KSpeakOnMuteNotificationCoolDownDuration = 60;
+
 VideoConferenceTrayController* g_controller_instance = nullptr;
 }  // namespace
 
@@ -81,6 +93,26 @@
   }
 }
 
+void VideoConferenceTrayController::OnSpeakOnMuteDetected() {
+  const base::TimeTicks current_time = base::TimeTicks::Now();
+
+  if (!last_speak_on_mute_notification_time_.has_value() ||
+      (current_time - last_speak_on_mute_notification_time_.value())
+              .InSeconds() >= KSpeakOnMuteNotificationCoolDownDuration) {
+    ToastData toast_data(
+        kVideoConferenceTraySpeakOnMuteDetectedId,
+        ToastCatalogName::kVideoConferenceTraySpeakOnMuteDetected,
+        l10n_util::GetStringUTF16(
+            IDS_ASH_VIDEO_CONFERENCE_TOAST_SPEAK_ON_MUTE_DETECTED),
+        ToastData::kDefaultToastDuration,
+        /*visible_on_lock_screen=*/false);
+    toast_data.show_on_all_root_windows = true;
+    ToastManager::Get()->Show(std::move(toast_data));
+
+    last_speak_on_mute_notification_time_.emplace(current_time);
+  }
+}
+
 void VideoConferenceTrayController::UpdateWithMediaState(
     VideoConferenceMediaState state) {
   auto old_state = state_;
@@ -128,4 +160,4 @@
   // TODO(b/249828245): Implement logic to handle this.
 }
 
-}  // namespace ash
\ No newline at end of file
+}  // namespace ash
diff --git a/ash/system/video_conference/video_conference_tray_controller.h b/ash/system/video_conference/video_conference_tray_controller.h
index 20428f2..24cbc40b 100644
--- a/ash/system/video_conference/video_conference_tray_controller.h
+++ b/ash/system/video_conference/video_conference_tray_controller.h
@@ -9,6 +9,7 @@
 #include "ash/system/video_conference/effects/video_conference_tray_effects_manager.h"
 #include "ash/system/video_conference/video_conference_media_state.h"
 #include "base/observer_list_types.h"
+#include "base/time/time.h"
 #include "chromeos/ash/components/audio/cras_audio_handler.h"
 #include "chromeos/crosapi/mojom/video_conference.mojom-forward.h"
 #include "media/capture/video/chromeos/camera_hal_dispatcher_impl.h"
@@ -93,6 +94,10 @@
       bool mute_on,
       CrasAudioHandler::InputMuteChangeMethod method) override;
 
+  // CrasAudioHandler::AudioObserver:
+  // Pop up a toast when speaking on mute is detected.
+  void OnSpeakOnMuteDetected() override;
+
   VideoConferenceTrayEffectsManager& effects_manager() {
     return effects_manager_;
   }
@@ -107,8 +112,11 @@
 
   // Registered observers.
   base::ObserverList<Observer> observer_list_;
+
+  // The last time speak-on-mute notification showed.
+  absl::optional<base::TimeTicks> last_speak_on_mute_notification_time_;
 };
 
 }  // namespace ash
 
-#endif  // ASH_SYSTEM_VIDEO_CONFERENCE_VIDEO_CONFERENCE_TRAY_CONTROLLER_H_
\ No newline at end of file
+#endif  // ASH_SYSTEM_VIDEO_CONFERENCE_VIDEO_CONFERENCE_TRAY_CONTROLLER_H_
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc
index 8c8f27b..05e6fb6 100644
--- a/ash/test/ash_test_helper.cc
+++ b/ash/test/ash_test_helper.cc
@@ -410,11 +410,7 @@
 }
 
 void AshTestHelper::StabilizeUIForPixelTest() {
-  const gfx::Size primary_display_size =
-      display::Screen::GetScreen()
-          ->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow())
-          .size();
-  pixel_test_helper_->StabilizeUi(primary_display_size);
+  pixel_test_helper_->StabilizeUi();
 }
 
 }  // namespace ash
diff --git a/ash/test/pixel/ash_pixel_test_helper.cc b/ash/test/pixel/ash_pixel_test_helper.cc
index 99e44479..050ed62 100644
--- a/ash/test/pixel/ash_pixel_test_helper.cc
+++ b/ash/test/pixel/ash_pixel_test_helper.cc
@@ -10,7 +10,9 @@
 #include "ash/test/ash_test_util.h"
 #include "ash/wallpaper/wallpaper_controller_impl.h"
 #include "base/command_line.h"
+#include "base/functional/callback.h"
 #include "base/i18n/base_i18n_switches.h"
+#include "base/run_loop.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
 
@@ -19,7 +21,10 @@
 namespace {
 
 // The color of the default wallpaper in pixel tests.
-constexpr SkColor kWallPaperColor = SK_ColorMAGENTA;
+constexpr SkColor kWallpaperColor = SK_ColorMAGENTA;
+
+// 1x1 wallpaper will tile to cover the display.
+constexpr int kWallpaperSize = 1;
 
 // Specify the locale and the time zone used in pixel tests.
 constexpr char kLocale[] = "en_US";
@@ -39,9 +44,9 @@
 
 AshPixelTestHelper::~AshPixelTestHelper() = default;
 
-void AshPixelTestHelper::StabilizeUi(const gfx::Size& wallpaper_size) {
+void AshPixelTestHelper::StabilizeUi() {
   MaybeSetDarkMode();
-  SetWallPaper(wallpaper_size);
+  SetWallpaper();
   SetBatteryState();
 }
 
@@ -56,31 +61,45 @@
     dark_light_mode_controller->ToggleColorMode();
 }
 
-void AshPixelTestHelper::SetWallPaper(const gfx::Size& wallpaper_size) {
+void AshPixelTestHelper::SetWallpaper() {
   auto* controller = Shell::Get()->wallpaper_controller();
   controller->set_wallpaper_reload_no_delay_for_test();
 
   switch (params_.wallpaper_init_type) {
     case pixel_test::WallpaperInitType::kRegular: {
-      gfx::ImageSkia wallpaper_image =
-          CreateSolidColorTestImage(wallpaper_size, kWallPaperColor);
+      gfx::ImageSkia wallpaper_image = CreateSolidColorTestImage(
+          {kWallpaperSize, kWallpaperSize}, kWallpaperColor);
       controller->set_allow_blur_or_shield_for_testing();
 
+      DCHECK(!wallpaper_controller_observation_.IsObserving());
+      wallpaper_controller_observation_.Observe(controller);
+
+      base::RunLoop loop;
+      DCHECK(!on_wallpaper_finalized_);
+      on_wallpaper_finalized_ = loop.QuitClosure();
+
       // Use the one shot wallpaper to ensure that the custom wallpaper set by
       // pixel tests does not go away after changing display metrics.
       controller->ShowWallpaperImage(
           wallpaper_image,
           WallpaperInfo{/*in_location=*/std::string(),
-                        /*in_layout=*/WALLPAPER_LAYOUT_STRETCH,
+                        /*in_layout=*/WALLPAPER_LAYOUT_TILE,
                         /*in_type=*/WallpaperType::kOneShot,
                         /*in_date=*/base::Time::Now().LocalMidnight()},
           /*preview_mode=*/false, /*always_on_top=*/false);
+
+      // Wait for `WallpaperControllerObserver::OnWallpaperColorsChanged` so
+      // that colors are finalized before pixel testing views.
+      loop.Run();
+      DCHECK(!wallpaper_controller_observation_.IsObserving());
       break;
     }
     case pixel_test::WallpaperInitType::kPolicy:
       controller->set_bypass_decode_for_testing();
 
       // A dummy file path is sufficient for setting a default policy wallpaper.
+      // Do not wait for resize or color calculation, as this is not a real png
+      // and it will never load.
       controller->SetDevicePolicyWallpaperPath(base::FilePath("tmp.png"));
 
       break;
@@ -97,4 +116,10 @@
   chromeos::FakePowerManagerClient::Get()->UpdatePowerProperties(proto);
 }
 
+void AshPixelTestHelper::OnWallpaperColorsChanged() {
+  DCHECK(on_wallpaper_finalized_);
+  wallpaper_controller_observation_.Reset();
+  std::move(on_wallpaper_finalized_).Run();
+}
+
 }  // namespace ash
diff --git a/ash/test/pixel/ash_pixel_test_helper.h b/ash/test/pixel/ash_pixel_test_helper.h
index 70c0a15..fe396e11 100644
--- a/ash/test/pixel/ash_pixel_test_helper.h
+++ b/ash/test/pixel/ash_pixel_test_helper.h
@@ -5,43 +5,52 @@
 #ifndef ASH_TEST_PIXEL_ASH_PIXEL_TEST_HELPER_H_
 #define ASH_TEST_PIXEL_ASH_PIXEL_TEST_HELPER_H_
 
+#include "ash/public/cpp/wallpaper/wallpaper_controller_observer.h"
 #include "ash/test/pixel/ash_pixel_test_init_params.h"
-#include "ash/wallpaper/test_wallpaper_controller_client.h"
-#include "base/files/scoped_temp_dir.h"
+#include "base/functional/callback.h"
+#include "base/scoped_observation.h"
 #include "base/test/icu_test_util.h"
 
-namespace gfx {
-class Size;
-}  // namespace gfx
-
 namespace ash {
 
+class WallpaperController;
+
 // A test helper class that sets up the system UI for pixel tests.
-class AshPixelTestHelper {
+class AshPixelTestHelper : public WallpaperControllerObserver {
  public:
   explicit AshPixelTestHelper(pixel_test::InitParams params);
   AshPixelTestHelper(const AshPixelTestHelper&) = delete;
   AshPixelTestHelper& operator=(const AshPixelTestHelper&) = delete;
-  ~AshPixelTestHelper();
+  ~AshPixelTestHelper() override;
 
   // Makes the variable UI components (such as the battery view and wallpaper)
   // constant to avoid flakiness in pixel tests.
-  void StabilizeUi(const gfx::Size& wallpaper_size);
+  void StabilizeUi();
 
  private:
   // Ensures that the system UI is under the dark mode if the dark/light feature
   // is enabled.
   void MaybeSetDarkMode();
 
-  // Sets a pure color wallpaper.
-  void SetWallPaper(const gfx::Size& wallpaper_size);
+  // Sets a pure color wallpaper and waits for wallpaper async tasks (resize,
+  // color calculation) to complete.
+  void SetWallpaper();
 
   // Sets the battery state. It ensures that the tray battery icon does not
   // change during pixel tests.
   void SetBatteryState();
 
+  // WallpaperControllerObserver:
+  void OnWallpaperColorsChanged() override;
+
   const pixel_test::InitParams params_;
 
+  // Allows blocking until wallpaper async tasks have finished and the UI has
+  // stabilized. Async tasks include wallpaper resize and color calculation.
+  base::OnceClosure on_wallpaper_finalized_;
+  base::ScopedObservation<WallpaperController, WallpaperControllerObserver>
+      wallpaper_controller_observation_{this};
+
   // Used for setting the locale and the time zone.
   const base::test::ScopedRestoreICUDefaultLocale scoped_locale_;
   const base::test::ScopedRestoreDefaultTimezone time_zone_;
diff --git a/ash/touch/touch_hud_renderer.cc b/ash/touch/touch_hud_renderer.cc
index 8efc6ca..c5a8dbf 100644
--- a/ash/touch/touch_hud_renderer.cc
+++ b/ash/touch/touch_hud_renderer.cc
@@ -26,7 +26,7 @@
 constexpr int kPointRadius = 20;
 constexpr SkColor4f kProjectionFillColor{0.96f, 0.96f, 0.86f, 1.0f};
 constexpr SkColor4f kProjectionStrokeColor = SkColors::kGray;
-constexpr int kProjectionAlpha = 0xB0;
+constexpr float kProjectionAlpha = 0xB0 / 255.0f;
 constexpr base::TimeDelta kFadeoutDuration = base::Milliseconds(250);
 constexpr int kFadeoutFrameRate = 60;
 
@@ -71,12 +71,12 @@
  private:
   // views::View:
   void OnPaint(gfx::Canvas* canvas) override {
-    int alpha = kProjectionAlpha;
-    if (fadeout_)
-      alpha = static_cast<int>(fadeout_->CurrentValueBetween(alpha, 0));
+    const float alpha =
+        fadeout_ ? fadeout_->CurrentValueBetween(kProjectionAlpha, 0.0f)
+                 : kProjectionAlpha;
 
     cc::PaintFlags fill_flags;
-    fill_flags.setAlpha(alpha);
+    fill_flags.setAlphaf(alpha);
 
     constexpr SkColor4f gradient_colors[2] = {kProjectionFillColor,
                                               kProjectionStrokeColor};
@@ -93,7 +93,7 @@
     cc::PaintFlags stroke_flags;
     stroke_flags.setStyle(cc::PaintFlags::kStroke_Style);
     stroke_flags.setColor(kProjectionStrokeColor);
-    stroke_flags.setAlpha(alpha);
+    stroke_flags.setAlphaf(alpha);
     canvas->DrawCircle(center, SkIntToScalar(kPointRadius), stroke_flags);
   }
 
diff --git a/ash/wallpaper/wallpaper_controller_impl.cc b/ash/wallpaper/wallpaper_controller_impl.cc
index 0c4e1ef6..33d75f9 100644
--- a/ash/wallpaper/wallpaper_controller_impl.cc
+++ b/ash/wallpaper/wallpaper_controller_impl.cc
@@ -44,7 +44,6 @@
 #include "base/barrier_closure.h"
 #include "base/check.h"
 #include "base/command_line.h"
-#include "base/files/file_enumerator.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
@@ -536,27 +535,6 @@
     base::CreateDirectory(user_directory);
 }
 
-// Implementation of |WallpaperControllerImpl::GetOfflineWallpaper|.
-std::vector<std::string> GetOfflineWallpaperListImpl() {
-  DCHECK(!GlobalChromeOSWallpapersDir().empty());
-  std::vector<std::string> url_list;
-  if (base::DirectoryExists(GlobalChromeOSWallpapersDir())) {
-    base::FileEnumerator files(GlobalChromeOSWallpapersDir(),
-                               /*recursive=*/false,
-                               base::FileEnumerator::FILES);
-    for (base::FilePath current = files.Next(); !current.empty();
-         current = files.Next()) {
-      // Do not add file name of small resolution wallpaper to the list.
-      if (!base::EndsWith(current.BaseName().RemoveExtension().value(),
-                          kSmallWallpaperSuffix,
-                          base::CompareCase::SENSITIVE)) {
-        url_list.push_back(current.BaseName().value());
-      }
-    }
-  }
-  return url_list;
-}
-
 // Returns the type of the user with the specified |id| or USER_TYPE_REGULAR.
 user_manager::UserType GetUserType(const AccountId& id) {
   const UserSession* user_session =
@@ -1621,13 +1599,6 @@
   SetDefaultWallpaper(account_id, show_wallpaper, base::DoNothing());
 }
 
-void WallpaperControllerImpl::GetOfflineWallpaperList(
-    GetOfflineWallpaperListCallback callback) {
-  sequenced_task_runner_->PostTaskAndReplyWithResult(
-      FROM_HERE, base::BindOnce(&GetOfflineWallpaperListImpl),
-      std::move(callback));
-}
-
 void WallpaperControllerImpl::SetAnimationDuration(
     base::TimeDelta animation_duration) {
   animation_duration_ = animation_duration;
diff --git a/ash/wallpaper/wallpaper_controller_impl.h b/ash/wallpaper/wallpaper_controller_impl.h
index 007ebde..009588c 100644
--- a/ash/wallpaper/wallpaper_controller_impl.h
+++ b/ash/wallpaper/wallpaper_controller_impl.h
@@ -297,8 +297,6 @@
   void RemoveAlwaysOnTopWallpaper() override;
   void RemoveUserWallpaper(const AccountId& account_id) override;
   void RemovePolicyWallpaper(const AccountId& account_id) override;
-  void GetOfflineWallpaperList(
-      GetOfflineWallpaperListCallback callback) override;
   void SetAnimationDuration(base::TimeDelta animation_duration) override;
   void OpenWallpaperPickerIfAllowed() override;
   void MinimizeInactiveWindows(const std::string& user_id_hash) override;
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc
index 68803b34..062130b0 100644
--- a/ash/wallpaper/wallpaper_controller_unittest.cc
+++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -1214,14 +1214,8 @@
 
   // Verify that the wallpaper with |url| is available offline, and the returned
   // file name should not contain the small wallpaper suffix.
-  run_loop = std::make_unique<base::RunLoop>();
-  controller_->GetOfflineWallpaperList(base::BindLambdaForTesting(
-      [&run_loop](const std::vector<std::string>& url_list) {
-        EXPECT_EQ(1U, url_list.size());
-        EXPECT_EQ(GURL(kDummyUrl).ExtractFileName(), url_list[0]);
-        run_loop->Quit();
-      }));
-  run_loop->Run();
+  EXPECT_TRUE(base::PathExists(online_wallpaper_dir_.GetPath().Append(
+      GURL(kDummyUrl).ExtractFileName())));
 }
 
 TEST_F(WallpaperControllerTest, SetAndRemovePolicyWallpaper) {
diff --git a/ash/webui/camera_app_ui/resources/js/externs/types.d.ts b/ash/webui/camera_app_ui/resources/js/externs/types.d.ts
index ca7c7141..ef334fa 100644
--- a/ash/webui/camera_app_ui/resources/js/externs/types.d.ts
+++ b/ash/webui/camera_app_ui/resources/js/externs/types.d.ts
@@ -131,9 +131,6 @@
   rtpTimestamp?: number;
 }
 
-type VideoFrameRequestCallback =
-    (now: DOMHighResTimeStamp, metadata: VideoFrameMetadata) => void;
-
 interface HTMLVideoElement {
   requestVideoFrameCallback(callback: VideoFrameRequestCallback): number;
   cancelVideoFrameCallback(handle: number): undefined;
diff --git a/ash/webui/camera_app_ui/resources/js/lib/comlink.ts b/ash/webui/camera_app_ui/resources/js/lib/comlink.ts
index 62eac595..03df7ae0 100644
--- a/ash/webui/camera_app_ui/resources/js/lib/comlink.ts
+++ b/ash/webui/camera_app_ui/resources/js/lib/comlink.ts
@@ -477,7 +477,7 @@
   return obj;
 }
 
-export function proxy<T>(obj: T): T&ProxyMarked {
+export function proxy<T extends {}>(obj: T): T&ProxyMarked {
   return Object.assign(obj, {[proxyMarker]: true}) as any;
 }
 
diff --git a/ash/webui/camera_app_ui/resources/js/mojo/device_operator.ts b/ash/webui/camera_app_ui/resources/js/mojo/device_operator.ts
index 56dddd50..afe1058 100644
--- a/ash/webui/camera_app_ui/resources/js/mojo/device_operator.ts
+++ b/ash/webui/camera_app_ui/resources/js/mojo/device_operator.ts
@@ -746,7 +746,8 @@
         const val = Reflect.get(target, property);
         if (val instanceof Function) {
           return (...args: unknown[]) => operationQueue.push(
-                     () => Reflect.apply(val, target, args));
+                     () =>
+                         Reflect.apply(val, target, args) as Promise<unknown>);
         }
         return val;
       },
diff --git a/ash/webui/camera_app_ui/resources/js/mojo/util.ts b/ash/webui/camera_app_ui/resources/js/mojo/util.ts
index 8476f80..ca69a23b 100644
--- a/ash/webui/camera_app_ui/resources/js/mojo/util.ts
+++ b/ash/webui/camera_app_ui/resources/js/mojo/util.ts
@@ -48,7 +48,8 @@
           // would be uncaught exception if we try to call the mojo function.
           return NEVER_SETTLED_PROMISE;
         }
-        return wrapMojoResponse(Reflect.apply(val, target, args));
+        return wrapMojoResponse(
+            Reflect.apply(val, target, args) as Promise<unknown>| undefined);
       };
     }
     return val;
diff --git a/ash/webui/camera_app_ui/resources/tsconfig_base.json b/ash/webui/camera_app_ui/resources/tsconfig_base.json
index 2662ad2..df6aabb 100644
--- a/ash/webui/camera_app_ui/resources/tsconfig_base.json
+++ b/ash/webui/camera_app_ui/resources/tsconfig_base.json
@@ -6,7 +6,6 @@
     "target": "esnext",
     "typeRoots": ["../../../../third_party/node/node_modules/@types"],
     "types": [
-      "dom-mediacapture-record",
       "google.analytics",
       "offscreencanvas",
       "trusted-types",
diff --git a/ash/webui/diagnostics_ui/resources/mojo_interface_provider.js b/ash/webui/diagnostics_ui/resources/mojo_interface_provider.js
index 2c89402b..838b52b5 100644
--- a/ash/webui/diagnostics_ui/resources/mojo_interface_provider.js
+++ b/ash/webui/diagnostics_ui/resources/mojo_interface_provider.js
@@ -4,7 +4,7 @@
 
 import {assert} from 'chrome://resources/ash/common/assert.js';
 
-import {fakeAllNetworksAvailable, fakeBatteryChargeStatus, fakeBatteryHealth, fakeBatteryInfo, fakeCellularNetwork, fakeCpuUsage, fakeEthernetNetwork, fakeKeyboards, fakeMemoryUsage, fakePowerRoutineResults, fakeRoutineResults, fakeSystemInfo, fakeTouchDevices, fakeWifiNetwork} from './fake_data.js';
+import {fakeAllNetworksAvailable, fakeBatteryChargeStatus, fakeBatteryHealth, fakeBatteryInfo, fakeCellularNetwork, fakeCpuUsage, fakeEthernetNetwork, fakeKeyboards, fakeMemoryUsage, fakeSystemInfo, fakeTouchDevices, fakeWifiNetwork} from './fake_data.js';
 import {FakeInputDataProvider} from './fake_input_data_provider.js';
 import {FakeNetworkHealthProvider} from './fake_network_health_provider.js';
 import {FakeSystemDataProvider} from './fake_system_data_provider.js';
diff --git a/ash/webui/eche_app_ui/launch_app_helper.cc b/ash/webui/eche_app_ui/launch_app_helper.cc
index 0733ae0..e90b541 100644
--- a/ash/webui/eche_app_ui/launch_app_helper.cc
+++ b/ash/webui/eche_app_ui/launch_app_helper.cc
@@ -11,6 +11,7 @@
 #include "ash/shell.h"
 #include "ash/webui/eche_app_ui/eche_alert_generator.h"
 #include "base/check.h"
+#include "base/metrics/histogram_functions.h"
 #include "chromeos/ash/components/phonehub/phone_hub_manager.h"
 #include "chromeos/ash/components/phonehub/screen_lock_manager.h"
 #include "ui/gfx/image/image.h"
@@ -18,6 +19,14 @@
 namespace ash {
 namespace eche_app {
 
+namespace {
+
+// TODO(b/265173006): Create an AppMetricsRecorder class to abstract metrics
+// logging from implementation classes.
+constexpr base::TimeDelta kPackageSetResetFrequency = base::Days(1);
+
+}  // namespace
+
 LaunchAppHelper::NotificationInfo::NotificationInfo(
     Category category,
     absl::variant<NotificationType, mojom::WebNotificationType> type)
@@ -88,9 +97,25 @@
                                     const std::u16string& visible_name,
                                     const absl::optional<int64_t>& user_id,
                                     const gfx::Image& icon,
-                                    const std::u16string& phone_name) const {
+                                    const std::u16string& phone_name) {
   launch_eche_app_function_.Run(notification_id, package_name, visible_name,
                                 user_id, icon, phone_name);
+
+  // Sessions can last for well over a day, so this check exists to cover that
+  // corner case and clears the |session_packages_launched_| set so we can
+  // start tracking unique packages again.
+  // TODO(b/265172591): Optimize the reset to align with histogram uploads.
+  if (session_packages_last_reset_ == base::TimeTicks() ||
+      base::TimeTicks::Now() - session_packages_last_reset_ >=
+          kPackageSetResetFrequency) {
+    session_packages_launched_.clear();
+    session_packages_last_reset_ = base::TimeTicks::Now();
+  }
+
+  if (!session_packages_launched_.contains(package_name)) {
+    base::UmaHistogramCounts1000("Eche.UniqueAppsStreamed.PerDay", 1);
+    session_packages_launched_.insert(package_name);
+  }
 }
 
 }  // namespace eche_app
diff --git a/ash/webui/eche_app_ui/launch_app_helper.h b/ash/webui/eche_app_ui/launch_app_helper.h
index 29374d4..66a4100 100644
--- a/ash/webui/eche_app_ui/launch_app_helper.h
+++ b/ash/webui/eche_app_ui/launch_app_helper.h
@@ -7,7 +7,9 @@
 
 #include "ash/webui/eche_app_ui/feature_status.h"
 #include "ash/webui/eche_app_ui/mojom/eche_app.mojom.h"
+#include "base/containers/flat_set.h"
 #include "base/functional/callback.h"
+#include "base/timer/timer.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/abseil-cpp/absl/types/variant.h"
 
@@ -114,10 +116,18 @@
                      const std::u16string& visible_name,
                      const absl::optional<int64_t>& user_id,
                      const gfx::Image& icon,
-                     const std::u16string& phone_name) const;
+                     const std::u16string& phone_name);
+
+  const base::flat_set<std::string> GetSessionPackagesLaunchedForTest() const {
+    return session_packages_launched_;
+  }
 
  private:
   bool IsScreenLockRequired() const;
+
+  base::flat_set<std::string> session_packages_launched_;
+  base::TimeTicks session_packages_last_reset_ = base::TimeTicks();
+
   phonehub::PhoneHubManager* phone_hub_manager_;
   LaunchEcheAppFunction launch_eche_app_function_;
   LaunchNotificationFunction launch_notification_function_;
diff --git a/ash/webui/eche_app_ui/launch_app_helper_unittest.cc b/ash/webui/eche_app_ui/launch_app_helper_unittest.cc
index 934e134..3b7068d 100644
--- a/ash/webui/eche_app_ui/launch_app_helper_unittest.cc
+++ b/ash/webui/eche_app_ui/launch_app_helper_unittest.cc
@@ -11,8 +11,10 @@
 #include "ash/shell.h"
 #include "ash/system/toast/toast_manager_impl.h"
 #include "ash/test/ash_test_base.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
+#include "base/timer/timer.h"
 #include "chromeos/ash/components/phonehub/fake_phone_hub_manager.h"
 #include "chromeos/ash/components/phonehub/screen_lock_manager.h"
 #include "chromeos/ash/components/test/ash_test_suite.h"
@@ -24,6 +26,13 @@
 namespace ash {
 namespace eche_app {
 
+namespace {
+
+constexpr auto kOneDay = base::Days(1u);
+constexpr char kUniqueAppsMetricName[] = "Eche.UniqueAppsStreamed.PerDay";
+
+}  // namespace
+
 class Callback {
  public:
   static void LaunchEcheAppFunction(
@@ -63,7 +72,8 @@
 
 class LaunchAppHelperTest : public ash::AshTestBase {
  protected:
-  LaunchAppHelperTest() = default;
+  LaunchAppHelperTest()
+      : ash::AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
   LaunchAppHelperTest(const LaunchAppHelperTest&) = delete;
   LaunchAppHelperTest& operator=(const LaunchAppHelperTest&) = delete;
   ~LaunchAppHelperTest() override = default;
@@ -129,6 +139,10 @@
     launch_app_helper_->CloseNotification(notification_id);
   }
 
+  const base::flat_set<std::string> GetLaunchAppHelperPackageSet() {
+    return launch_app_helper_->GetSessionPackagesLaunchedForTest();
+  }
+
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
   std::unique_ptr<phonehub::FakePhoneHubManager> fake_phone_hub_manager_;
@@ -204,5 +218,77 @@
   EXPECT_TRUE(Callback::getCloseNotification());
 }
 
+TEST_F(LaunchAppHelperTest, UniqueAppPackages) {
+  base::HistogramTester histogram_tester;
+
+  const absl::optional<int64_t> notification_id = 0;
+  const std::string package_name = "package_name";
+  const std::u16string visible_name = u"visible_name";
+  const absl::optional<int64_t> user_id = 0;
+  const std::u16string phone_name = u"your phone";
+
+  const absl::optional<int64_t> notification_id2 = 1;
+  const std::string package_name2 = "package_name2";
+  const std::u16string visible_name2 = u"visible_name2";
+
+  LaunchEcheApp(notification_id, package_name, visible_name, user_id,
+                gfx::Image(), phone_name);
+
+  histogram_tester.ExpectTotalCount(kUniqueAppsMetricName, 1);
+  EXPECT_EQ(1u, GetLaunchAppHelperPackageSet().size());
+
+  LaunchEcheApp(notification_id, package_name, visible_name, user_id,
+                gfx::Image(), phone_name);
+
+  histogram_tester.ExpectTotalCount(kUniqueAppsMetricName, 1);
+  EXPECT_EQ(1u, GetLaunchAppHelperPackageSet().size());
+
+  LaunchEcheApp(notification_id2, package_name2, visible_name2, user_id,
+                gfx::Image(), phone_name);
+
+  histogram_tester.ExpectTotalCount(kUniqueAppsMetricName, 2);
+  EXPECT_EQ(2u, GetLaunchAppHelperPackageSet().size());
+}
+
+TEST_F(LaunchAppHelperTest, SessionPackagesResetsAfterOneDay) {
+  base::HistogramTester histogram_tester;
+
+  const absl::optional<int64_t> notification_id = 0;
+  const std::string package_name = "package_name";
+  const std::u16string visible_name = u"visible_name";
+  const absl::optional<int64_t> user_id = 0;
+  const std::u16string phone_name = u"your phone";
+
+  const absl::optional<int64_t> notification_id2 = 1;
+  const std::string package_name2 = "package_name2";
+  const std::u16string visible_name2 = u"visible_name2";
+
+  LaunchEcheApp(notification_id, package_name, visible_name, user_id,
+                gfx::Image(), phone_name);
+
+  histogram_tester.ExpectTotalCount(kUniqueAppsMetricName, 1);
+  EXPECT_EQ(1u, GetLaunchAppHelperPackageSet().size());
+
+  LaunchEcheApp(notification_id2, package_name2, visible_name2, user_id,
+                gfx::Image(), phone_name);
+
+  histogram_tester.ExpectTotalCount(kUniqueAppsMetricName, 2);
+  EXPECT_EQ(2u, GetLaunchAppHelperPackageSet().size());
+
+  task_environment()->FastForwardBy(kOneDay);
+
+  LaunchEcheApp(notification_id, package_name, visible_name, user_id,
+                gfx::Image(), phone_name);
+
+  histogram_tester.ExpectTotalCount(kUniqueAppsMetricName, 3);
+  EXPECT_EQ(1u, GetLaunchAppHelperPackageSet().size());
+
+  LaunchEcheApp(notification_id, package_name, visible_name, user_id,
+                gfx::Image(), phone_name);
+
+  histogram_tester.ExpectTotalCount(kUniqueAppsMetricName, 3);
+  EXPECT_EQ(1u, GetLaunchAppHelperPackageSet().size());
+}
+
 }  // namespace eche_app
 }  // namespace ash
diff --git a/ash/webui/personalization_app/resources/js/personalization_reducers.ts b/ash/webui/personalization_app/resources/js/personalization_reducers.ts
index 3b40bfabb..3c198b70 100644
--- a/ash/webui/personalization_app/resources/js/personalization_reducers.ts
+++ b/ash/webui/personalization_app/resources/js/personalization_reducers.ts
@@ -31,8 +31,9 @@
  * Combines reducers into a single top level reducer. Inspired by Redux's
  * |combineReducers| functions.
  */
-function combineReducers<T>(mapping: {[K in keyof T]: ReducerFunction<T[K]>}): (
-    state: T, action: Actions, globalState: PersonalizationState) => T {
+function combineReducers<T extends {}>(
+    mapping: {[K in keyof T]: ReducerFunction<T[K]>}):
+    (state: T, action: Actions, globalState: PersonalizationState) => T {
   function reduce(
       state: T, action: Actions, globalState: PersonalizationState): T {
     const newState: T =
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc
index 28176326..f566e7f 100644
--- a/ash/wm/desks/desks_controller.cc
+++ b/ash/wm/desks/desks_controller.cc
@@ -1914,8 +1914,6 @@
     views::Widget* widget = views::Widget::GetWidgetForNativeView(window);
     DCHECK(widget);
 
-    widget->Close();
-
     // `widget->Close();` calls the underlying `native_widget_->Close()` which
     // will schedule `native_widget_->CloseNow()` as an async task. Only
     // when `native_widget_->CloseNow()` finishes running, the window will
@@ -1940,6 +1938,11 @@
           ->GetChildById(kShellWindowId_UnparentedContainer)
           ->AddChild(window);
     }
+
+    // We need to ensure that `widget->Close()` is called after we move the
+    // windows to the unparented container because some windows lose access to
+    // their root window immediately when their widget starts closing.
+    widget->Close();
   }
 
   // Schedules a delayed task to forcefully close all windows that have not
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc
index 01ec021b..50f4537 100644
--- a/ash/wm/overview/overview_session_unittest.cc
+++ b/ash/wm/overview/overview_session_unittest.cc
@@ -3589,6 +3589,54 @@
       base::Contains(controller->desks()[1]->windows(), normal_window.get()));
 }
 
+// Tests that the overview item associated with the floated window appears
+// underneath the about to be dragged window after long pressing.
+TEST_F(FloatOverviewSessionTest, LongPressingWithFloatedWindow) {
+  // Shorten the long press times so we don't have to delay as long.
+  ui::GestureConfiguration* gesture_config =
+      ui::GestureConfiguration::GetInstance();
+  gesture_config->set_long_press_time_in_ms(1);
+  gesture_config->set_short_press_time(base::Milliseconds(1));
+  gesture_config->set_show_press_delay_in_ms(1);
+
+  // Create one normal and one floated window.
+  auto normal_window = CreateAppWindow();
+  auto floated_window = CreateAppWindow();
+  PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+  ASSERT_TRUE(WindowState::Get(floated_window.get())->IsFloated());
+
+  ToggleOverview();
+
+  // Simulate a long press on the overview item of the normal window.
+  OverviewItem* normal_item = GetOverviewItemForWindow(normal_window.get());
+  ui::test::EventGenerator* generator = GetEventGenerator();
+  generator->set_current_screen_location(
+      gfx::ToRoundedPoint(normal_item->target_bounds().CenterPoint()));
+  generator->PressTouch();
+  base::RunLoop run_loop;
+  base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
+      FROM_HERE, run_loop.QuitClosure(), base::Milliseconds(2));
+  run_loop.Run();
+
+  // After long pressing, the float container should be stacked under the desk
+  // container so that the overview item of the float window appears underneath
+  // during the drag.
+  for (aura::Window* root : Shell::GetAllRootWindows()) {
+    EXPECT_TRUE(
+        IsStackedBelow(root->GetChildById(kShellWindowId_FloatContainer),
+                       root->GetChildById(kShellWindowId_DeskContainerA)));
+  }
+
+  // Test that on release, the float container is stacked above the desk
+  // container again.
+  generator->ReleaseTouch();
+  for (aura::Window* root : Shell::GetAllRootWindows()) {
+    EXPECT_TRUE(
+        IsStackedBelow(root->GetChildById(kShellWindowId_DeskContainerA),
+                       root->GetChildById(kShellWindowId_FloatContainer)));
+  }
+}
+
 class TabletModeOverviewSessionTest : public OverviewTestBase {
  public:
   TabletModeOverviewSessionTest() = default;
diff --git a/ash/wm/overview/overview_window_drag_controller.cc b/ash/wm/overview/overview_window_drag_controller.cc
index 8328d705..08e0fe7b 100644
--- a/ash/wm/overview/overview_window_drag_controller.cc
+++ b/ash/wm/overview/overview_window_drag_controller.cc
@@ -323,17 +323,6 @@
       StartNormalDragMode(location_in_screen);
     else
       return;
-
-    if (chromeos::wm::features::IsFloatWindowEnabled()) {
-      if (auto* float_window =
-              Shell::Get()->float_controller()->FindFloatedWindowOfDesk(
-                  DesksController::Get()->active_desk())) {
-        // If the float window is dragged, it will be on top of everything as
-        // expected.
-        if (item_->GetWindow() != float_window)
-          float_drag_helper_ = std::make_unique<ScopedFloatDragHelper>(this);
-      }
-    }
   }
 
   if (current_drag_behavior_ == DragBehavior::kDragToClose)
@@ -458,6 +447,8 @@
           grid_desks_bar_data.shrink_bounds.origin();
     }
   }
+
+  MaybeCreateFloatDragHelper();
 }
 
 OverviewWindowDragController::DragResult OverviewWindowDragController::Fling(
@@ -547,6 +538,7 @@
       ->StartNudge(item_);
 
   item_->UpdateShadowTypeForDrag(/*is_dragging=*/true);
+  MaybeCreateFloatDragHelper();
 }
 
 void OverviewWindowDragController::ContinueDragToClose(
@@ -978,6 +970,23 @@
                  : kClamshellDrag[action]);
 }
 
+void OverviewWindowDragController::MaybeCreateFloatDragHelper() {
+  if (!chromeos::wm::features::IsFloatWindowEnabled()) {
+    return;
+  }
+
+  if (auto* float_window =
+          Shell::Get()->float_controller()->FindFloatedWindowOfDesk(
+              DesksController::Get()->active_desk())) {
+    DCHECK(item_);
+    // If the float window is dragged, it will be on top of everything as
+    // expected.
+    if (item_->GetWindow() != float_window) {
+      float_drag_helper_ = std::make_unique<ScopedFloatDragHelper>(this);
+    }
+  }
+}
+
 void OverviewWindowDragController::DestroyFloatDragHelper() {
   float_drag_helper_.reset();
 }
diff --git a/ash/wm/overview/overview_window_drag_controller.h b/ash/wm/overview/overview_window_drag_controller.h
index dbabb9f..1fba1cf 100644
--- a/ash/wm/overview/overview_window_drag_controller.h
+++ b/ash/wm/overview/overview_window_drag_controller.h
@@ -176,6 +176,11 @@
                         bool is_dragged_to_other_display) const;
   void RecordDragToClose(DragToCloseAction action) const;
 
+  // Creates `float_drag_helper_` if needed. The helper will temporarily stack
+  // the float container under the active desk container, so that dragging
+  // regular windows appear above overview items of floated windows.
+  void MaybeCreateFloatDragHelper();
+
   // Called by `float_drag_helper_` to destroy itself as it may need to live
   // after a gesture is completed if there is an animation.
   void DestroyFloatDragHelper();
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc
index 117e062e..8756a3b 100644
--- a/base/metrics/field_trial.cc
+++ b/base/metrics/field_trial.cc
@@ -517,22 +517,6 @@
 }
 
 // static
-void FieldTrialList::StatesToString(std::string* output) {
-  FieldTrial::ActiveGroups active_groups;
-  GetActiveFieldTrialGroups(&active_groups);
-  for (const auto& active_group : active_groups) {
-    DCHECK_EQ(std::string::npos,
-              active_group.trial_name.find(kPersistentStringSeparator));
-    DCHECK_EQ(std::string::npos,
-              active_group.group_name.find(kPersistentStringSeparator));
-    output->append(active_group.trial_name);
-    output->append(1, kPersistentStringSeparator);
-    output->append(active_group.group_name);
-    output->append(1, kPersistentStringSeparator);
-  }
-}
-
-// static
 std::vector<FieldTrial::State> FieldTrialList::GetAllFieldTrialStates(
     PassKey<test::ScopedFeatureList>) {
   std::vector<FieldTrial::State> states;
diff --git a/base/metrics/field_trial.h b/base/metrics/field_trial.h
index 67496e3..efa8ff6 100644
--- a/base/metrics/field_trial.h
+++ b/base/metrics/field_trial.h
@@ -371,9 +371,9 @@
 
 //------------------------------------------------------------------------------
 // Class with a list of all active field trials.  A trial is active if it has
-// been registered, which includes evaluating its state based on its probaility.
-// Only one instance of this class exists and outside of testing, will live for
-// the entire life time of the process.
+// been registered, which includes evaluating its state based on its
+// probability. Only one instance of this class exists and outside of testing,
+// will live for the entire life time of the process.
 class BASE_EXPORT FieldTrialList {
  public:
   using FieldTrialAllocator = PersistentMemoryAllocator;
@@ -450,16 +450,6 @@
   // Returns true if the named trial exists and has been activated.
   static bool IsTrialActive(StringPiece trial_name);
 
-  // Creates a persistent representation of active FieldTrial instances for
-  // resurrection in another process. This allows randomization to be done in
-  // one process, and secondary processes can be synchronized on the result.
-  // The resulting string contains the name and group name pairs of all
-  // registered FieldTrials for which the group has been chosen and externally
-  // observed (via |group()|) and which have not been disabled, with "/" used
-  // to separate all names and to terminate the string. This string is parsed
-  // by |CreateTrialsFromString()|.
-  static void StatesToString(std::string* output);
-
   // Creates a persistent representation of all FieldTrial instances for
   // resurrection in another process. This allows randomization to be done in
   // one process, and secondary processes can be synchronized on the result.
@@ -499,7 +489,7 @@
       const CommandLine& command_line,
       FieldTrial::ActiveGroups* active_groups);
 
-  // Use a state string (re: StatesToString()) to augment the current list of
+  // Use a state string (re: AllStatesToString()) to augment the current list of
   // field trials to include the supplied trials, and using a 100% probability
   // for each trial, force them to have the same group string. This is commonly
   // used in a non-browser process, to carry randomly selected state in a
diff --git a/base/metrics/field_trial_unittest.cc b/base/metrics/field_trial_unittest.cc
index 22313e5..2699806 100644
--- a/base/metrics/field_trial_unittest.cc
+++ b/base/metrics/field_trial_unittest.cc
@@ -338,43 +338,6 @@
   EXPECT_TRUE(FieldTrialList::IsTrialActive(kTrialName));
 }
 
-TEST_F(FieldTrialTest, Save) {
-  std::string save_string;
-
-  scoped_refptr<FieldTrial> trial =
-      CreateFieldTrial("Some name", 10, "Default some name");
-  // There is no winner yet, so no textual group name is associated with trial.
-  // In this case, the trial should not be included.
-  EXPECT_EQ("", trial->group_name_internal());
-  FieldTrialList::StatesToString(&save_string);
-  EXPECT_EQ("", save_string);
-  save_string.clear();
-
-  // Create a winning group.
-  trial->AppendGroup("Winner", 10);
-  trial->Activate();
-  FieldTrialList::StatesToString(&save_string);
-  EXPECT_EQ("Some name/Winner/", save_string);
-  save_string.clear();
-
-  // Create a second trial and winning group.
-  scoped_refptr<FieldTrial> trial2 = CreateFieldTrial("xxx", 10, "Default xxx");
-  trial2->AppendGroup("yyyy", 10);
-  trial2->Activate();
-
-  FieldTrialList::StatesToString(&save_string);
-  // We assume names are alphabetized... though this is not critical.
-  EXPECT_EQ("Some name/Winner/xxx/yyyy/", save_string);
-  save_string.clear();
-
-  // Create a third trial with only the default group.
-  scoped_refptr<FieldTrial> trial3 = CreateFieldTrial("zzz", 10, "default");
-  trial3->Activate();
-
-  FieldTrialList::StatesToString(&save_string);
-  EXPECT_EQ("Some name/Winner/xxx/yyyy/zzz/default/", save_string);
-}
-
 TEST_F(FieldTrialTest, SaveAll) {
   std::string save_string;
 
@@ -459,8 +422,9 @@
   trial->AppendGroup("Winner", 10);
   trial->Activate();
   std::string save_string;
-  FieldTrialList::StatesToString(&save_string);
-  EXPECT_EQ("Some name/Winner/", save_string);
+  FieldTrialList::AllStatesToString(&save_string);
+  // * prefix since it is activated.
+  EXPECT_EQ("*Some name/Winner/", save_string);
 
   // It is OK if we redundantly specify a winner.
   EXPECT_TRUE(FieldTrialList::CreateTrialsFromString(save_string));
@@ -854,9 +818,9 @@
     FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
     EXPECT_TRUE(active_groups.empty());
 
-    // The trial shouldn't be listed in the |StatesToString()| result.
+    // The trial shouldn't be listed in the |AllStatesToString()| result.
     std::string states;
-    FieldTrialList::StatesToString(&states);
+    FieldTrialList::AllStatesToString(&states);
     EXPECT_TRUE(states.empty());
   }
 }
diff --git a/base/task/sequence_manager/task_queue_impl.h b/base/task/sequence_manager/task_queue_impl.h
index 57ec8ad..874d3b1 100644
--- a/base/task/sequence_manager/task_queue_impl.h
+++ b/base/task/sequence_manager/task_queue_impl.h
@@ -555,7 +555,7 @@
       OnTaskPostedCallbackHandleImpl* on_task_posted_callback_handle);
 
   QueueName name_;
-  const raw_ptr<SequenceManagerImpl> sequence_manager_;
+  const raw_ptr<SequenceManagerImpl, DanglingUntriaged> sequence_manager_;
 
   const scoped_refptr<const AssociatedThreadId> associated_thread_;
 
diff --git a/build/android/gradle/generate_gradle.py b/build/android/gradle/generate_gradle.py
index 91def72..d6e603e 100755
--- a/build/android/gradle/generate_gradle.py
+++ b/build/android/gradle/generate_gradle.py
@@ -904,10 +904,12 @@
     targets = _RebasePath(generated_inputs, output_dir)
     _RunNinja(output_dir, targets)
 
-  logging.warning('Generated files will only appear once you\'ve built them.')
-  logging.warning('Generated projects for Android Studio %s', channel)
-  logging.warning('For more tips: https://chromium.googlesource.com/chromium'
-                  '/src.git/+/main/docs/android_studio.md')
+  print('Generated projects for Android Studio ' + channel)
+  print('** Building using Android Studio / Gradle does not work.')
+  print('** This project is only for IDE editing & tools.')
+  print('Note: Generated files will appear only if they have been built')
+  print('For more tips: https://chromium.googlesource.com/chromium/src.git/'
+        '+/main/docs/android_studio.md')
 
 
 if __name__ == '__main__':
diff --git a/build/clobber.py b/build/clobber.py
index b84027b0..91927774 100755
--- a/build/clobber.py
+++ b/build/clobber.py
@@ -7,47 +7,119 @@
 
 import argparse
 import os
+import shutil
 import subprocess
 import sys
 
 
-_SRC_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+def extract_gn_build_commands(build_ninja_file):
+  """Extracts from a build.ninja the commands to run GN.
+
+  The commands to run GN are the gn rule and build.ninja build step at the
+  top of the build.ninja file. We want to keep these when deleting GN builds
+  since we want to preserve the command-line flags to GN.
+
+  On error, returns the empty string."""
+  result = ""
+  with open(build_ninja_file, 'r') as f:
+    # Reads until the first empty line after the "build build.ninja:" target.
+    # We assume everything before it necessary as well (eg the
+    # "ninja_required_version" line).
+    found_build_dot_ninja_target = False
+    for line in f.readlines():
+      result += line
+      if line.startswith('build build.ninja:'):
+        found_build_dot_ninja_target = True
+      if found_build_dot_ninja_target and line[0] == '\n':
+        return result
+  return ''  # We got to EOF and didn't find what we were looking for.
 
 
-def _gn_cmd(cmd, build_dir):
-  gn_exe = 'gn'
-  if sys.platform == 'win32':
-    gn_exe += '.bat'
-  return [gn_exe, cmd, '--root=%s' % _SRC_DIR, '-C', build_dir]
+def delete_dir(build_dir):
+  if os.path.islink(build_dir):
+    return
+  # For unknown reasons (anti-virus?) rmtree of Chromium build directories
+  # often fails on Windows.
+  if sys.platform.startswith('win'):
+    subprocess.check_call(['rmdir', '/s', '/q', build_dir], shell=True)
+  else:
+    shutil.rmtree(build_dir)
 
 
-def _generate_build_ninja(build_dir):
-  gn_gen_cmd = _gn_cmd('gen', build_dir)
-  print('Running %s' % ' '.join(gn_gen_cmd))
-  subprocess.run(gn_gen_cmd, check=True)
+def delete_build_dir(build_dir):
+  # GN writes a build.ninja.d file. Note that not all GN builds have args.gn.
+  build_ninja_d_file = os.path.join(build_dir, 'build.ninja.d')
+  if not os.path.exists(build_ninja_d_file):
+    delete_dir(build_dir)
+    return
 
+  # GN builds aren't automatically regenerated when you sync. To avoid
+  # messing with the GN workflow, erase everything but the args file, and
+  # write a dummy build.ninja file that will automatically rerun GN the next
+  # time Ninja is run.
+  build_ninja_file = os.path.join(build_dir, 'build.ninja')
+  build_commands = extract_gn_build_commands(build_ninja_file)
 
-def _clean_build_dir(build_dir):
-  print('Cleaning %s' % build_dir)
-
-  gn_clean_cmd = _gn_cmd('clean', build_dir)
-  print('Running %s' % ' '.join(gn_clean_cmd))
   try:
-    subprocess.run(gn_clean_cmd, check=True)
-  except Exception:
-    # gn clean may fail when build.ninja is corrupted or missing.
-    # Regenerate build.ninja and retry gn clean again.
-    _generate_build_ninja(build_dir)
-    print('Running %s' % ' '.join(gn_clean_cmd))
-    subprocess.run(gn_clean_cmd, check=True)
+    gn_args_file = os.path.join(build_dir, 'args.gn')
+    with open(gn_args_file, 'r') as f:
+      args_contents = f.read()
+  except IOError:
+    args_contents = ''
+
+  exception_during_rm = None
+  try:
+    # delete_dir and os.mkdir() may fail, such as when chrome.exe is running,
+    # and we still want to restore args.gn/build.ninja/build.ninja.d, so catch
+    # the exception and rethrow it later.
+    delete_dir(build_dir)
+    os.mkdir(build_dir)
+  except Exception as e:
+    exception_during_rm = e
+
+  # Put back the args file (if any).
+  if args_contents != '':
+    with open(gn_args_file, 'w') as f:
+      f.write(args_contents)
+
+  # Write the build.ninja file sufficiently to regenerate itself.
+  with open(os.path.join(build_dir, 'build.ninja'), 'w') as f:
+    if build_commands != '':
+      f.write(build_commands)
+    else:
+      # Couldn't parse the build.ninja file, write a default thing.
+      f.write('''ninja_required_version = 1.7.2
+
+rule gn
+  command = gn -q gen //out/%s/
+  description = Regenerating ninja files
+
+build build.ninja: gn
+  generator = 1
+  depfile = build.ninja.d
+''' % (os.path.split(build_dir)[1]))
+
+  # Write a .d file for the build which references a nonexistant file. This
+  # will make Ninja always mark the build as dirty.
+  with open(build_ninja_d_file, 'w') as f:
+    f.write('build.ninja: nonexistant_file.gn\n')
+
+  if exception_during_rm:
+    # Rethrow the exception we caught earlier.
+    raise exception_during_rm
 
 
 def clobber(out_dir):
-  """Clobber contents of build directory."""
+  """Clobber contents of build directory.
+
+  Don't delete the directory itself: some checkouts have the build directory
+  mounted."""
   for f in os.listdir(out_dir):
     path = os.path.join(out_dir, f)
-    if os.path.isdir(path):
-      _clean_build_dir(path)
+    if os.path.isfile(path):
+      os.unlink(path)
+    elif os.path.isdir(path):
+      delete_build_dir(path)
 
 
 def main():
diff --git a/build/clobber_unittest.py b/build/clobber_unittest.py
index 990926c..908718d 100755
--- a/build/clobber_unittest.py
+++ b/build/clobber_unittest.py
@@ -7,33 +7,125 @@
 import pathlib
 import shutil
 import tempfile
+import textwrap
 import unittest
+from unittest import mock
 
 import clobber
 
 
-class TestClean(unittest.TestCase):
+class TestExtractBuildCommand(unittest.TestCase):
+  def setUp(self):
+    _, self.build_ninja_path = tempfile.mkstemp(text=True)
+
+  def tearDown(self):
+    os.remove(self.build_ninja_path)
+
+  def test_normal_extraction(self):
+    build_ninja_file_contents = textwrap.dedent("""
+        ninja_required_version = 1.7.2
+
+        rule gn
+          command = ../../buildtools/gn --root=../.. -q --regeneration gen .
+          pool = console
+          description = Regenerating ninja files
+
+        build build.ninja.stamp: gn
+          generator = 1
+          depfile = build.ninja.d
+
+        build build.ninja: phony build.ninja.stamp
+          generator = 1
+
+        pool build_toolchain_action_pool
+          depth = 72
+
+        pool build_toolchain_link_pool
+          depth = 23
+
+        subninja toolchain.ninja
+        subninja clang_newlib_x64/toolchain.ninja
+        subninja glibc_x64/toolchain.ninja
+        subninja irt_x64/toolchain.ninja
+        subninja nacl_bootstrap_x64/toolchain.ninja
+        subninja newlib_pnacl/toolchain.ninja
+
+        build blink_python_tests: phony obj/blink_python_tests.stamp
+        build blink_tests: phony obj/blink_tests.stamp
+
+        default all
+    """)  # Based off of a standard linux build dir.
+    with open(self.build_ninja_path, 'w') as f:
+      f.write(build_ninja_file_contents)
+
+    expected_build_ninja_file_contents = textwrap.dedent("""
+        ninja_required_version = 1.7.2
+
+        rule gn
+          command = ../../buildtools/gn --root=../.. -q --regeneration gen .
+          pool = console
+          description = Regenerating ninja files
+
+        build build.ninja.stamp: gn
+          generator = 1
+          depfile = build.ninja.d
+
+        build build.ninja: phony build.ninja.stamp
+          generator = 1
+
+    """)
+
+    self.assertEqual(clobber.extract_gn_build_commands(self.build_ninja_path),
+                     expected_build_ninja_file_contents)
+
+  def test_unexpected_format(self):
+    # No "build build.ninja:" line should make it return an empty string.
+    build_ninja_file_contents = textwrap.dedent("""
+        ninja_required_version = 1.7.2
+
+        rule gn
+          command = ../../buildtools/gn --root=../.. -q --regeneration gen .
+          pool = console
+          description = Regenerating ninja files
+
+        subninja toolchain.ninja
+
+        build blink_python_tests: phony obj/blink_python_tests.stamp
+        build blink_tests: phony obj/blink_tests.stamp
+
+    """)
+    with open(self.build_ninja_path, 'w') as f:
+      f.write(build_ninja_file_contents)
+
+    self.assertEqual(clobber.extract_gn_build_commands(self.build_ninja_path),
+                     '')
+
+
+class TestDelete(unittest.TestCase):
   def setUp(self):
     self.build_dir = tempfile.mkdtemp()
 
+    pathlib.Path(os.path.join(self.build_dir, 'build.ninja')).touch()
+    pathlib.Path(os.path.join(self.build_dir, 'build.ninja.d')).touch()
+
   def tearDown(self):
     shutil.rmtree(self.build_dir)
 
-  def test_gn_clean_ok(self):
-    pathlib.Path(os.path.join(self.build_dir, 'build.ninja')).touch()
-    pathlib.Path(os.path.join(self.build_dir, 'build.ninja.d')).touch()
-
+  def test_delete_build_dir_full(self):
     # Create a dummy file in the build dir and ensure it gets removed.
     dummy_file = os.path.join(self.build_dir, 'dummy')
     pathlib.Path(dummy_file).touch()
 
-    clobber._clean_build_dir(self.build_dir)
+    clobber.delete_build_dir(self.build_dir)
+
     self.assertFalse(os.path.exists(dummy_file))
 
-  def test_gn_clean_fail(self):
-    # gn clean fails without build.ninja.
-    # clean_build_dir() regenerates build.ninja internally.
-    clobber._clean_build_dir(self.build_dir)
+  def test_delete_build_dir_fail(self):
+    # Make delete_dir() throw to ensure it's handled gracefully.
+
+    with mock.patch('clobber.delete_dir', side_effect=OSError):
+      with self.assertRaises(OSError):
+        clobber.delete_build_dir(self.build_dir)
 
 
 if __name__ == '__main__':
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index 63e6089..d7b2ade 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-11.20230117.0.1
+11.20230117.2.1
diff --git a/build/rust/std/remap_alloc.cc b/build/rust/std/remap_alloc.cc
index 42e189c..ceac756 100644
--- a/build/rust/std/remap_alloc.cc
+++ b/build/rust/std/remap_alloc.cc
@@ -42,7 +42,11 @@
 // do that here, or we could build a crate with a #[global_allocator] and
 // redirect these symbols to that crate instead. The advantage of the latter
 // is that it would work equally well for those cases where rustc is doing
-// the final linking.
+// the final linking. At present, this is not necessary because
+// PartitionAlloc-Everywhere successfully handles the calls to malloc which
+// result from passing through this code. We might want to call into
+// PA directly if we wished for Rust allocations to be in a different
+// partition, or similar, in future.
 //
 // They're weak symbols, because this file will sometimes end up in targets
 // which are linked by rustc, and thus we would otherwise get duplicate
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc
index bc9d365..768c94f 100644
--- a/cc/layers/heads_up_display_layer_impl.cc
+++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -868,7 +868,7 @@
 
   // Draw current status.
   flags.setStyle(PaintFlags::kStroke_Style);
-  flags.setAlpha(32);
+  flags.setAlphaf(32.0f / 255.0f);
   flags.setStrokeWidth(4);
   DrawArc(canvas, oval, 180, angle, flags);
 
diff --git a/cc/paint/paint_filter.cc b/cc/paint/paint_filter.cc
index f107e17..d19d1a2 100644
--- a/cc/paint/paint_filter.cc
+++ b/cc/paint/paint_filter.cc
@@ -1065,7 +1065,7 @@
     ImageProvider* image_provider) const {
   PaintFlags orig_flags;
   orig_flags.setShader(shader_);
-  orig_flags.setAlpha(alpha_);
+  orig_flags.setAlphaf(alpha_ / 255.0f);
   orig_flags.setFilterQuality(filter_quality_);
   orig_flags.setDither(dither_ == SkImageFilters::Dither::kYes);
 
diff --git a/cc/paint/paint_flags.h b/cc/paint/paint_flags.h
index 23e9db0..bf199e69 100644
--- a/cc/paint/paint_flags.h
+++ b/cc/paint/paint_flags.h
@@ -52,9 +52,6 @@
     return SkColorGetA(color_.toSkColor());
   }
   ALWAYS_INLINE float getAlphaf() const { return color_.fA; }
-  ALWAYS_INLINE void setAlpha(uint8_t a) {
-    color_ = SkColor4f::FromColor(SkColorSetA(color_.toSkColor(), a));
-  }
   template <class F, class = std::enable_if_t<std::is_same_v<F, float>>>
   ALWAYS_INLINE void setAlphaf(F a) {
     color_.fA = a;
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc
index 94a327c..97eee9e5 100644
--- a/cc/paint/paint_op_buffer_unittest.cc
+++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -136,7 +136,7 @@
   PaintOpAppendTest() {
     rect_ = SkRect::MakeXYWH(2, 3, 4, 5);
     flags_.setColor(SK_ColorMAGENTA);
-    flags_.setAlpha(100);
+    flags_.setAlphaf(100.0f / 255.0f);
   }
 
   void PushOps(PaintOpBuffer* buffer) {
@@ -245,7 +245,7 @@
   int paint_flags_alpha = 50;
   PaintFlags draw_flags;
   draw_flags.setColor(SkColors::kMagenta);
-  draw_flags.setAlpha(paint_flags_alpha);
+  draw_flags.setAlphaf(paint_flags_alpha / 255.0f);
   EXPECT_TRUE(draw_flags.SupportsFoldingAlpha());
   SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
   buffer.push<DrawRectOp>(rect, draw_flags);
@@ -295,7 +295,7 @@
 
   PaintFlags draw_flags;
   draw_flags.setColor(SkColors::kMagenta);
-  draw_flags.setAlpha(50);
+  draw_flags.setAlphaf(50.0f / 255.0f);
   draw_flags.setBlendMode(SkBlendMode::kSrc);
   EXPECT_FALSE(draw_flags.SupportsFoldingAlpha());
   SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
@@ -322,7 +322,7 @@
 
   PaintFlags draw_flags;
   draw_flags.setColor(SkColors::kMagenta);
-  draw_flags.setAlpha(50);
+  draw_flags.setAlphaf(50.0f / 255.0f);
   draw_flags.setBlendMode(SkBlendMode::kColorBurn);
   EXPECT_FALSE(draw_flags.SupportsFoldingAlpha());
   SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
@@ -347,7 +347,7 @@
 
   PaintFlags draw_flags;
   draw_flags.setColor(SkColors::kMagenta);
-  draw_flags.setAlpha(50);
+  draw_flags.setAlphaf(50.0f / 255.0f);
   draw_flags.setBlendMode(SkBlendMode::kSrcOver);
   EXPECT_TRUE(draw_flags.SupportsFoldingAlpha());
   SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
@@ -390,7 +390,7 @@
   int paint_flags_alpha = 50;
   PaintFlags draw_flags;
   draw_flags.setColor(SkColors::kMagenta);
-  draw_flags.setAlpha(paint_flags_alpha);
+  draw_flags.setAlphaf(paint_flags_alpha / 255.0f);
   EXPECT_TRUE(draw_flags.SupportsFoldingAlpha());
   SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
   sub_buffer.push<DrawRectOp>(rect, draw_flags);
@@ -1143,7 +1143,7 @@
     [] {
       PaintFlags flags;
       flags.setColor(SK_ColorCYAN);
-      flags.setAlpha(103);
+      flags.setAlphaf(103.0f / 255.0f);
       flags.setStrokeWidth(0.32f);
       flags.setStrokeMiter(7.98f);
       flags.setBlendMode(SkBlendMode::kSrcOut);
@@ -2113,7 +2113,7 @@
     written = nullptr;
 
     PaintFlags override_flags = static_cast<const PaintOpWithFlags&>(op).flags;
-    override_flags.setAlpha(override_flags.getAlpha() * 0.5);
+    override_flags.setAlphaf(override_flags.getAlpha() * 0.5f / 255.0f);
     bytes_written = op.Serialize(output_.get(), output_size_,
                                  options_provider.serialize_options(),
                                  &override_flags, SkM44(), SkM44());
@@ -2293,7 +2293,7 @@
 
   PaintFlags draw_flags;
   draw_flags.setColor(SkColors::kMagenta);
-  draw_flags.setAlpha(50);
+  draw_flags.setAlphaf(50.0f / 255.0f);
   SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
   buffer.push<DrawRectOp>(rect, draw_flags);
   buffer.push<RestoreOp>();
diff --git a/cc/paint/paint_op_helper_unittest.cc b/cc/paint/paint_op_helper_unittest.cc
index 262d6b4..52aa08da 100644
--- a/cc/paint/paint_op_helper_unittest.cc
+++ b/cc/paint/paint_op_helper_unittest.cc
@@ -5,8 +5,10 @@
 #include "cc/test/paint_op_helper.h"
 #include "cc/paint/paint_canvas.h"
 #include "cc/paint/paint_op_buffer.h"
+#include "cc/test/skia_common.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkTextBlob.h"
+#include "third_party/skia/include/effects/SkLumaColorFilter.h"
 
 namespace cc {
 namespace {
@@ -266,6 +268,28 @@
       "supportsFoldingAlpha=true, isValid=true, hasDiscardableImages=false])");
 }
 
+TEST(PaintOpHelper, SaveLayerWithFilterToString) {
+  SkRect bounds = SkRect::MakeXYWH(1, 2, 3, 4);
+  PaintFlags flags;
+  flags.setImageFilter(sk_make_sp<DropShadowPaintFilter>(
+      0.0f, 0.0f, 0.0f, 0.0f, SkColors::kTransparent,
+      DropShadowPaintFilter::ShadowMode::kDrawShadowAndForeground, nullptr));
+  SaveLayerOp op(bounds, flags);
+  EXPECT_EQ(
+      PaintOpHelper::ToString(op),
+      "SaveLayerOp(bounds=[1.000,2.000 3.000x4.000], flags=[color=rgba(0, 0, "
+      "0, 255), blendMode=kSrcOver, isAntiAlias=false, isDither=false, "
+      "filterQuality=kNone_SkFilterQuality, "
+      "strokeWidth=0.000, strokeMiter=4.000, strokeCap=kButt_Cap, "
+      "strokeJoin=kMiter_Join, colorFilter=(nil), "
+      "maskFilter=(nil), shader=(nil), hasShader=false, shaderIsOpaque=false, "
+      "pathEffect=(nil), imageFilter=DropShadowPaintFilter(dx=0.000, dy=0.000, "
+      "sigma_x=0.000, sigma_y=0.000, color=rgba(0.000000, 0.000000, 0.000000, "
+      "0.000000), shadow_mode=kDrawShadowAndForeground, input=(nil), "
+      "crop_rect=(nil)), drawLooper=(nil), supportsFoldingAlpha=false, "
+      "isValid=true, hasDiscardableImages=false])");
+}
+
 TEST(PaintOpHelper, SaveLayerAlphaToString) {
   SaveLayerAlphaOp op(SkRect::MakeXYWH(1, 2, 3, 4), 1.0f);
   std::string str = PaintOpHelper::ToString(op);
@@ -294,5 +318,287 @@
   EXPECT_EQ(str, "TranslateOp(dx=0.000, dy=0.000)");
 }
 
+TEST(PaintOpHelperFilters, ColorFilterPaintFilter) {
+  PaintFilter::CropRect crop_rect(SkRect::MakeWH(100.f, 100.f));
+  ColorFilterPaintFilter filter(SkLumaColorFilter::Make(),
+                                /*input=*/nullptr, &crop_rect);
+  EXPECT_EQ(PaintOpHelper::ToString(filter),
+            "ColorFilterPaintFilter(color_filter=SkColorFilter, input=(nil), "
+            "crop_rect=[0.000,0.000 100.000x100.000])");
+}
+
+TEST(PaintOpHelperFilters, BlurPaintFilter) {
+  PaintFilter::CropRect crop_rect(SkRect::MakeWH(100.f, 100.f));
+  BlurPaintFilter filter(1.f, 2.f, SkTileMode::kRepeat,
+                         /*input=*/nullptr, &crop_rect);
+  EXPECT_EQ(PaintOpHelper::ToString(filter),
+            "BlurPaintFilter(sigma_x=1.000, sigma_y=2.000, tile_mode=kRepeat, "
+            "input=(nil), crop_rect=[0.000,0.000 100.000x100.000])");
+}
+
+TEST(PaintOpHelperFilters, DropShadowPaintFilter) {
+  PaintFilter::CropRect crop_rect(SkRect::MakeWH(100.f, 100.f));
+  DropShadowPaintFilter filter(
+      1.f, 2.f, 3.f, 4.f, SkColors::kWhite,
+      DropShadowPaintFilter::ShadowMode::kDrawShadowOnly,
+      /*input=*/nullptr, &crop_rect);
+  EXPECT_EQ(PaintOpHelper::ToString(filter),
+            "DropShadowPaintFilter(dx=1.000, dy=2.000, sigma_x=3.000, "
+            "sigma_y=4.000, color=rgba(1.000000, 1.000000, 1.000000, "
+            "1.000000), shadow_mode=kDrawShadowOnly, input=(nil), "
+            "crop_rect=[0.000,0.000 100.000x100.000])");
+}
+
+TEST(PaintOpHelperFilters, MagnifierPaintFilter) {
+  PaintFilter::CropRect crop_rect(SkRect::MakeWH(100.f, 100.f));
+  MagnifierPaintFilter filter(SkRect::MakeWH(100.f, 100.f), /*inset=*/0.1f,
+                              /*input=*/nullptr, &crop_rect);
+  EXPECT_EQ(PaintOpHelper::ToString(filter),
+            "MagnifierPaintFilter(src_rect=[0.000,0.000 100.000x100.000], "
+            "inset=0.100, input=(nil), "
+            "crop_rect=[0.000,0.000 100.000x100.000])");
+}
+
+TEST(PaintOpHelperFilters, ComposePaintFilter) {
+  ComposePaintFilter filter(sk_make_sp<OffsetPaintFilter>(
+                                /*dx=*/0.1f, /*dy=*/0.2f, /*input=*/nullptr),
+                            nullptr);
+  EXPECT_EQ(PaintOpHelper::ToString(filter),
+            "ComposePaintFilter(outer=OffsetPaintFilter(dx=0.1, dy=0.2, "
+            "input=(nil), crop_rect=(nil)), inner=(nil), crop_rect=(nil))");
+}
+
+TEST(PaintOpHelperFilters, AlphaThresholdPaintFilter) {
+  PaintFilter::CropRect crop_rect(SkRect::MakeWH(100.f, 100.f));
+  AlphaThresholdPaintFilter filter(SkRegion(SkIRect::MakeWH(100, 100)),
+                                   /*inner_min=*/0.1f, /*outer_max=*/0.2f,
+                                   /*input=*/nullptr, &crop_rect);
+  EXPECT_EQ(PaintOpHelper::ToString(filter),
+            "AlphaThresholdPaintFilter(region=[0,0 100x100], "
+            "inner_min=0.100, outer_max=0.200, input=(nil), "
+            "crop_rect=[0.000,0.000 100.000x100.000])");
+}
+
+TEST(PaintOpHelperFilters, XfermodePaintFilter) {
+  PaintFilter::CropRect crop_rect(SkRect::MakeWH(100.f, 100.f));
+  XfermodePaintFilter filter(SkBlendMode::kSrc,
+                             /*background=*/nullptr, /*foreground=*/nullptr,
+                             &crop_rect);
+  EXPECT_EQ(PaintOpHelper::ToString(filter),
+            "XfermodePaintFilter(blend_mode=kSrc, "
+            "background=(nil), foreground=(nil), "
+            "crop_rect=[0.000,0.000 100.000x100.000])");
+}
+
+TEST(PaintOpHelperFilters, ArithmeticPaintFilter) {
+  PaintFilter::CropRect crop_rect(SkRect::MakeWH(100.f, 100.f));
+  ArithmeticPaintFilter filter(/*k1=*/0.1f, /*k2=*/0.2f, /*k3=*/0.3f,
+                               /*k4=*/0.4f, /*enforce_pm_color=*/true,
+                               /*background=*/nullptr, /*foreground=*/nullptr,
+                               &crop_rect);
+  EXPECT_EQ(PaintOpHelper::ToString(filter),
+            "ArithmeticPaintFilter(k1=0.1, k2=0.2, k3=0.3, k4=0.4, "
+            "enfore_pm_color=true, background=(nil), foreground=(nil), "
+            "crop_rect=[0.000,0.000 100.000x100.000])");
+}
+
+TEST(PaintOpHelperFilters, MatrixConvolutionPaintFilter) {
+  SkScalar scalars[9] = {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f};
+  PaintFilter::CropRect crop_rect(SkRect::MakeWH(100.f, 100.f));
+  MatrixConvolutionPaintFilter filter(
+      /*kernel_size=*/SkISize::Make(3, 3),
+      /*kernel=*/scalars, /*gain=*/0.1f, /*bias=*/0.2f,
+      /*kernel_offset=*/SkIPoint::Make(2, 2), SkTileMode::kRepeat,
+      /*convolve_alpha=*/false,
+      /*input=*/nullptr, &crop_rect);
+  EXPECT_EQ(PaintOpHelper::ToString(filter),
+            "MatrixConvolutionPaintFilter(kernel_size=SkISize(3, 3), "
+            "kernel=[1.000, 2.000, 3.000, 4.000, 5.000, 6.000, 7.000, 8.000, "
+            "9.000], gain=0.100, bias=0.200, kernel_offset=SkIPoint(2, 2), "
+            "tile_mode=kRepeat, convolve_alpha=false, input=(nil), "
+            "crop_rect=[0.000,0.000 100.000x100.000])");
+}
+
+TEST(PaintOpHelperFilters, DisplacementMapEffectPaintFilter) {
+  PaintFilter::CropRect crop_rect(SkRect::MakeWH(100.f, 100.f));
+  DisplacementMapEffectPaintFilter filter(
+      SkColorChannel::kR, SkColorChannel::kR, /*scale=*/0.1f,
+      /*displacement=*/nullptr, /*color=*/nullptr, &crop_rect);
+  EXPECT_EQ(PaintOpHelper::ToString(filter),
+            "DisplacementMapEffectPaintFilter(channel_x=kR, channel_y=kR, "
+            "scale=0.100, displacement=(nil), color=(nil), "
+            "crop_rect=[0.000,0.000 100.000x100.000])");
+}
+
+TEST(PaintOpHelperFilters, ImagePaintFilter) {
+  ImagePaintFilter filter(CreateDiscardablePaintImage(gfx::Size(100, 100)),
+                          SkRect::MakeWH(100.f, 100.f),
+                          SkRect::MakeWH(100.f, 100.f),
+                          PaintFlags::FilterQuality::kNone);
+  EXPECT_EQ(PaintOpHelper::ToString(filter),
+            "ImagePaintFilter(image=<paint image>, "
+            "src_rect=[0.000,0.000 100.000x100.000], "
+            "dst_rect=[0.000,0.000 100.000x100.000], "
+            "filter_quality=kNone_SkFilterQuality, crop_rect=(nil))");
+}
+
+TEST(PaintOpHelperFilters, RecordPaintFilter) {
+  PaintOpBuffer buffer;
+  buffer.push<SaveOp>();
+  RecordPaintFilter filter(buffer.ReleaseAsRecord(),
+                           SkRect::MakeWH(100.f, 100.f),
+                           /*raster_scale=*/{0.5f, 0.8f},
+                           RecordPaintFilter::ScalingBehavior::kFixedScale);
+  EXPECT_EQ(PaintOpHelper::ToString(filter),
+            "RecordPaintFilter(record=<paint record>, "
+            "record_bounds=[0.000,0.000 100.000x100.000], "
+            "raster_scale=[0.5x0.8], scaling_behavior=kFixedScale, "
+            "crop_rect=(nil))");
+}
+
+TEST(PaintOpHelperFilters, MergePaintFilter) {
+  PaintFilter::CropRect crop_rect(SkRect::MakeWH(100.f, 100.f));
+  sk_sp<PaintFilter> filters[] = {
+      sk_make_sp<ImagePaintFilter>(
+          CreateDiscardablePaintImage(gfx::Size(100, 100)),
+          SkRect::MakeWH(100.f, 100.f), SkRect::MakeWH(100.f, 100.f),
+          PaintFlags::FilterQuality::kNone),
+      nullptr};
+  MergePaintFilter filter(filters, 2, &crop_rect);
+  EXPECT_EQ(PaintOpHelper::ToString(filter),
+            "MergePaintFilter(input_count=2, input=[ImagePaintFilter("
+            "image=<paint image>, "
+            "src_rect=[0.000,0.000 100.000x100.000], "
+            "dst_rect=[0.000,0.000 100.000x100.000], "
+            "filter_quality=kNone_SkFilterQuality, crop_rect=(nil)), (nil)], "
+            "crop_rect=[0.000,0.000 100.000x100.000])");
+}
+
+TEST(PaintOpHelperFilters, MorphologyPaintFilter) {
+  PaintFilter::CropRect crop_rect(SkRect::MakeWH(100.f, 100.f));
+  MorphologyPaintFilter filter(MorphologyPaintFilter::MorphType::kErode,
+                               /*radius_x=*/1, /*radius_y=*/2, nullptr,
+                               &crop_rect);
+  EXPECT_EQ(PaintOpHelper::ToString(filter),
+            "MorphologyPaintFilter(morph_type=kErode, radius_x=1, radius_y=2, "
+            "input=(nil), crop_rect=[0.000,0.000 100.000x100.000])");
+}
+
+TEST(PaintOpHelperFilters, OffsetPaintFilter) {
+  PaintFilter::CropRect crop_rect(SkRect::MakeWH(100.f, 100.f));
+  OffsetPaintFilter filter(/*dx=*/0.1f, /*dy=*/0.2f, /*input=*/nullptr,
+                           &crop_rect);
+  EXPECT_EQ(PaintOpHelper::ToString(filter),
+            "OffsetPaintFilter(dx=0.1, dy=0.2, input=(nil), "
+            "crop_rect=[0.000,0.000 100.000x100.000])");
+}
+
+TEST(PaintOpHelperFilters, TilePaintFilter) {
+  TilePaintFilter filter(SkRect::MakeWH(100.f, 100.f),
+                         SkRect::MakeWH(200.f, 200.f),
+                         /*input=*/nullptr);
+  EXPECT_EQ(PaintOpHelper::ToString(filter),
+            "TilePaintFilter(src=[0.000,0.000 100.000x100.000], "
+            "dst=[0.000,0.000 200.000x200.000], input=(nil), crop_rect=(nil))");
+}
+
+TEST(PaintOpHelperFilters, TurbulencePaintFilter) {
+  PaintFilter::CropRect crop_rect(SkRect::MakeWH(100.f, 100.f));
+  const auto tile_size = SkISize::Make(3, 4);
+  TurbulencePaintFilter filter(
+      TurbulencePaintFilter::TurbulenceType::kFractalNoise,
+      /*base_frequency_x=*/0.1f, /*base_frequency_y=*/0.2f, /*num_octaves=*/2,
+      /*seed=*/0.3f, /*tile_size=*/&tile_size, &crop_rect);
+  EXPECT_EQ(PaintOpHelper::ToString(filter),
+            "TurbulencePaintFilter(turbulence_type=kFractalNoise, "
+            "base_frequency_x=0.100, base_frequency_y=0.200, num_octaves=2, "
+            "seed=0.300, tile_size=SkISize(3, 4), "
+            "crop_rect=[0.000,0.000 100.000x100.000])");
+}
+
+TEST(PaintOpHelperFilters, ShaderPaintFilter) {
+  PaintFilter::CropRect crop_rect(SkRect::MakeWH(100.f, 100.f));
+  ShaderPaintFilter filter(
+      PaintShader::MakeImage(CreateDiscardablePaintImage(gfx::Size(100, 100)),
+                             /*tx=*/SkTileMode::kClamp,
+                             /*ty=*/SkTileMode::kRepeat,
+                             /*local_matrix=*/nullptr),
+      /*alpha=*/255, PaintFlags::FilterQuality::kMedium,
+      SkImageFilters::Dither::kYes, &crop_rect);
+  EXPECT_EQ(
+      PaintOpHelper::ToString(filter),
+      "ShaderPaintFilter(shader=[type=kImage, flags=0, end_radius=0, "
+      "start_radius=0, tx=0, ty=1, fallback_color=rgba(0.000000, 0.000000, "
+      "0.000000, 0.000000), scaling_behavior=kRasterAtScale, "
+      "local_matrix=(nil), center=[0.000,0.000], tile=[0.000,0.000 "
+      "0.000x0.000], start_point=[0.000,0.000], end_point=[0.000,0.000], "
+      "start_degrees=0, end_degrees=0, image=<paint image>, record=(nil), "
+      "id=4294967295, tile_scale=(nil), colors=(nil), positions=(nil)], "
+      "alpha=255, filter_quality=kMedium_SkFilterQuality, dither=kYes, "
+      "crop_rect=[0.000,0.000 100.000x100.000])");
+}
+
+TEST(PaintOpHelperFilters, MatrixPaintFilter) {
+  MatrixPaintFilter filter(SkMatrix::I(), PaintFlags::FilterQuality::kHigh,
+                           /*input=*/nullptr);
+  EXPECT_EQ(
+      PaintOpHelper::ToString(filter),
+      "MatrixPaintFilter(matrix=[  1.0000   0.0000   0.0000][  0.0000   1.0000 "
+      "  0.0000][  0.0000   0.0000   1.0000]], "
+      "filter_quality=kHigh_SkFilterQuality, input=(nil), crop_rect=(nil))");
+}
+
+TEST(PaintOpHelperFilters, LightingDistantPaintFilter) {
+  PaintFilter::CropRect crop_rect(SkRect::MakeWH(100.f, 100.f));
+  LightingDistantPaintFilter filter(
+      PaintFilter::LightingType::kSpecular,
+      /*direction=*/SkPoint3::Make(0.1f, 0.2f, 0.3f), SkColors::kWhite,
+      /*surface_scale=*/0.1f, /*kconstant=*/0.2f,
+      /*shininess=*/0.3f, /*input=*/nullptr, &crop_rect);
+  EXPECT_EQ(
+      PaintOpHelper::ToString(filter),
+      "LightingDistantPaintFilter(lighting_type=kSpecular, "
+      "direction=SkPoint3(0.100, 0.200, 0.300), "
+      "light_color=rgba(1.000000, 1.000000, 1.000000, 1.000000), "
+      "surface_scale=0.100, kconstant=0.200, shininess=0.300, input=(nil), "
+      "crop_rect=[0.000,0.000 100.000x100.000])");
+}
+
+TEST(PaintOpHelperFilters, LightingPointPaintFilter) {
+  PaintFilter::CropRect crop_rect(SkRect::MakeWH(100.f, 100.f));
+  LightingPointPaintFilter filter(
+      PaintFilter::LightingType::kSpecular,
+      /*location=*/SkPoint3::Make(0.1f, 0.2f, 0.3f), SkColors::kWhite,
+      /*surface_scale=*/0.1f, /*kconstant=*/0.2f,
+      /*shininess=*/0.3f, /*input=*/nullptr, &crop_rect);
+  EXPECT_EQ(
+      PaintOpHelper::ToString(filter),
+      "LightingPointPaintFilter(lighting_type=kSpecular, "
+      "location=SkPoint3(0.100, 0.200, 0.300), "
+      "light_color=rgba(1.000000, 1.000000, 1.000000, 1.000000), "
+      "surface_scale=0.100, kconstant=0.200, shininess=0.300, input=(nil), "
+      "crop_rect=[0.000,0.000 100.000x100.000])");
+}
+
+TEST(PaintOpHelperFilters, LightingSpotPaintFilter) {
+  PaintFilter::CropRect crop_rect(SkRect::MakeWH(100.f, 100.f));
+  LightingSpotPaintFilter filter(
+      PaintFilter::LightingType::kSpecular,
+      /*location=*/SkPoint3::Make(0.1f, 0.2f, 0.3f),
+      /*target=*/SkPoint3::Make(0.4f, 0.5f, 0.6f), /*specular_exponent=*/0.1f,
+      /*cutoff_angle=*/0.2f, SkColors::kWhite,
+      /*surface_scale=*/0.1f, /*kconstant=*/0.2f,
+      /*shininess=*/0.3f, /*input=*/nullptr, &crop_rect);
+  EXPECT_EQ(
+      PaintOpHelper::ToString(filter),
+      "LightingSpotPaintFilter(lighting_type=kSpecular, "
+      "location=SkPoint3(0.100, 0.200, 0.300), "
+      "target=SkPoint3(0.400, 0.500, 0.600), "
+      "specular_exponent=0.100, cutoff_angle=0.200, "
+      "light_color=rgba(1.000000, 1.000000, 1.000000, 1.000000), "
+      "surface_scale=0.100, kconstant=0.200, shininess=0.300, input=(nil), "
+      "crop_rect=[0.000,0.000 100.000x100.000])");
+}
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/paint/scoped_raster_flags.cc b/cc/paint/scoped_raster_flags.cc
index b5eb6e4..42c11d4 100644
--- a/cc/paint/scoped_raster_flags.cc
+++ b/cc/paint/scoped_raster_flags.cc
@@ -119,8 +119,10 @@
     // Use modulated hairline when possible, as it is faster and produces
     // results closer to the original intent.
     MutableFlags()->setStrokeWidth(0);
-    MutableFlags()->setAlpha(std::round(
-        flags()->getAlpha() * std::sqrt(stroke_vec.x() * stroke_vec.y())));
+    MutableFlags()->setAlphaf(
+        std::round(flags()->getAlpha() *
+                   std::sqrt(stroke_vec.x() * stroke_vec.y())) /
+        255.0f);
     return;
   }
 
diff --git a/cc/raster/raster_source_unittest.cc b/cc/raster/raster_source_unittest.cc
index cfb38d2..62d0120 100644
--- a/cc/raster/raster_source_unittest.cc
+++ b/cc/raster/raster_source_unittest.cc
@@ -570,7 +570,7 @@
   const unsigned alpha_dark = 10u;
   PaintFlags white_flags;
   white_flags.setColor(SK_ColorWHITE);
-  white_flags.setAlpha(alpha_dark);
+  white_flags.setAlphaf(alpha_dark / 255.0f);
   recording_source->add_draw_rect_with_flags(gfx::Rect(layer_bounds),
                                              white_flags);
   recording_source->Rerecord();
@@ -606,7 +606,7 @@
 
   // Record everything as a slightly lighter white.
   const unsigned alpha_light = 18u;
-  white_flags.setAlpha(alpha_light);
+  white_flags.setAlphaf(alpha_light / 255.0f);
   recording_source_light->add_draw_rect_with_flags(gfx::Rect(layer_bounds),
                                                    white_flags);
   recording_source_light->Rerecord();
diff --git a/cc/test/fake_raster_source.cc b/cc/test/fake_raster_source.cc
index 7a248bd4..2bb8f970 100644
--- a/cc/test/fake_raster_source.cc
+++ b/cc/test/fake_raster_source.cc
@@ -40,7 +40,7 @@
   PaintFlags salmon_pink_flags;
   salmon_pink_flags.setColor(SK_ColorRED);
   salmon_pink_flags.setBlendMode(SkBlendMode::kMultiply);
-  salmon_pink_flags.setAlpha(128);
+  salmon_pink_flags.setAlphaf(128.0f / 255.0f);
   recording_source->add_draw_rect_with_flags(gfx::Rect(size),
                                              salmon_pink_flags);
 
diff --git a/cc/test/paint_op_helper.h b/cc/test/paint_op_helper.h
index 2339610..ef26975 100644
--- a/cc/test/paint_op_helper.h
+++ b/cc/test/paint_op_helper.h
@@ -21,147 +21,154 @@
 // implementation should be limited ot the header.
 class PaintOpHelper {
  public:
+  // Print optional/nullable wrapper types are using underlying types.
+  template <typename T>
+  static std::string ToString(const T* ptr) {
+    return ptr ? ToString(*ptr) : "(nil)";
+  }
+
+  template <typename T>
+  static std::string ToString(const sk_sp<T>& ptr) {
+    return ptr ? ToString(*ptr) : "(nil)";
+  }
+
+  template <typename T>
+  static std::string ToString(scoped_refptr<T> ptr) {
+    return ptr ? ToString(*ptr) : "(nil)";
+  }
+
+  template <typename T>
+  static std::string ToString(const absl::optional<T>& opt) {
+    return opt.has_value() ? ToString(*opt) : "(nil)";
+  }
+
   static std::string ToString(const PaintOp& base_op) {
     std::ostringstream str;
     str << std::boolalpha;
     switch (base_op.GetType()) {
       case PaintOpType::Annotate: {
         const auto& op = static_cast<const AnnotateOp&>(base_op);
-        str << "AnnotateOp(type="
-            << PaintOpHelper::EnumToString(op.annotation_type)
-            << ", rect=" << PaintOpHelper::SkiaTypeToString(op.rect)
-            << ", data=" << PaintOpHelper::SkiaTypeToString(op.data) << ")";
+        str << "AnnotateOp(type=" << ToString(op.annotation_type)
+            << ", rect=" << ToString(op.rect) << ", data=" << ToString(op.data)
+            << ")";
         break;
       }
       case PaintOpType::ClipPath: {
         const auto& op = static_cast<const ClipPathOp&>(base_op);
-        str << "ClipPathOp(path=" << PaintOpHelper::SkiaTypeToString(op.path)
-            << ", op=" << PaintOpHelper::SkiaTypeToString(op.op)
-            << ", antialias=" << op.antialias
+        str << "ClipPathOp(path=" << ToString(op.path)
+            << ", op=" << ToString(op.op) << ", antialias=" << op.antialias
             << ", use_cache=" << (op.use_cache == UsePaintCache::kEnabled)
             << ")";
         break;
       }
       case PaintOpType::ClipRect: {
         const auto& op = static_cast<const ClipRectOp&>(base_op);
-        str << "ClipRectOp(rect=" << PaintOpHelper::SkiaTypeToString(op.rect)
-            << ", op=" << PaintOpHelper::SkiaTypeToString(op.op)
-            << ", antialias=" << op.antialias << ")";
+        str << "ClipRectOp(rect=" << ToString(op.rect)
+            << ", op=" << ToString(op.op) << ", antialias=" << op.antialias
+            << ")";
         break;
       }
       case PaintOpType::ClipRRect: {
         const auto& op = static_cast<const ClipRRectOp&>(base_op);
-        str << "ClipRRectOp(rrect=" << PaintOpHelper::SkiaTypeToString(op.rrect)
-            << ", op=" << PaintOpHelper::SkiaTypeToString(op.op)
-            << ", antialias=" << op.antialias << ")";
+        str << "ClipRRectOp(rrect=" << ToString(op.rrect)
+            << ", op=" << ToString(op.op) << ", antialias=" << op.antialias
+            << ")";
         break;
       }
       case PaintOpType::Concat: {
         const auto& op = static_cast<const ConcatOp&>(base_op);
-        str << "ConcatOp(matrix=" << PaintOpHelper::SkiaTypeToString(op.matrix)
-            << ")";
+        str << "ConcatOp(matrix=" << ToString(op.matrix) << ")";
         break;
       }
       case PaintOpType::CustomData: {
         const auto& op = static_cast<const CustomDataOp&>(base_op);
-        str << "CustomDataOp(id=" << PaintOpHelper::SkiaTypeToString(op.id)
-            << ")";
+        str << "CustomDataOp(id=" << ToString(op.id) << ")";
         break;
       }
       case PaintOpType::DrawColor: {
         const auto& op = static_cast<const DrawColorOp&>(base_op);
-        str << "DrawColorOp(color=" << PaintOpHelper::SkiaTypeToString(op.color)
-            << ", mode=" << PaintOpHelper::SkiaTypeToString(op.mode) << ")";
+        str << "DrawColorOp(color=" << ToString(op.color)
+            << ", mode=" << ToString(op.mode) << ")";
         break;
       }
       case PaintOpType::DrawDRRect: {
         const auto& op = static_cast<const DrawDRRectOp&>(base_op);
-        str << "DrawDRRectOp(outer="
-            << PaintOpHelper::SkiaTypeToString(op.outer)
-            << ", inner=" << PaintOpHelper::SkiaTypeToString(op.inner)
-            << ", flags=" << PaintOpHelper::FlagsToString(op.flags) << ")";
+        str << "DrawDRRectOp(outer=" << ToString(op.outer)
+            << ", inner=" << ToString(op.inner)
+            << ", flags=" << ToString(op.flags) << ")";
         break;
       }
       case PaintOpType::DrawImage: {
         const auto& op = static_cast<const DrawImageOp&>(base_op);
-        str << "DrawImageOp(image=" << PaintOpHelper::ImageToString(op.image)
-            << ", left=" << PaintOpHelper::SkiaTypeToString(op.left)
-            << ", top=" << PaintOpHelper::SkiaTypeToString(op.top)
-            << ", flags=" << PaintOpHelper::FlagsToString(op.flags) << ")";
+        str << "DrawImageOp(image=" << ToString(op.image)
+            << ", left=" << ToString(op.left) << ", top=" << ToString(op.top)
+            << ", flags=" << ToString(op.flags) << ")";
         break;
       }
       case PaintOpType::DrawImageRect: {
         const auto& op = static_cast<const DrawImageRectOp&>(base_op);
-        str << "DrawImageRectOp(image="
-            << PaintOpHelper::ImageToString(op.image)
-            << ", src=" << PaintOpHelper::SkiaTypeToString(op.src)
-            << ", dst=" << PaintOpHelper::SkiaTypeToString(op.dst)
-            << ", constraint=" << PaintOpHelper::EnumToString(op.constraint)
-            << ", flags=" << PaintOpHelper::FlagsToString(op.flags) << ")";
+        str << "DrawImageRectOp(image=" << ToString(op.image)
+            << ", src=" << ToString(op.src) << ", dst=" << ToString(op.dst)
+            << ", constraint=" << ToString(op.constraint)
+            << ", flags=" << ToString(op.flags) << ")";
         break;
       }
       case PaintOpType::DrawIRect: {
         const auto& op = static_cast<const DrawIRectOp&>(base_op);
-        str << "DrawIRectOp(rect=" << PaintOpHelper::SkiaTypeToString(op.rect)
-            << ", flags=" << PaintOpHelper::FlagsToString(op.flags) << ")";
+        str << "DrawIRectOp(rect=" << ToString(op.rect)
+            << ", flags=" << ToString(op.flags) << ")";
         break;
       }
       case PaintOpType::DrawLine: {
         const auto& op = static_cast<const DrawLineOp&>(base_op);
-        str << "DrawLineOp(x0=" << PaintOpHelper::SkiaTypeToString(op.x0)
-            << ", y0=" << PaintOpHelper::SkiaTypeToString(op.y0)
-            << ", x1=" << PaintOpHelper::SkiaTypeToString(op.x1)
-            << ", y1=" << PaintOpHelper::SkiaTypeToString(op.y1)
-            << ", flags=" << PaintOpHelper::FlagsToString(op.flags) << ")";
+        str << "DrawLineOp(x0=" << ToString(op.x0) << ", y0=" << ToString(op.y0)
+            << ", x1=" << ToString(op.x1) << ", y1=" << ToString(op.y1)
+            << ", flags=" << ToString(op.flags) << ")";
         break;
       }
       case PaintOpType::DrawOval: {
         const auto& op = static_cast<const DrawOvalOp&>(base_op);
-        str << "DrawOvalOp(oval=" << PaintOpHelper::SkiaTypeToString(op.oval)
-            << ", flags=" << PaintOpHelper::FlagsToString(op.flags) << ")";
+        str << "DrawOvalOp(oval=" << ToString(op.oval)
+            << ", flags=" << ToString(op.flags) << ")";
         break;
       }
       case PaintOpType::DrawPath: {
         const auto& op = static_cast<const DrawPathOp&>(base_op);
-        str << "DrawPathOp(path=" << PaintOpHelper::SkiaTypeToString(op.path)
-            << ", flags=" << PaintOpHelper::FlagsToString(op.flags)
+        str << "DrawPathOp(path=" << ToString(op.path)
+            << ", flags=" << ToString(op.flags)
             << ", use_cache=" << (op.use_cache == UsePaintCache::kEnabled)
             << ")";
         break;
       }
       case PaintOpType::DrawRecord: {
         const auto& op = static_cast<const DrawRecordOp&>(base_op);
-        str << "DrawRecordOp(record="
-            << PaintOpHelper::RecordToString(op.record) << ")";
+        str << "DrawRecordOp(record=" << ToString(op.record) << ")";
         break;
       }
       case PaintOpType::DrawRect: {
         const auto& op = static_cast<const DrawRectOp&>(base_op);
-        str << "DrawRectOp(rect=" << PaintOpHelper::SkiaTypeToString(op.rect)
-            << ", flags=" << PaintOpHelper::FlagsToString(op.flags) << ")";
+        str << "DrawRectOp(rect=" << ToString(op.rect)
+            << ", flags=" << ToString(op.flags) << ")";
         break;
       }
       case PaintOpType::DrawRRect: {
         const auto& op = static_cast<const DrawRRectOp&>(base_op);
-        str << "DrawRRectOp(rrect=" << PaintOpHelper::SkiaTypeToString(op.rrect)
-            << ", flags=" << PaintOpHelper::FlagsToString(op.flags) << ")";
+        str << "DrawRRectOp(rrect=" << ToString(op.rrect)
+            << ", flags=" << ToString(op.flags) << ")";
         break;
       }
       case PaintOpType::DrawSkottie: {
         const auto& op = static_cast<const DrawSkottieOp&>(base_op);
         str << "DrawSkottieOp("
-            << "skottie=" << PaintOpHelper::SkottieToString(op.skottie)
-            << ", dst=" << PaintOpHelper::SkiaTypeToString(op.dst)
-            << ", t=" << op.t << ")";
+            << "skottie=" << ToString(op.skottie)
+            << ", dst=" << ToString(op.dst) << ", t=" << op.t << ")";
         break;
       }
       case PaintOpType::DrawTextBlob: {
         const auto& op = static_cast<const DrawTextBlobOp&>(base_op);
-        str << "DrawTextBlobOp(blob="
-            << PaintOpHelper::TextBlobToString(op.blob)
-            << ", x=" << PaintOpHelper::SkiaTypeToString(op.x)
-            << ", y=" << PaintOpHelper::SkiaTypeToString(op.y)
-            << ", flags=" << PaintOpHelper::FlagsToString(op.flags) << ")";
+        str << "DrawTextBlobOp(blob=" << ToString(op.blob)
+            << ", x=" << ToString(op.x) << ", y=" << ToString(op.y)
+            << ", flags=" << ToString(op.flags) << ")";
         break;
       }
       case PaintOpType::Noop: {
@@ -174,8 +181,7 @@
       }
       case PaintOpType::Rotate: {
         const auto& op = static_cast<const RotateOp&>(base_op);
-        str << "RotateOp(degrees="
-            << PaintOpHelper::SkiaTypeToString(op.degrees) << ")";
+        str << "RotateOp(degrees=" << ToString(op.degrees) << ")";
         break;
       }
       case PaintOpType::Save: {
@@ -184,34 +190,31 @@
       }
       case PaintOpType::SaveLayer: {
         const auto& op = static_cast<const SaveLayerOp&>(base_op);
-        str << "SaveLayerOp(bounds="
-            << PaintOpHelper::SkiaTypeToString(op.bounds)
-            << ", flags=" << PaintOpHelper::FlagsToString(op.flags) << ")";
+        str << "SaveLayerOp(bounds=" << ToString(op.bounds)
+            << ", flags=" << ToString(op.flags) << ")";
         break;
       }
       case PaintOpType::SaveLayerAlpha: {
         const auto& op = static_cast<const SaveLayerAlphaOp&>(base_op);
-        str << "SaveLayerAlphaOp(bounds="
-            << PaintOpHelper::SkiaTypeToString(op.bounds)
+        str << "SaveLayerAlphaOp(bounds=" << ToString(op.bounds)
             << ", alpha=" << static_cast<uint32_t>(op.alpha * 255) << ")";
         break;
       }
       case PaintOpType::Scale: {
         const auto& op = static_cast<const ScaleOp&>(base_op);
-        str << "ScaleOp(sx=" << PaintOpHelper::SkiaTypeToString(op.sx)
-            << ", sy=" << PaintOpHelper::SkiaTypeToString(op.sy) << ")";
+        str << "ScaleOp(sx=" << ToString(op.sx) << ", sy=" << ToString(op.sy)
+            << ")";
         break;
       }
       case PaintOpType::SetMatrix: {
         const auto& op = static_cast<const SetMatrixOp&>(base_op);
-        str << "SetMatrixOp(matrix="
-            << PaintOpHelper::SkiaTypeToString(op.matrix) << ")";
+        str << "SetMatrixOp(matrix=" << ToString(op.matrix) << ")";
         break;
       }
       case PaintOpType::Translate: {
         const auto& op = static_cast<const TranslateOp&>(base_op);
-        str << "TranslateOp(dx=" << PaintOpHelper::SkiaTypeToString(op.dx)
-            << ", dy=" << PaintOpHelper::SkiaTypeToString(op.dy) << ")";
+        str << "TranslateOp(dx=" << ToString(op.dx)
+            << ", dy=" << ToString(op.dy) << ")";
         break;
       }
       case PaintOpType::SetNodeId: {
@@ -223,31 +226,39 @@
     return str.str();
   }
 
-  static std::string SkiaTypeToString(const SkScalar& scalar) {
+  static std::string ToString(uint8_t value) {
+    return base::StringPrintf("%d", value);
+  }
+
+  static std::string ToString(const SkScalar& scalar) {
     return base::StringPrintf("%.3f", scalar);
   }
 
-  static std::string SkiaTypeToString(const SkPoint& point) {
+  static std::string ToString(const SkPoint& point) {
     return base::StringPrintf("[%.3f,%.3f]", point.fX, point.fY);
   }
 
-  static std::string SkiaTypeToString(const SkRect& rect) {
+  static std::string ToString(const SkRect& rect) {
     return base::StringPrintf("[%.3f,%.3f %.3fx%.3f]", rect.x(), rect.y(),
                               rect.width(), rect.height());
   }
 
-  static std::string SkiaTypeToString(const SkIRect& rect) {
+  static std::string ToString(const SkIRect& rect) {
     return base::StringPrintf("[%d,%d %dx%d]", rect.x(), rect.y(), rect.width(),
                               rect.height());
   }
 
-  static std::string SkiaTypeToString(const SkRRect& rect) {
+  static std::string ToString(const SkRRect& rect) {
     return base::StringPrintf("[bounded by %.3f,%.3f %.3fx%.3f]",
                               rect.rect().x(), rect.rect().y(),
                               rect.rect().width(), rect.rect().height());
   }
 
-  static std::string SkiaTypeToString(const SkM44& matrix) {
+  static std::string ToString(const SkRegion& rect) {
+    return ToString(rect.getBounds());
+  }
+
+  static std::string ToString(const SkM44& matrix) {
     return base::StringPrintf(
         "[%8.4f %8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f "
         "%8.4f][%8.4f %8.4f %8.4f %8.4f]]",
@@ -257,7 +268,7 @@
         matrix.rc(3, 0), matrix.rc(3, 1), matrix.rc(3, 2), matrix.rc(3, 3));
   }
 
-  static std::string SkiaTypeToString(const SkMatrix& matrix) {
+  static std::string ToString(const SkMatrix& matrix) {
     return base::StringPrintf(
         "[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]]",
         matrix.rc(0, 0), matrix.rc(0, 1), matrix.rc(0, 2), matrix.rc(1, 0),
@@ -265,18 +276,47 @@
         matrix.rc(2, 2));
   }
 
-  static std::string SkiaTypeToString(const SkColor& color) {
+  static std::string ToString(const SkColor& color) {
     return base::StringPrintf("rgba(%d, %d, %d, %d)", SkColorGetR(color),
                               SkColorGetG(color), SkColorGetB(color),
                               SkColorGetA(color));
   }
 
-  static std::string SkiaTypeToString(const SkColor4f& color) {
+  static std::string ToString(const SkColor4f& color) {
     return base::StringPrintf("rgba(%f, %f, %f, %f)", color.fR, color.fG,
                               color.fB, color.fA);
   }
 
-  static std::string SkiaTypeToString(const SkBlendMode& mode) {
+  static std::string ToString(const SkISize& size) {
+    return base::StringPrintf("SkISize(%d, %d)", size.width(), size.height());
+  }
+
+  static std::string ToString(const SkIPoint& point) {
+    return base::StringPrintf("SkIPoint(%d, %d)", point.x(), point.y());
+  }
+
+  static std::string ToString(const SkPoint3& point) {
+    return base::StringPrintf(
+        "SkPoint3(%s, %s, %s)", ToString(point.x()).c_str(),
+        ToString(point.y()).c_str(), ToString(point.z()).c_str());
+  }
+
+  static std::string ToString(SkColorChannel channel) {
+    switch (channel) {
+      case SkColorChannel::kR:
+        return "kR";
+      case SkColorChannel::kG:
+        return "kG";
+      case SkColorChannel::kB:
+        return "kB";
+      case SkColorChannel::kA:
+        return "kA";
+    }
+    NOTREACHED();
+    return "unknown";
+  }
+
+  static std::string ToString(const SkBlendMode& mode) {
     switch (mode) {
       default:
         break;
@@ -342,7 +382,7 @@
     return "<unknown SkBlendMode>";
   }
 
-  static std::string SkiaTypeToString(const SkClipOp& op) {
+  static std::string ToString(const SkClipOp& op) {
     switch (op) {
       default:
         break;
@@ -354,20 +394,18 @@
     return "<unknown SkClipOp>";
   }
 
-  static std::string SkiaTypeToString(const sk_sp<SkData> data) {
-    return data ? "<SkData>" : "(nil)";
+  static std::string ToString(const SkData& data) { return "<SkData>"; }
+
+  static std::string ToString(const ThreadsafePath& path) {
+    return ToString(static_cast<const SkPath&>(path));
   }
 
-  static std::string SkiaTypeToString(const ThreadsafePath& path) {
-    return SkiaTypeToString(static_cast<const SkPath&>(path));
-  }
-
-  static std::string SkiaTypeToString(const SkPath& path) {
+  static std::string ToString(const SkPath& path) {
     // TODO(vmpstr): SkPath has a dump function which we can use here?
     return "<SkPath>";
   }
 
-  static std::string SkiaTypeToString(PaintFlags::FilterQuality quality) {
+  static std::string ToString(PaintFlags::FilterQuality quality) {
     switch (quality) {
       case PaintFlags::FilterQuality::kNone:
         return "kNone_SkFilterQuality";
@@ -381,7 +419,7 @@
     return "<unknown FilterQuality>";
   }
 
-  static std::string SkiaTypeToString(PaintFlags::Cap cap) {
+  static std::string ToString(PaintFlags::Cap cap) {
     switch (cap) {
       case PaintFlags::kButt_Cap:
         return "kButt_Cap";
@@ -393,7 +431,7 @@
     return "<unknown PaintFlags::Cap>";
   }
 
-  static std::string SkiaTypeToString(PaintFlags::Join join) {
+  static std::string ToString(PaintFlags::Join join) {
     switch (join) {
       case PaintFlags::kMiter_Join:
         return "kMiter_Join";
@@ -405,31 +443,73 @@
     return "<unknown PaintFlags::Join>";
   }
 
-  static std::string SkiaTypeToString(const sk_sp<SkColorFilter>& filter) {
-    if (!filter)
-      return "(nil)";
+  static std::string ToString(TurbulencePaintFilter::TurbulenceType type) {
+    switch (type) {
+      case TurbulencePaintFilter::TurbulenceType::kTurbulence:
+        return "kTurbulence";
+      case TurbulencePaintFilter::TurbulenceType::kFractalNoise:
+        return "kFractalNoise";
+    }
+    return "<unknown TurbulencePaintFilter::TurbulenceType>";
+  }
+
+  static std::string ToString(MorphologyPaintFilter::MorphType type) {
+    switch (type) {
+      case MorphologyPaintFilter::MorphType::kDilate:
+        return "kDilate";
+      case MorphologyPaintFilter::MorphType::kErode:
+        return "kErode";
+    }
+    return "<unknown MorphologyPaintFilter::MorphType>";
+  }
+
+  static std::string ToString(PaintFilter::LightingType type) {
+    switch (type) {
+      case PaintFilter::LightingType::kDiffuse:
+        return "kDiffuse";
+      case PaintFilter::LightingType::kSpecular:
+        return "kSpecular";
+    }
+    return "<unknown PaintFilter::LightingType>";
+  }
+
+  static std::string ToString(DropShadowPaintFilter::ShadowMode shadow_mode) {
+    switch (shadow_mode) {
+      case DropShadowPaintFilter::ShadowMode::kDrawShadowAndForeground:
+        return "kDrawShadowAndForeground";
+      case DropShadowPaintFilter::ShadowMode::kDrawShadowOnly:
+        return "kDrawShadowOnly";
+    }
+    return "<unknown DropShadowPaintFilter::ShadowMode>";
+  }
+
+  static std::string ToString(const SkImageFilters::Dither dither) {
+    switch (dither) {
+      case SkImageFilters::Dither::kNo:
+        return "kNo";
+      case SkImageFilters::Dither::kYes:
+        return "kYes";
+    }
+    return "<unknown SkImageFilters::Dither>";
+  }
+
+  static std::string ToString(const SkColorFilter& filter) {
     return "SkColorFilter";
   }
 
-  static std::string SkiaTypeToString(const sk_sp<SkMaskFilter>& filter) {
-    if (!filter)
-      return "(nil)";
+  static std::string ToString(const SkMaskFilter& filter) {
     return "SkMaskFilter";
   }
 
-  static std::string SkiaTypeToString(const sk_sp<SkPathEffect>& effect) {
-    if (!effect)
-      return "(nil)";
+  static std::string ToString(const SkPathEffect& effect) {
     return "SkPathEffect";
   }
 
-  static std::string SkiaTypeToString(const sk_sp<SkDrawLooper>& looper) {
-    if (!looper)
-      return "(nil)";
+  static std::string ToString(const SkDrawLooper& looper) {
     return "SkDrawLooper";
   }
 
-  static std::string EnumToString(PaintCanvas::AnnotationType type) {
+  static std::string ToString(PaintCanvas::AnnotationType type) {
     switch (type) {
       default:
         break;
@@ -443,8 +523,7 @@
     return "<unknown AnnotationType>";
   }
 
-  static std::string EnumToString(
-      const SkCanvas::SrcRectConstraint& constraint) {
+  static std::string ToString(const SkCanvas::SrcRectConstraint& constraint) {
     switch (constraint) {
       default:
         break;
@@ -456,7 +535,7 @@
     return "<unknown SrcRectConstraint>";
   }
 
-  static std::string EnumToString(PaintShader::ScalingBehavior behavior) {
+  static std::string ToString(PaintShader::ScalingBehavior behavior) {
     switch (behavior) {
       case PaintShader::ScalingBehavior::kRasterAtScale:
         return "kRasterAtScale";
@@ -466,7 +545,7 @@
     return "<unknown ScalingBehavior>";
   }
 
-  static std::string EnumToString(PaintShader::Type type) {
+  static std::string ToString(PaintShader::Type type) {
     switch (type) {
       case PaintShader::Type::kEmpty:
         return "kEmpty";
@@ -490,84 +569,84 @@
     return "<unknown PaintShader::Type>";
   }
 
-  static std::string ImageToString(const PaintImage& image) {
+  static std::string ToString(const PaintImage& image) {
     return "<paint image>";
   }
 
-  static std::string SkottieToString(scoped_refptr<SkottieWrapper> skottie) {
+  static std::string ToString(const SkottieWrapper& skottie) {
     std::ostringstream str;
     str << "<skottie [";
-    str << "duration=" << skottie->duration() << " seconds";
-    str << ", width="
-        << PaintOpHelper::SkiaTypeToString(skottie->size().width());
-    str << ", height="
-        << PaintOpHelper::SkiaTypeToString(skottie->size().height());
+    str << "duration=" << skottie.duration() << " seconds";
+    str << ", width=" << ToString(skottie.size().width());
+    str << ", height=" << ToString(skottie.size().height());
     str << "]";
     return str.str();
   }
 
-  static std::string RecordToString(const PaintRecord& record) {
+  static std::string ToString(const PaintRecord& record) {
     return record.empty() ? "(empty)" : "<paint record>";
   }
 
-  static std::string RecordToString(const absl::optional<PaintRecord>& record) {
-    return record ? RecordToString(*record) : "(nil)";
+  static std::string ToString(const SkTextBlob& blob) {
+    return "<sk text blob>";
   }
 
-  static std::string TextBlobToString(const sk_sp<SkTextBlob>& blob) {
-    return blob ? "<sk text blob>" : "(nil)";
+  static std::string ToString(SkTileMode tile_mode) {
+    switch (tile_mode) {
+      case SkTileMode::kClamp:
+        return "kClamp";
+      case SkTileMode::kRepeat:
+        return "kRepeat";
+      case SkTileMode::kMirror:
+        return "kMirror";
+      case SkTileMode::kDecal:
+        return "kDecal";
+    }
+    return "<unknown SkTileMode>";
   }
 
-  static std::string PaintShaderToString(const PaintShader* shader) {
-    if (!shader)
-      return "(nil)";
+  static std::string ToString(const gfx::SizeF& size) {
+    return base::StringPrintf("[%s]", size.ToString().c_str());
+  }
+
+  static std::string ToString(const PaintShader& shader) {
     std::ostringstream str;
-    str << "[type=" << EnumToString(shader->shader_type());
-    str << ", flags=" << shader->flags_;
-    str << ", end_radius=" << shader->end_radius_;
-    str << ", start_radius=" << shader->start_radius_;
-    str << ", tx=" << static_cast<unsigned>(shader->tx_);
-    str << ", ty=" << static_cast<unsigned>(shader->ty_);
-    str << ", fallback_color="
-        << PaintOpHelper::SkiaTypeToString(shader->fallback_color_);
-    str << ", scaling_behavior=" << EnumToString(shader->scaling_behavior_);
-    if (shader->local_matrix_.has_value()) {
-      str << ", local_matrix=" << SkiaTypeToString(*shader->local_matrix_);
+    str << "[type=" << ToString(shader.shader_type());
+    str << ", flags=" << shader.flags_;
+    str << ", end_radius=" << shader.end_radius_;
+    str << ", start_radius=" << shader.start_radius_;
+    str << ", tx=" << static_cast<unsigned>(shader.tx_);
+    str << ", ty=" << static_cast<unsigned>(shader.ty_);
+    str << ", fallback_color=" << ToString(shader.fallback_color_);
+    str << ", scaling_behavior=" << ToString(shader.scaling_behavior_);
+    str << ", local_matrix=" << ToString(shader.local_matrix_);
+    str << ", center=" << ToString(shader.center_);
+    str << ", tile=" << ToString(shader.tile_);
+    str << ", start_point=" << ToString(shader.start_point_);
+    str << ", end_point=" << ToString(shader.end_point_);
+    str << ", start_degrees=" << shader.start_degrees_;
+    str << ", end_degrees=" << shader.end_degrees_;
+    if (shader.shader_type() == PaintShader::Type::kImage) {
+      str << ", image=" << ToString(shader.image_);
     } else {
-      str << ", local_matrix=(nil)";
-    }
-    str << ", center=" << SkiaTypeToString(shader->center_);
-    str << ", tile=" << SkiaTypeToString(shader->tile_);
-    str << ", start_point=" << SkiaTypeToString(shader->start_point_);
-    str << ", end_point=" << SkiaTypeToString(shader->end_point_);
-    str << ", start_degrees=" << shader->start_degrees_;
-    str << ", end_degrees=" << shader->end_degrees_;
-    if (shader->shader_type() == PaintShader::Type::kImage)
-      str << ", image=" << ImageToString(shader->image_);
-    else
       str << ", image=(nil)";
-    str << ", record=" << RecordToString(shader->record_);
-    str << ", id=" << shader->id_;
-    str << ", tile_scale=";
-    if (shader->tile_scale_) {
-      str << "[" << shader->tile_scale_->ToString() << "]";
-    } else {
-      str << "(nil)";
     }
-    if (shader->colors_.size() > 0) {
-      str << ", colors=["
-          << PaintOpHelper::SkiaTypeToString(shader->colors_[0]);
-      for (size_t i = 1; i < shader->colors_.size(); ++i) {
-        str << ", " << PaintOpHelper::SkiaTypeToString(shader->colors_[i]);
+    str << ", record=" << ToString(shader.record_);
+    str << ", id=" << shader.id_;
+    str << ", tile_scale=" << ToString(shader.tile_scale_);
+    if (shader.colors_.size() > 0) {
+      str << ", colors=[" << ToString(shader.colors_[0]);
+      for (size_t i = 1; i < shader.colors_.size(); ++i) {
+        str << ", " << ToString(shader.colors_[i]);
       }
       str << "]";
     } else {
       str << ", colors=(nil)";
     }
-    if (shader->positions_.size() > 0) {
-      str << ", positions=[" << shader->positions_[0];
-      for (size_t i = 1; i < shader->positions_.size(); ++i) {
-        str << ", " << shader->positions_[i];
+    if (shader.positions_.size() > 0) {
+      str << ", positions=[" << shader.positions_[0];
+      for (size_t i = 1; i < shader.positions_.size(); ++i) {
+        str << ", " << shader.positions_[i];
       }
       str << "]";
     } else {
@@ -578,41 +657,288 @@
     return str.str();
   }
 
-  static std::string PaintFilterToString(const sk_sp<PaintFilter> filter) {
-    return filter ? "<PaintFilter>" : "(nil)";
-  }
-
-  static std::string FlagsToString(const PaintFlags& flags) {
+  static std::string ToString(const PaintFilter& base_filter) {
     std::ostringstream str;
     str << std::boolalpha;
-    str << "[color=" << PaintOpHelper::SkiaTypeToString(flags.getColor());
-    str << ", blendMode="
-        << PaintOpHelper::SkiaTypeToString(flags.getBlendMode());
+    switch (base_filter.type()) {
+      case PaintFilter::Type::kNullFilter:
+        str << "NullFilter()";
+        break;
+      case PaintFilter::Type::kColorFilter: {
+        const auto& filter =
+            static_cast<const ColorFilterPaintFilter&>(base_filter);
+        str << "ColorFilterPaintFilter("
+            << "color_filter=" << ToString(filter.color_filter())
+            << ", input=" << ToString(filter.input())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kBlur: {
+        const auto& filter = static_cast<const BlurPaintFilter&>(base_filter);
+
+        str << "BlurPaintFilter("
+            << "sigma_x=" << ToString(filter.sigma_x())
+            << ", sigma_y=" << ToString(filter.sigma_y())
+            << ", tile_mode=" << ToString(filter.tile_mode())
+            << ", input=" << ToString(filter.input())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kDropShadow: {
+        const auto& filter =
+            static_cast<const DropShadowPaintFilter&>(base_filter);
+        str << "DropShadowPaintFilter("
+            << "dx=" << ToString(filter.dx())
+            << ", dy=" << ToString(filter.dy())
+            << ", sigma_x=" << ToString(filter.sigma_x())
+            << ", sigma_y=" << ToString(filter.sigma_y())
+            << ", color=" << ToString(filter.color())
+            << ", shadow_mode=" << ToString(filter.shadow_mode())
+            << ", input=" << ToString(filter.input())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kMagnifier: {
+        const auto& filter =
+            static_cast<const MagnifierPaintFilter&>(base_filter);
+        str << "MagnifierPaintFilter("
+            << "src_rect=" << ToString(filter.src_rect())
+            << ", inset=" << ToString(filter.inset())
+            << ", input=" << ToString(filter.input())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kCompose: {
+        const auto& filter =
+            static_cast<const ComposePaintFilter&>(base_filter);
+        str << "ComposePaintFilter("
+            << "outer=" << ToString(filter.outer())
+            << ", inner=" << ToString(filter.inner())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kAlphaThreshold: {
+        const auto& filter =
+            static_cast<const AlphaThresholdPaintFilter&>(base_filter);
+        str << "AlphaThresholdPaintFilter("
+            << "region=" << ToString(filter.region())
+            << ", inner_min=" << ToString(filter.inner_min())
+            << ", outer_max=" << ToString(filter.outer_max())
+            << ", input=" << ToString(filter.input())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kXfermode: {
+        const auto& filter =
+            static_cast<const XfermodePaintFilter&>(base_filter);
+        str << "XfermodePaintFilter("
+            << "blend_mode=" << ToString(filter.blend_mode())
+            << ", background=" << ToString(filter.background())
+            << ", foreground=" << ToString(filter.foreground())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kArithmetic: {
+        const auto& filter =
+            static_cast<const ArithmeticPaintFilter&>(base_filter);
+        str << "ArithmeticPaintFilter("
+            << "k1=" << filter.k1() << ", k2=" << filter.k2()
+            << ", k3=" << filter.k3() << ", k4=" << filter.k4()
+            << ", enfore_pm_color=" << filter.enforce_pm_color()
+            << ", background=" << ToString(filter.background())
+            << ", foreground=" << ToString(filter.foreground())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kMatrixConvolution: {
+        const auto& filter =
+            static_cast<const MatrixConvolutionPaintFilter&>(base_filter);
+        const SkISize& kernel_size = filter.kernel_size();
+        str << "MatrixConvolutionPaintFilter("
+            << "kernel_size=" << ToString(kernel_size) << ", kernel=[";
+        for (int32_t i = 0; i < kernel_size.width() * kernel_size.height();
+             ++i) {
+          str << (i != 0 ? ", " : "") << ToString(filter.kernel_at(i));
+        }
+        str << "], gain=" << ToString(filter.gain())
+            << ", bias=" << ToString(filter.bias())
+            << ", kernel_offset=" << ToString(filter.kernel_offset())
+            << ", tile_mode=" << ToString(filter.tile_mode())
+            << ", convolve_alpha=" << filter.convolve_alpha()
+            << ", input=" << ToString(filter.input())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kDisplacementMapEffect: {
+        const auto& filter =
+            static_cast<const DisplacementMapEffectPaintFilter&>(base_filter);
+        str << "DisplacementMapEffectPaintFilter("
+            << "channel_x=" << ToString(filter.channel_x())
+            << ", channel_y=" << ToString(filter.channel_y())
+            << ", scale=" << ToString(filter.scale())
+            << ", displacement=" << ToString(filter.displacement())
+            << ", color=" << ToString(filter.color())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kImage: {
+        const auto& filter = static_cast<const ImagePaintFilter&>(base_filter);
+        str << "ImagePaintFilter("
+            << "image=" << ToString(filter.image())
+            << ", src_rect=" << ToString(filter.src_rect())
+            << ", dst_rect=" << ToString(filter.dst_rect())
+            << ", filter_quality=" << ToString(filter.filter_quality())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kPaintRecord: {
+        const auto& filter = static_cast<const RecordPaintFilter&>(base_filter);
+        str << "RecordPaintFilter("
+            << "record=" << ToString(filter.record())
+            << ", record_bounds=" << ToString(filter.record_bounds())
+            << ", raster_scale=" << ToString(filter.raster_scale())
+            << ", scaling_behavior=" << ToString(filter.scaling_behavior())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kMerge: {
+        const auto& filter = static_cast<const MergePaintFilter&>(base_filter);
+        str << "MergePaintFilter("
+            << "input_count=" << filter.input_count() << ", input=[";
+        for (size_t i = 0; i < filter.input_count(); ++i) {
+          str << (i != 0 ? ", " : "") << ToString(filter.input_at(i));
+        }
+        str << "], crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kMorphology: {
+        const auto& filter =
+            static_cast<const MorphologyPaintFilter&>(base_filter);
+        str << "MorphologyPaintFilter("
+            << "morph_type=" << ToString(filter.morph_type())
+            << ", radius_x=" << filter.radius_x()
+            << ", radius_y=" << filter.radius_y()
+            << ", input=" << ToString(filter.input())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kOffset: {
+        const auto& filter = static_cast<const OffsetPaintFilter&>(base_filter);
+        str << "OffsetPaintFilter("
+            << "dx=" << filter.dx() << ", dy=" << filter.dy()
+            << ", input=" << ToString(filter.input())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kTile: {
+        const auto& filter = static_cast<const TilePaintFilter&>(base_filter);
+        str << "TilePaintFilter("
+            << "src=" << ToString(filter.src())
+            << ", dst=" << ToString(filter.dst())
+            << ", input=" << ToString(filter.input())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kTurbulence: {
+        const auto& filter =
+            static_cast<const TurbulencePaintFilter&>(base_filter);
+        str << "TurbulencePaintFilter("
+            << "turbulence_type=" << ToString(filter.turbulence_type())
+            << ", base_frequency_x=" << ToString(filter.base_frequency_x())
+            << ", base_frequency_y=" << ToString(filter.base_frequency_y())
+            << ", num_octaves=" << filter.num_octaves()
+            << ", seed=" << ToString(filter.seed())
+            << ", tile_size=" << ToString(filter.tile_size())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kShader: {
+        const auto& filter = static_cast<const ShaderPaintFilter&>(base_filter);
+        str << "ShaderPaintFilter("
+            << "shader=" << ToString(filter.shader())
+            << ", alpha=" << ToString(filter.alpha())
+            << ", filter_quality=" << ToString(filter.filter_quality())
+            << ", dither=" << ToString(filter.dither())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kMatrix: {
+        const auto& filter = static_cast<const MatrixPaintFilter&>(base_filter);
+        str << "MatrixPaintFilter("
+            << "matrix=" << ToString(filter.matrix())
+            << ", filter_quality=" << ToString(filter.filter_quality())
+            << ", input=" << ToString(filter.input())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kLightingDistant: {
+        const auto& filter =
+            static_cast<const LightingDistantPaintFilter&>(base_filter);
+        str << "LightingDistantPaintFilter("
+            << "lighting_type=" << ToString(filter.lighting_type())
+            << ", direction=" << ToString(filter.direction())
+            << ", light_color=" << ToString(filter.light_color())
+            << ", surface_scale=" << ToString(filter.surface_scale())
+            << ", kconstant=" << ToString(filter.kconstant())
+            << ", shininess=" << ToString(filter.shininess())
+            << ", input=" << ToString(filter.input())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kLightingPoint: {
+        const auto& filter =
+            static_cast<const LightingPointPaintFilter&>(base_filter);
+        str << "LightingPointPaintFilter("
+            << "lighting_type=" << ToString(filter.lighting_type())
+            << ", location=" << ToString(filter.location())
+            << ", light_color=" << ToString(filter.light_color())
+            << ", surface_scale=" << ToString(filter.surface_scale())
+            << ", kconstant=" << ToString(filter.kconstant())
+            << ", shininess=" << ToString(filter.shininess())
+            << ", input=" << ToString(filter.input())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+        break;
+      }
+      case PaintFilter::Type::kLightingSpot: {
+        const auto& filter =
+            static_cast<const LightingSpotPaintFilter&>(base_filter);
+        str << "LightingSpotPaintFilter("
+            << "lighting_type=" << ToString(filter.lighting_type())
+            << ", location=" << ToString(filter.location())
+            << ", target=" << ToString(filter.target())
+            << ", specular_exponent=" << ToString(filter.specular_exponent())
+            << ", cutoff_angle=" << ToString(filter.cutoff_angle())
+            << ", light_color=" << ToString(filter.light_color())
+            << ", surface_scale=" << ToString(filter.surface_scale())
+            << ", kconstant=" << ToString(filter.kconstant())
+            << ", shininess=" << ToString(filter.shininess())
+            << ", input=" << ToString(filter.input())
+            << ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
+      }
+    }
+    return str.str();
+  }
+
+  static std::string ToString(const PaintFlags& flags) {
+    std::ostringstream str;
+    str << std::boolalpha;
+    str << "[color=" << ToString(flags.getColor());
+    str << ", blendMode=" << ToString(flags.getBlendMode());
     str << ", isAntiAlias=" << flags.isAntiAlias();
     str << ", isDither=" << flags.isDither();
-    str << ", filterQuality="
-        << PaintOpHelper::SkiaTypeToString(flags.getFilterQuality());
-    str << ", strokeWidth="
-        << PaintOpHelper::SkiaTypeToString(flags.getStrokeWidth());
-    str << ", strokeMiter="
-        << PaintOpHelper::SkiaTypeToString(flags.getStrokeMiter());
-    str << ", strokeCap="
-        << PaintOpHelper::SkiaTypeToString(flags.getStrokeCap());
-    str << ", strokeJoin="
-        << PaintOpHelper::SkiaTypeToString(flags.getStrokeJoin());
-    str << ", colorFilter="
-        << PaintOpHelper::SkiaTypeToString(flags.getColorFilter());
-    str << ", maskFilter="
-        << PaintOpHelper::SkiaTypeToString(flags.getMaskFilter());
-    str << ", shader=" << PaintOpHelper::PaintShaderToString(flags.getShader());
+    str << ", filterQuality=" << ToString(flags.getFilterQuality());
+    str << ", strokeWidth=" << ToString(flags.getStrokeWidth());
+    str << ", strokeMiter=" << ToString(flags.getStrokeMiter());
+    str << ", strokeCap=" << ToString(flags.getStrokeCap());
+    str << ", strokeJoin=" << ToString(flags.getStrokeJoin());
+    str << ", colorFilter=" << ToString(flags.getColorFilter());
+    str << ", maskFilter=" << ToString(flags.getMaskFilter());
+    str << ", shader=" << ToString(flags.getShader());
     str << ", hasShader=" << flags.HasShader();
     str << ", shaderIsOpaque=" << (flags.HasShader() && flags.ShaderIsOpaque());
-    str << ", pathEffect="
-        << PaintOpHelper::SkiaTypeToString(flags.getPathEffect());
-    str << ", imageFilter="
-        << PaintOpHelper::PaintFilterToString(flags.getImageFilter());
-    str << ", drawLooper="
-        << PaintOpHelper::SkiaTypeToString(flags.getLooper());
+    str << ", pathEffect=" << ToString(flags.getPathEffect());
+    str << ", imageFilter=" << ToString(flags.getImageFilter());
+    str << ", drawLooper=" << ToString(flags.getLooper());
     str << ", supportsFoldingAlpha=" << flags.SupportsFoldingAlpha();
     str << ", isValid=" << flags.IsValid();
     str << ", hasDiscardableImages=" << flags.HasDiscardableImages();
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index a09d7b9..035b772 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -160,7 +160,10 @@
     data_deps = []
 
     if (is_chromeos_ash) {
-      data_deps += [ "//sandbox/linux:chrome_sandbox" ]
+      data_deps += [
+        "//components/variations/cros:evaluate_seed",
+        "//sandbox/linux:chrome_sandbox",
+      ]
       deps += [
         "//components/exo/wayland:ui_controls_protocol_stub",
         "//components/exo/wayland:weston_test_stub",
diff --git a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryModernViewBinder.java b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryModernViewBinder.java
index b63329b..952d757 100644
--- a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryModernViewBinder.java
+++ b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryModernViewBinder.java
@@ -103,6 +103,11 @@
                 chipView.setMaxWidth(Integer.MAX_VALUE);
             }
 
+            // When chips are recycled, the constraint on primary text width (that is applied on
+            // long credit card suggestions) can persist. Reset such constraints.
+            chipView.getPrimaryTextView().setMaxWidth(Integer.MAX_VALUE);
+            chipView.getPrimaryTextView().setEllipsize(null);
+
             chipView.getPrimaryTextView().setText(item.getSuggestion().getLabel());
             if (item.getSuggestion().getItemTag() != null
                     && !item.getSuggestion().getItemTag().isEmpty()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/BackPressHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/BackPressHelper.java
index 30da932d..c7ab576 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/BackPressHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/BackPressHelper.java
@@ -8,6 +8,8 @@
 import androidx.activity.OnBackPressedDispatcher;
 import androidx.lifecycle.LifecycleOwner;
 
+import org.chromium.components.browser_ui.widget.gesture.BackPressHandler;
+
 /**
  * Helper class for back press event handling via {@link OnBackPressedDisptacher}. This is
  * a recommended way over {@link Activity#onBackPressed}. Refer to the Android developer's guide
@@ -15,9 +17,10 @@
  */
 public final class BackPressHelper {
     /**
-     * Handles back press event.
+     * @deprecated Handles back press event. #onBackPressed is deprecated starting from U. Prefer
+     * {@link BackPressHandler} whenever possible.
      */
-    public interface BackPressedHandler {
+    public interface ObsoleteBackPressedHandler {
         /**
          * @return {@code true} if the event was consumed. {@code false} otherwise.
          */
@@ -25,14 +28,36 @@
     }
 
     /**
-     * Create a {@link BackPressHelper} that can handle a chain of handlers.
+     * @deprecated Create a {@link BackPressHelper} that can handle a chain of handlers.
+     * Prefer {@link #create(LifecycleOwner, OnBackPressedDispatcher, BackPressHandler)}
+     * whenever possible.
      * @param lifecycleOwner {@link LifecycleOwner} managing the back press logic's lifecycle.
      * @param dispatcher {@link OnBackPressedDispatcher} that holds other callbacks.
-     * @param handler {@link BackPressedHandler} implementing the caller's back press handler.
+     * @param handler {@link ObsoleteBackPressedHandler} implementing the caller's back press
+     *         handler.
+     */
+    @Deprecated
+    public static void create(LifecycleOwner lifecycleOwner, OnBackPressedDispatcher dispatcher,
+            ObsoleteBackPressedHandler handler) {
+        new BackPressHelper(lifecycleOwner, dispatcher, handler);
+    }
+
+    /**
+     * Register a {@link BackPressHandler} on a given {@link  OnBackPressedDispatcher}.
+     * @param lifecycleOwner {@link LifecycleOwner} managing the back press logic's lifecycle.
+     * @param dispatcher {@link OnBackPressedDispatcher} that holds other callbacks.
+     * @param handler {@link BackPressHandler} observing back press state and consuming back press.
      */
     public static void create(LifecycleOwner lifecycleOwner, OnBackPressedDispatcher dispatcher,
-            BackPressedHandler handler) {
-        new BackPressHelper(lifecycleOwner, dispatcher, handler);
+            BackPressHandler handler) {
+        var callback = new OnBackPressedCallback(/* enabled */ false) {
+            @Override
+            public void handleOnBackPressed() {
+                handler.handleBackPress();
+            }
+        };
+        handler.getHandleBackPressChangedSupplier().addObserver(callback::setEnabled);
+        dispatcher.addCallback(lifecycleOwner, callback);
     }
 
     /**
@@ -52,7 +77,7 @@
     }
 
     private BackPressHelper(LifecycleOwner lifecycleOwner, OnBackPressedDispatcher dispatcher,
-            BackPressedHandler handler) {
+            ObsoleteBackPressedHandler handler) {
         dispatcher.addCallback(lifecycleOwner, new OnBackPressedCallback(true) {
             @Override
             public void handleOnBackPressed() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkActivity.java
index 8be62d67d..63748ed 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkActivity.java
@@ -14,6 +14,7 @@
 import org.chromium.chrome.browser.BackPressHelper;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.SnackbarActivity;
+import org.chromium.chrome.browser.back_press.BackPressManager;
 import org.chromium.chrome.browser.bookmarks.BookmarkManager;
 import org.chromium.chrome.browser.bookmarks.BookmarkPage;
 import org.chromium.components.bookmarks.BookmarkId;
@@ -42,7 +43,12 @@
         if (TextUtils.isEmpty(url)) url = UrlConstants.BOOKMARKS_URL;
         mBookmarkManager.updateForUrl(url);
         setContentView(mBookmarkManager.getView());
-        BackPressHelper.create(this, getOnBackPressedDispatcher(), mBookmarkManager::onBackPressed);
+        if (BackPressManager.isSecondaryActivityEnabled()) {
+            BackPressHelper.create(this, getOnBackPressedDispatcher(), mBookmarkManager);
+        } else {
+            BackPressHelper.create(
+                    this, getOnBackPressedDispatcher(), mBookmarkManager::onBackPressed);
+        }
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/ServiceTracingProxyProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/base/ServiceTracingProxyProvider.java
index 813fc473..c299d61 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/base/ServiceTracingProxyProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/base/ServiceTracingProxyProvider.java
@@ -27,6 +27,7 @@
 
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Proxy;
@@ -75,17 +76,23 @@
 
         @Override
         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-            if (!ThreadUtils.runningOnUiThread()) return method.invoke(mSystemImpl, args);
+            try {
+                if (!ThreadUtils.runningOnUiThread()) return method.invoke(mSystemImpl, args);
 
-            long start = SystemClock.elapsedRealtime();
-            Object result = method.invoke(mSystemImpl, args);
-            long durationMs = SystemClock.elapsedRealtime() - start;
+                long start = SystemClock.elapsedRealtime();
+                Object result = method.invoke(mSystemImpl, args);
+                long durationMs = SystemClock.elapsedRealtime() - start;
 
-            if (durationMs >= MINIMUM_IPC_TRACE_DURATION_MS) {
-                TraceEvent.instantAndroidIPC(
-                        mSystemImpl.getClass().getName() + "#" + method.getName(), durationMs);
+                if (durationMs >= MINIMUM_IPC_TRACE_DURATION_MS) {
+                    TraceEvent.instantAndroidIPC(
+                            mSystemImpl.getClass().getName() + "#" + method.getName(), durationMs);
+                }
+                return result;
+            } catch (InvocationTargetException e) {
+                // Need to rethrow the cause or the proxy will generate
+                // UndeclaredThrowableExceptions that callers won't be expecting.
+                throw e.getCause();
             }
-            return result;
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
index a9291545..0bda5cf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
@@ -20,6 +20,8 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.ObserverList;
 import org.chromium.base.metrics.RecordUserAction;
+import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.app.bookmarks.BookmarkActivity;
 import org.chromium.chrome.browser.commerce.ShoppingFeatures;
@@ -38,6 +40,7 @@
 import org.chromium.components.bookmarks.BookmarkType;
 import org.chromium.components.browser_ui.util.ConversionUtils;
 import org.chromium.components.browser_ui.widget.dragreorder.DragStateDelegate;
+import org.chromium.components.browser_ui.widget.gesture.BackPressHandler;
 import org.chromium.components.browser_ui.widget.selectable_list.SelectableListLayout;
 import org.chromium.components.browser_ui.widget.selectable_list.SelectableListToolbar.SearchDelegate;
 import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelegate;
@@ -53,8 +56,9 @@
  * views and shared logics between tablet and phone. For tablet/phone specific logics, see
  * {@link BookmarkActivity} (phone) and {@link BookmarkPage} (tablet).
  */
-public class BookmarkManager
-        implements BookmarkDelegate, SearchDelegate, PartnerBookmarksReader.FaviconUpdateObserver {
+public class BookmarkManager implements BookmarkDelegate, SearchDelegate,
+                                        PartnerBookmarksReader.FaviconUpdateObserver,
+                                        BackPressHandler {
     private static final int FAVICON_MAX_CACHE_SIZE_BYTES =
             10 * ConversionUtils.BYTES_PER_MEGABYTE; // 10MB
 
@@ -71,7 +75,23 @@
     private RecyclerView mRecyclerView;
     private BookmarkActionBar mToolbar;
     private SelectionDelegate<BookmarkId> mSelectionDelegate;
-    private final Stack<BookmarkUIState> mStateStack = new Stack<>();
+    private final Stack<BookmarkUIState> mStateStack = new Stack<>() {
+        @Override
+        public BookmarkUIState push(BookmarkUIState item) {
+            // The back press state depends on the size of stack. So push/pop item first in order
+            // to keep the size update-to-date.
+            var state = super.push(item);
+            onBackPressStateChanged();
+            return state;
+        }
+
+        @Override
+        public synchronized BookmarkUIState pop() {
+            var state = super.pop();
+            onBackPressStateChanged();
+            return state;
+        }
+    };
     private LargeIconBridge mLargeIconBridge;
     private boolean mFaviconsNeedRefresh;
     private String mInitialUrl;
@@ -83,6 +103,9 @@
     private BookmarkDragStateDelegate mDragStateDelegate;
     private AdapterDataObserver mAdapterDataObserver;
 
+    private final ObservableSupplierImpl<Boolean> mBackPressStateSupplier =
+            new ObservableSupplierImpl<>();
+
     private final BookmarkModelObserver mBookmarkModelObserver = new BookmarkModelObserver() {
         @Override
         public void bookmarkNodeChildrenReordered(BookmarkItem node) {
@@ -220,6 +243,8 @@
                 mMainView.findViewById(R.id.selectable_list);
         mSelectableListLayout = selectableList;
         mSelectableListLayout.initializeEmptyView(R.string.bookmarks_folder_empty);
+        mSelectableListLayout.getHandleBackPressChangedSupplier().addObserver(
+                (x) -> onBackPressStateChanged());
 
         mAdapter = new BookmarkItemsAdapter(mContext, snackbarManager);
 
@@ -338,6 +363,28 @@
         return false;
     }
 
+    private void onBackPressStateChanged() {
+        if (mIsDestroyed) {
+            mBackPressStateSupplier.set(false);
+            return;
+        }
+        mBackPressStateSupplier.set(
+                Boolean.TRUE.equals(mSelectableListLayout.getHandleBackPressChangedSupplier().get())
+                || mStateStack.size() > 1);
+    }
+
+    // BackPressHandler Overrides
+    @Override
+    public void handleBackPress() {
+        var ret = onBackPressed();
+        assert ret;
+    }
+
+    @Override
+    public ObservableSupplier<Boolean> getHandleBackPressChangedSupplier() {
+        return mBackPressStateSupplier;
+    }
+
     /**
      * @return The view that shows the main browsing history UI.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabUma.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabUma.java
index e3cb45e..99295ea 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabUma.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabUma.java
@@ -129,26 +129,7 @@
     }
 
     /**
-     * Record the tab state transition into histograms.
-     * @param prevState Previous state of the tab.
-     * @param newState New state of the tab.
-     * @param delta Time elapsed from the last state transition in milliseconds.
-     */
-    private void recordTabStateTransition(int prevState, int newState, long delta) {
-        if (prevState == TAB_STATE_INITIAL) {
-            RecordHistogram.recordEnumeratedHistogram("Tabs.StateTransfer.Target_Initial", newState,
-                    TAB_STATE_MAX);
-        } else if (prevState == TAB_STATE_ACTIVE) {
-            RecordHistogram.recordEnumeratedHistogram("Tabs.StateTransfer.Target_Active", newState,
-                    TAB_STATE_MAX);
-        } else if (prevState == TAB_STATE_INACTIVE) {
-            RecordHistogram.recordEnumeratedHistogram("Tabs.StateTransfer.Target_Inactive",
-                    newState, TAB_STATE_MAX);
-        }
-    }
-
-    /**
-     * Updates saved TabState and its timestamp. Records the state transition into the histogram.
+     * Updates saved TabState and its timestamp.
      * @param newState New state of the tab.
      */
     private void updateTabState(int newState) {
@@ -156,7 +137,6 @@
             return;
         }
         long now = System.currentTimeMillis();
-        recordTabStateTransition(mLastTabState, newState, now - mLastTabStateChangeMillis);
         mLastTabStateChangeMillis = now;
         mLastTabState = newState;
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkTest.java
index c4496fd..42945ce 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkTest.java
@@ -533,6 +533,87 @@
 
     @Test
     @MediumTest
+    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE})
+    public void testSearchBookmarks_pressBack() throws Exception {
+        BookmarkPromoHeader.forcePromoStateForTests(SyncPromoState.PROMO_FOR_SYNC_TURNED_OFF_STATE);
+        BookmarkId folder = addFolder(TEST_FOLDER_TITLE);
+        addBookmark(TEST_PAGE_TITLE_GOOGLE, mTestPage, folder);
+        addBookmark(TEST_PAGE_TITLE_FOO, mTestPageFoo, folder);
+        openBookmarkManager();
+
+        RecyclerView.Adapter adapter = getAdapter();
+        final BookmarkDelegate delegate = getBookmarkManager();
+
+        // Open the new folder where these bookmarks were created.
+        openFolder(folder);
+
+        Assert.assertEquals(
+                Boolean.TRUE, getBookmarkManager().getHandleBackPressChangedSupplier().get());
+
+        TestThreadUtils.runOnUiThreadBlocking(delegate::openSearchUI);
+
+        Assert.assertEquals(BookmarkUIState.STATE_SEARCHING, delegate.getCurrentState());
+        Assert.assertEquals(
+                "Wrong number of items after showing search UI. The promo should be hidden.", 2,
+                adapter.getItemCount());
+
+        Assert.assertEquals(
+                Boolean.TRUE, getBookmarkManager().getHandleBackPressChangedSupplier().get());
+
+        // Exit search UI.
+        TestThreadUtils.runOnUiThreadBlocking(
+                mBookmarkActivity.getOnBackPressedDispatcher()::onBackPressed);
+        Assert.assertNotEquals(BookmarkUIState.STATE_SEARCHING, delegate.getCurrentState());
+
+        // Enter search UI again.
+        TestThreadUtils.runOnUiThreadBlocking(delegate::openSearchUI);
+
+        searchBookmarks("Google");
+        RecyclerViewTestUtils.waitForStableRecyclerView(mItemsContainer);
+        Assert.assertEquals("Wrong number of items after searching.", 1,
+                mItemsContainer.getAdapter().getItemCount());
+
+        BookmarkRow itemView =
+                (BookmarkRow) mItemsContainer.findViewHolderForLayoutPosition(0).itemView;
+
+        toggleSelectionAndEndAnimation(getIdByPosition(0), itemView);
+
+        // Make sure the Item "test" is selected.
+        CriteriaHelper.pollUiThread(
+                itemView::isChecked, "Expected item \"test\" to become selected");
+
+        TestThreadUtils.runOnUiThreadBlocking(
+                mBookmarkActivity.getOnBackPressedDispatcher()::onBackPressed);
+
+        // Clear selection but still in search UI.
+        CriteriaHelper.pollUiThread(
+                () -> !itemView.isChecked(), "Expected item \"test\" to become not selected");
+        Assert.assertEquals(BookmarkUIState.STATE_SEARCHING, delegate.getCurrentState());
+        Assert.assertEquals(
+                Boolean.TRUE, getBookmarkManager().getHandleBackPressChangedSupplier().get());
+
+        // Exit search UI.
+        TestThreadUtils.runOnUiThreadBlocking(
+                mBookmarkActivity.getOnBackPressedDispatcher()::onBackPressed);
+        Assert.assertEquals(BookmarkUIState.STATE_FOLDER, delegate.getCurrentState());
+
+        // Exit folder.
+        Assert.assertEquals(
+                Boolean.TRUE, getBookmarkManager().getHandleBackPressChangedSupplier().get());
+        TestThreadUtils.runOnUiThreadBlocking(
+                mBookmarkActivity.getOnBackPressedDispatcher()::onBackPressed);
+        Assert.assertEquals(BookmarkUIState.STATE_FOLDER, delegate.getCurrentState());
+
+        // Exit bookmark activity.
+        Assert.assertEquals(
+                Boolean.FALSE, getBookmarkManager().getHandleBackPressChangedSupplier().get());
+        TestThreadUtils.runOnUiThreadBlocking(
+                mBookmarkActivity.getOnBackPressedDispatcher()::onBackPressed);
+        ApplicationTestUtils.waitForActivityState(mBookmarkActivity, Stage.DESTROYED);
+    }
+
+    @Test
+    @MediumTest
     public void testSearchBookmarks_Delete() throws Exception {
         BookmarkPromoHeader.forcePromoStateForTests(SyncPromoState.NO_PROMO);
         BookmarkId testFolder = addFolder(TEST_FOLDER_TITLE);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflineTestUtil.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflineTestUtil.java
index d6d4aa37..f7b27f4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflineTestUtil.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflineTestUtil.java
@@ -10,6 +10,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
 import org.chromium.base.task.PostTask;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CriteriaHelper;
@@ -31,7 +32,8 @@
 public class OfflineTestUtil {
     // Forces request coordinator to process the requests in the queue.
     public static void startRequestCoordinatorProcessing() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> nativeStartRequestCoordinatorProcessing());
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> OfflineTestUtilJni.get().startRequestCoordinatorProcessing());
     }
 
     // Gets all the URLs in the request queue.
@@ -39,7 +41,7 @@
         final AtomicReference<SavePageRequest[]> result = new AtomicReference<>();
         final CallbackHelper callbackHelper = new CallbackHelper();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            nativeGetRequestsInQueue((SavePageRequest[] requests) -> {
+            OfflineTestUtilJni.get().getRequestsInQueue((SavePageRequest[] requests) -> {
                 result.set(requests);
                 callbackHelper.notifyCalled();
             });
@@ -54,10 +56,11 @@
                 new AtomicReference<List<OfflinePageItem>>();
         final CallbackHelper callbackHelper = new CallbackHelper();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            nativeGetAllPages(new ArrayList<OfflinePageItem>(), (List<OfflinePageItem> items) -> {
-                result.set(items);
-                callbackHelper.notifyCalled();
-            });
+            OfflineTestUtilJni.get().getAllPages(
+                    new ArrayList<OfflinePageItem>(), (List<OfflinePageItem> items) -> {
+                        result.set(items);
+                        callbackHelper.notifyCalled();
+                    });
         });
         callbackHelper.waitForCallback(0);
         return result.get();
@@ -69,7 +72,7 @@
         final CallbackHelper callbackHelper = new CallbackHelper();
         final AtomicReference<String> result = new AtomicReference<String>();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            nativeDumpRequestCoordinatorState((String dump) -> {
+            OfflineTestUtilJni.get().dumpRequestCoordinatorState((String dump) -> {
                 result.set(dump);
                 callbackHelper.notifyCalled();
             });
@@ -108,7 +111,7 @@
         final AtomicReference<byte[]> result = new AtomicReference<>();
         final CallbackHelper callbackHelper = new CallbackHelper();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            nativeGetRawThumbnail(offlineId, (byte[] rawThumbnail) -> {
+            OfflineTestUtilJni.get().getRawThumbnail(offlineId, (byte[] rawThumbnail) -> {
                 result.set(rawThumbnail);
                 callbackHelper.notifyCalled();
             });
@@ -147,21 +150,24 @@
     public static void interceptWithOfflineError(String url) throws TimeoutException {
         final CallbackHelper callbackHelper = new CallbackHelper();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            nativeInterceptWithOfflineError(url, () -> callbackHelper.notifyCalled());
+            OfflineTestUtilJni.get().interceptWithOfflineError(
+                    url, () -> callbackHelper.notifyCalled());
         });
         callbackHelper.waitForCallback(0);
     }
 
     // Clears all previous intercepts installed by interceptWithOfflineError.
     public static void clearIntercepts() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> nativeClearIntercepts());
+        TestThreadUtils.runOnUiThreadBlocking(() -> OfflineTestUtilJni.get().clearIntercepts());
     }
 
     // Waits for the connectivity state to change in the native network change notifier.
     public static void waitForConnectivityState(boolean connected) {
         AtomicBoolean done = new AtomicBoolean();
         TestThreadUtils.runOnUiThreadBlocking(
-                () -> nativeWaitForConnectivityState(connected, () -> done.set(true)));
+                ()
+                        -> OfflineTestUtilJni.get().waitForConnectivityState(
+                                connected, () -> done.set(true)));
         CriteriaHelper.pollInstrumentationThread(() -> done.get());
     }
 
@@ -169,22 +175,26 @@
     // also ensures that the server-enabled check is due.
     public static void setPrefetchingEnabledByServer(boolean enabled) {
         TestThreadUtils.runOnUiThreadBlocking(
-                () -> { nativeSetPrefetchingEnabledByServer(enabled); });
+                () -> { OfflineTestUtilJni.get().setPrefetchingEnabledByServer(enabled); });
     }
 
     public static void setGCMTokenForTesting(String gcmToken) {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { nativeSetGCMTokenForTesting(gcmToken); });
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> { OfflineTestUtilJni.get().setGCMTokenForTesting(gcmToken); });
     }
 
-    private static native void nativeGetRequestsInQueue(Callback<SavePageRequest[]> callback);
-    private static native void nativeGetAllPages(
-            List<OfflinePageItem> offlinePages, final Callback<List<OfflinePageItem>> callback);
-    private static native void nativeGetRawThumbnail(long offlineId, Callback<byte[]> callback);
-    private static native void nativeStartRequestCoordinatorProcessing();
-    private static native void nativeInterceptWithOfflineError(String url, Runnable readyRunnable);
-    private static native void nativeClearIntercepts();
-    private static native void nativeDumpRequestCoordinatorState(Callback<String> callback);
-    private static native void nativeWaitForConnectivityState(boolean connected, Runnable callback);
-    private static native void nativeSetPrefetchingEnabledByServer(boolean enabled);
-    private static native void nativeSetGCMTokenForTesting(String gcmToken);
+    @NativeMethods
+    interface Natives {
+        void getRequestsInQueue(Callback<SavePageRequest[]> callback);
+        void getAllPages(
+                List<OfflinePageItem> offlinePages, final Callback<List<OfflinePageItem>> callback);
+        void getRawThumbnail(long offlineId, Callback<byte[]> callback);
+        void startRequestCoordinatorProcessing();
+        void interceptWithOfflineError(String url, Runnable readyRunnable);
+        void clearIntercepts();
+        void dumpRequestCoordinatorState(Callback<String> callback);
+        void waitForConnectivityState(boolean connected, Runnable callback);
+        void setPrefetchingEnabledByServer(boolean enabled);
+        void setGCMTokenForTesting(String gcmToken);
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchTestBridge.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchTestBridge.java
index 806be79f..d61d539 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchTestBridge.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchTestBridge.java
@@ -5,27 +5,32 @@
 package org.chromium.chrome.browser.offlinepages.prefetch;
 
 import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
 
 /** Prefetch test Java to native bridge. */
 @JNINamespace("offline_pages::prefetch")
 public class PrefetchTestBridge {
     public static void enableLimitlessPrefetching(boolean enabled) {
-        nativeEnableLimitlessPrefetching(enabled);
+        PrefetchTestBridgeJni.get().enableLimitlessPrefetching(enabled);
     }
     public static boolean isLimitlessPrefetchingEnabled() {
-        return nativeIsLimitlessPrefetchingEnabled();
+        return PrefetchTestBridgeJni.get().isLimitlessPrefetchingEnabled();
     }
     public static void insertIntoCachedImageFetcher(String url, byte[] imageData) {
-        nativeInsertIntoCachedImageFetcher(url, imageData);
+        PrefetchTestBridgeJni.get().insertIntoCachedImageFetcher(url, imageData);
     }
     public static void addCandidatePrefetchURL(String url, String title, String thumbnailUrl,
             String faviconUrl, String snippet, String attribution) {
-        nativeAddCandidatePrefetchURL(url, title, thumbnailUrl, faviconUrl, snippet, attribution);
+        PrefetchTestBridgeJni.get().addCandidatePrefetchURL(
+                url, title, thumbnailUrl, faviconUrl, snippet, attribution);
     }
 
-    static native void nativeEnableLimitlessPrefetching(boolean enabled);
-    static native boolean nativeIsLimitlessPrefetchingEnabled();
-    static native void nativeInsertIntoCachedImageFetcher(String url, byte[] imageData);
-    static native void nativeAddCandidatePrefetchURL(String url, String title, String thumbnailUrl,
-            String faviconUrl, String snippet, String attribution);
+    @NativeMethods
+    interface Natives {
+        void enableLimitlessPrefetching(boolean enabled);
+        boolean isLimitlessPrefetchingEnabled();
+        void insertIntoCachedImageFetcher(String url, byte[] imageData);
+        void addCandidatePrefetchURL(String url, String title, String thumbnailUrl,
+                String faviconUrl, String snippet, String attribution);
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/query_tiles/QueryTileFakeServer.java b/chrome/android/javatests/src/org/chromium/chrome/browser/query_tiles/QueryTileFakeServer.java
index 2933e18..2d2c8d43 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/query_tiles/QueryTileFakeServer.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/query_tiles/QueryTileFakeServer.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.query_tiles;
 
 import org.chromium.base.Callback;
+import org.chromium.base.annotations.NativeMethods;
 
 /**
  * Spins up a test server and starts serving query tiles in native.
@@ -19,9 +20,13 @@
      */
     public static void setupFakeServer(
             int levels, int tilesPerLevel, Callback<Boolean> onFetchCompletedCallback) {
-        nativeSetupFakeServer(onFetchCompletedCallback, levels, tilesPerLevel);
+        QueryTileFakeServerJni.get().setupFakeServer(
+                onFetchCompletedCallback, levels, tilesPerLevel);
     }
 
-    static native void nativeSetupFakeServer(
-            Callback<Boolean> onFetchCompletedCallback, int levels, int tilesPerLevel);
+    @NativeMethods
+    interface Natives {
+        void setupFakeServer(
+                Callback<Boolean> onFetchCompletedCallback, int levels, int tilesPerLevel);
+    }
 }
\ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/subresource_filter/TestRulesetPublisher.java b/chrome/android/javatests/src/org/chromium/chrome/browser/subresource_filter/TestRulesetPublisher.java
index 05bd57a..9ff6bbdb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/subresource_filter/TestRulesetPublisher.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/subresource_filter/TestRulesetPublisher.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.subresource_filter;
 
 import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.NativeMethods;
 
 /**
  * Class which aids in publishing test rulesets for SubresourceFilter instrumentation tests.
@@ -14,7 +15,8 @@
     private boolean mPublished;
 
     public void createAndPublishRulesetDisallowingSuffixForTesting(String suffix) {
-        nativeCreateAndPublishRulesetDisallowingSuffixForTesting(suffix);
+        TestRulesetPublisherJni.get().createAndPublishRulesetDisallowingSuffixForTesting(
+                this, suffix);
     }
 
     public boolean isPublished() {
@@ -26,5 +28,9 @@
         mPublished = true;
     }
 
-    private native void nativeCreateAndPublishRulesetDisallowingSuffixForTesting(String suffix);
+    @NativeMethods
+    interface Natives {
+        void createAndPublishRulesetDisallowingSuffixForTesting(
+                TestRulesetPublisher obj, String suffix);
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabUmaTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabUmaTest.java
index e4c9272d..84f968d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabUmaTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabUmaTest.java
@@ -193,36 +193,21 @@
     public void testTabStateTransition() throws Exception {
         String transitionToInactive = "Tabs.StateTransfer.Time_Active_Inactive";
         String transitionToClosed = "Tabs.StateTransfer.Time_Active_Closed";
-        String transitionTargetInitial = "Tabs.StateTransfer.Target_Initial";
-        String transitionTargetActive = "Tabs.StateTransfer.Target_Active";
-        String transitionTargetInactive = "Tabs.StateTransfer.Target_Inactive";
 
-        Assert.assertEquals(1, getHistogram(transitionTargetInitial));
-        Assert.assertEquals(0, getHistogram(transitionTargetInactive));
-        Assert.assertEquals(0, getHistogram(transitionTargetActive));
         Assert.assertEquals(0, getHistogram(transitionToInactive));
         Assert.assertEquals(0, getHistogram(transitionToClosed));
 
         createLiveTab(/* foreground= */ false, /* kill= */ false);
-        Assert.assertEquals(2, getHistogram(transitionTargetInitial));
-        Assert.assertEquals(1, getHistogram(transitionTargetInactive));
-        Assert.assertEquals(0, getHistogram(transitionTargetActive));
         Assert.assertEquals(0, getHistogram(transitionToInactive));
         Assert.assertEquals(0, getHistogram(transitionToClosed));
 
         // Test a live tab killed in background before shown.
         createLiveTab(/* foreground= */ false, /* kill= */ true);
-        Assert.assertEquals(3, getHistogram(transitionTargetInitial));
-        Assert.assertEquals(2, getHistogram(transitionTargetInactive));
-        Assert.assertEquals(0, getHistogram(transitionTargetActive));
         Assert.assertEquals(0, getHistogram(transitionToInactive));
         Assert.assertEquals(0, getHistogram(transitionToClosed));
 
         // Test a tab created in background but not loaded eagerly.
         final Tab frozenBgTab = createLazilyLoadedTab(/* show= */ true);
-        Assert.assertEquals(4, getHistogram(transitionTargetInitial));
-        Assert.assertEquals(3, getHistogram(transitionTargetInactive));
-        Assert.assertEquals(0, getHistogram(transitionTargetActive));
         Assert.assertEquals(0, getHistogram(transitionToInactive));
         Assert.assertEquals(0, getHistogram(transitionToClosed));
 
@@ -238,17 +223,11 @@
             return tab;
         });
 
-        Assert.assertEquals(5, getHistogram(transitionTargetInitial));
-        Assert.assertEquals(4, getHistogram(transitionTargetInactive));
-        Assert.assertEquals(0, getHistogram(transitionTargetActive));
         Assert.assertEquals(0, getHistogram(transitionToInactive));
         Assert.assertEquals(0, getHistogram(transitionToClosed));
 
         // Test a foreground tab.
         createLiveTab(/* foreground= */ true, /* kill= */ false);
-        Assert.assertEquals(6, getHistogram(transitionTargetInitial));
-        Assert.assertEquals(4, getHistogram(transitionTargetInactive));
-        Assert.assertEquals(0, getHistogram(transitionTargetActive));
         Assert.assertEquals(0, getHistogram(transitionToInactive));
         Assert.assertEquals(0, getHistogram(transitionToClosed));
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/test/MockCertVerifierRuleAndroid.java b/chrome/android/javatests/src/org/chromium/chrome/browser/test/MockCertVerifierRuleAndroid.java
index c918e4e..339f12f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/test/MockCertVerifierRuleAndroid.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/test/MockCertVerifierRuleAndroid.java
@@ -25,29 +25,28 @@
     protected void before() {
         NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess();
         mNativePtr = MockCertVerifierRuleAndroidJni.get().init();
-        nativeSetResult(mNativePtr, mResult);
-        nativeSetUp(mNativePtr);
+        MockCertVerifierRuleAndroidJni.get().setResult(mNativePtr, mResult);
+        MockCertVerifierRuleAndroidJni.get().setUp(mNativePtr);
     }
 
     public void setResult(int result) {
         mResult = result;
         if (mNativePtr != 0) {
-            nativeSetResult(mNativePtr, result);
+            MockCertVerifierRuleAndroidJni.get().setResult(mNativePtr, result);
         }
     }
 
     @Override
     protected void after() {
-        nativeTearDown(mNativePtr);
+        MockCertVerifierRuleAndroidJni.get().tearDown(mNativePtr);
         mNativePtr = 0;
     }
 
-    private native void nativeSetUp(long nativeMockCertVerifierRuleAndroid);
-    private native void nativeSetResult(long nativeMockCertVerifierRuleAndroid, int result);
-    private native void nativeTearDown(long nativeMockCertVerifierRuleAndroid);
-
     @NativeMethods
     interface Natives {
         long init();
+        void setUp(long nativeMockCertVerifierRuleAndroid);
+        void setResult(long nativeMockCertVerifierRuleAndroid, int result);
+        void tearDown(long nativeMockCertVerifierRuleAndroid);
     }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/BackPressHelperUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/BackPressHelperUnitTest.java
index e544827..7fbed96 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/BackPressHelperUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/BackPressHelperUnitTest.java
@@ -29,9 +29,9 @@
 @Config(manifest = Config.NONE)
 public class BackPressHelperUnitTest {
     @Mock
-    private BackPressHelper.BackPressedHandler mBackPressedHandler;
+    private BackPressHelper.ObsoleteBackPressedHandler mBackPressedHandler;
     @Mock
-    private BackPressHelper.BackPressedHandler mBackPressedHandler2;
+    private BackPressHelper.ObsoleteBackPressedHandler mBackPressedHandler2;
     @Mock
     private LifecycleOwner mLifecycleOwner;
     private LifecycleRegistry mLifecycle;
diff --git a/chrome/android/monochrome/scripts/monochrome_python_tests.py b/chrome/android/monochrome/scripts/monochrome_python_tests.py
index ceaf82ec..9ce9577 100755
--- a/chrome/android/monochrome/scripts/monochrome_python_tests.py
+++ b/chrome/android/monochrome/scripts/monochrome_python_tests.py
@@ -51,7 +51,10 @@
   # Add them to the parser because typ.Runner checks that all arguments
   # are known. crbug.com/1084351
   parser.add_argument('--avd-config', help='Unused')
-  parser.add_argument('--use-persistent-shell', help='Unused')
+  parser.add_argument(
+      '--use-persistent-shell',
+      action='store_true',
+      help='Unused')
   return parser
 
 
diff --git a/chrome/app/chrome_main.cc b/chrome/app/chrome_main.cc
index 059813b5..64c0e48 100644
--- a/chrome/app/chrome_main.cc
+++ b/chrome/app/chrome_main.cc
@@ -150,6 +150,10 @@
 
   // Chrome-specific process modes.
   if (headless::IsHeadlessMode()) {
+    if (command_line->GetArgs().size() > 1) {
+      LOG(ERROR) << "Multiple targets are not supported in headless mode.";
+      return chrome::RESULT_CODE_UNSUPPORTED_PARAM;
+    }
     headless::SetUpCommandLine(command_line);
   } else {
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC) || \
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 12c4159..74e3bb8e 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -350,10 +350,6 @@
       change nontranslateable parts of the messages into placeholders (using the
       <ph> element).  You can also use the 'grit add' tool to help you identify
       nontranslateable parts and create placeholders for them. -->
-      <message name="IDS_BACK_BUTTON_AUTHENTICATOR_REQUEST_DIALOG" desc="A back button for authenticator request dialog.">
-        Go back
-      </message>
-
       <if expr="is_win">
         <message name="IDS_BACKGROUND_APP_INSTALLED_BALLOON_TITLE" desc="The title of the balloon that is displayed when a background app is installed">
           New background app added
@@ -13098,12 +13094,6 @@
       <message name="IDS_WEBAUTHN_CONTINUE" desc="Label of a button to continue in the dialog shown when using a security key.">
         Continue
       </message>
-      <message name="IDS_WEBAUTHN_TRANSPORT_SELECTION_TITLE" desc="Title of the dialog instructing the user to choose how they want to connect their security key with their computer, e.g. USB or Bluetooth.">
-        Verify your identity with <ph name="APP_NAME">$1<ex>google.com</ex></ph>
-      </message>
-      <message name="IDS_WEBAUTHN_TRANSPORT_SELECTION_DESCRIPTION" desc="Description in the dialog instructing the user to choose how they want to connect their security key with their computer, e.g. USB or Bluetooth.">
-        Pick an option
-      </message>
       <message name="IDS_WEBAUTHN_TRANSPORT_USB" desc="Menu item text. The user selects this to use a security key (an external physical device for user authentication) plugged in to the USB port of the computer.">
         USB security key
       </message>
@@ -13128,9 +13118,6 @@
       <message name="IDS_WEBAUTHN_ERROR_WRONG_KEY_TITLE" desc="Title of the dialog informing the user that they are trying to register a security key (an external physical device for user authentication) that they have already registered with the given web site before or they are trying to sign in to a given web site with a key they have not previously registered on that site.">
         Try a different security key
       </message>
-      <message name="IDS_WEBAUTHN_ERROR_WRONG_KEY_REGISTER_DESCRIPTION" desc="Description in the dialog informing the user that they are trying to register a security key (an external physical device for user authentication) that they have already registered with the given web site before.">
-        You already registered this security key. You don't have to register it again.
-      </message>
       <message name="IDS_WEBAUTHN_ERROR_WRONG_DEVICE_TITLE" desc="Title of the dialog informing the user that they are trying to register a passkey on a device that they have already registered with the given web site before.">
         Try a different device
       </message>
@@ -13186,9 +13173,6 @@
         </message>
       </if>
 
-      <message name="IDS_WEBAUTHN_TRANSPORT_POPUP_LABEL" desc="Menu item text. The user selects this to verify their identity on a web site (i.e. sign in) using a different hardware-based authentication mechanism from what they have selected previously.">
-        Choose another option
-      </message>
       <message name="IDS_WEBAUTHN_TRANSPORT_POPUP_USB" desc="Menu item text. The user selects this to verify their identity on a web site (i.e. sign in) using a security key (an external physical device for user authentication) plugged in to the USB port of the computer.">
         Verify via USB
       </message>
@@ -13210,9 +13194,6 @@
       <message name="IDS_WEBAUTHN_CABLE_ACTIVATE_TITLE_DEVICE" desc="Title of the dialog shown when the user tries to sign-in using a phone as a security key.">
         Check your device
       </message>
-      <message name="IDS_WEBAUTHN_CABLE_ACTIVATE_TITLE_ALT" desc="Title of the dialog shown when the user tries to sign-in using a phone as a security key. The word 'unlock' refers to using a PIN, pattern, or biometric to unlock the phone.">
-        Unlock your phone
-      </message>
       <message name="IDS_WEBAUTHN_CABLE_ACTIVATE_DESCRIPTION" desc="Contents of the dialog shown when the user tries to sign-in using a phone as a security key.">
         A notification was sent to your phone to confirm it's you.
       </message>
@@ -13220,15 +13201,9 @@
         A notification was sent to <ph name="DEVICE_NAME">$1<ex>Ted's Pixel 6 Pro</ex></ph>
       </message>
 
-      <message name="IDS_WEBAUTHN_CABLEV2_SERVERLINK_DESCRIPTION" desc="Contents of the dialog shown when the user tries to sign-in using a phone as a security key.">
-        <ph name="WEBSITE"><ex>accounts.google.com</ex>$1</ph> sent a notification to your phone. To confirm it's you, follow the steps there.
-      </message>
       <message name="IDS_WEBAUTHN_CABLEV2_SERVERLINK_TROUBLE" desc="This message is shown as a link below IDS_WEBAUTHN_CABLEV2_SERVERLINK_DESCRIPTION. The 'it' referenced here is the notification mentioned in that message.">
         Didn't get it?
       </message>
-      <message name="IDS_WEBAUTHN_CABLEV2_SERVERLINK_TROUBLE_ALT" desc="This message is shown as a link below IDS_WEBAUTHN_CABLEV2_SERVERLINK_DESCRIPTION. The translation of this string should match TC 8961468651054969074.">
-        Try another way
-      </message>
       <message name="IDS_WEBAUTHN_CABLEV2_AOA_TITLE" desc="Contents of the dialog shown when the user tries to sign-in using a phone as a security key. The 'cable' is a physical USB cable.">
         Connect your phone with a cable
       </message>
@@ -13238,12 +13213,6 @@
       <message name="IDS_WEBAUTHN_CABLEV2_AOA_REQUEST_DESCRIPTION" desc="Potentially displayed in a permissions dialog on Android to describe the type of request that a computer, that is connected over USB, is making. In this context the request from the computer is to use the Android device as a security key. A 'security key' is typically a physical USB token used for authentication (e.g. a gNubby) but in this case the phone is acting as one. The translation of 'security key' should match the phrase used in TC IDs such as 1685482178220389035 and 7775033610159191691">
         Security key request
       </message>
-      <message name="IDS_WEBAUTHN_CABLEV2_2ND_FACTOR_DESCRIPTION" desc="The contents of a dialog shown when the user tries to sign-in using a phone as a security key, or tries to register their phone as a security key for a future sign-in. A security key is traditionally a small USB device that is touched to confirm a sign-in (e.g. a gNubby) and, in this context, the phone is replacing the need for a separate device. The placeholder for the notification title will be replaced with the string that will appear in the notification on the phone. These messages are 4300134428943426639 and 581442427601260656.">
-        <ph name="WEBSITE"><ex>accounts.google.com</ex>$1</ph> sent a notification to your phone. To confirm it's you, tap the “<ph name="NOTIFICATIONTITLE"><ex>Verify with this phone</ex>$2</ph>” notification and follow the steps.
-      </message>
-      <message name="IDS_WEBAUTHN_CABLEV2_ADD_PHONE" desc="The label on a button-like element in a list of options. Clicking this causes Chrome to show a QR code that the user can scan with their phone to use that phone for signing into a website. Here 'phone' is used as a short hand for smartphone.">
-        Use phone with a QR code
-      </message>
       <message name="IDS_WEBAUTHN_PASSKEY_DIFFERENT_DEVICE_LABEL" desc="The label on a button-like element in a list of options. Clicking this causes Chrome to show a QR code that the user can scan with their phone to use that phone for signing into a website. Here 'phone' is used as a short hand for smartphone.">
         A different device
       </message>
@@ -13338,9 +13307,6 @@
       </message>
 
       <!-- WebAuthn account selection for resident keys -->
-      <message name="IDS_WEBAUTHN_SELECT_ACCOUNT" desc="The title on a dialog where the user is expected to select an account from a list. For example, the list may include several identities, e.g. joe@gmail.com, mary@gmail.com, and the user has to select one to login as.">
-        Select an account to sign in
-      </message>
       <message name="IDS_WEBAUTHN_UNKNOWN_ACCOUNT" desc="Label shown to the user on the list of account names if the account stored does not have a name associated to it.">
         Unknown account
       </message>
@@ -13480,7 +13446,6 @@
       </message>
    </if>
 
-   <!-- WebAuthn strings that are used on both Android and Desktop -->
    <message name="IDS_CABLEV2_MAKE_CREDENTIAL_NOTIFICATION_TITLE" desc="The title of a notification shown on Android that informs the user that a website wishes to register their phone for signing into that website." formatter_data="android_java">
      Verify with this phone
    </message>
diff --git a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLEV2_2ND_FACTOR_DESCRIPTION.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLEV2_2ND_FACTOR_DESCRIPTION.png.sha1
deleted file mode 100644
index 759ae051..0000000
--- a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLEV2_2ND_FACTOR_DESCRIPTION.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-e779c56e3ed54693d15e83d2411db7772898cb3c
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLEV2_ADD_PHONE.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLEV2_ADD_PHONE.png.sha1
deleted file mode 100644
index 8a1d283..0000000
--- a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLEV2_ADD_PHONE.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-ab81de45cc01f427997b8991b6c3cb26520b2622
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLEV2_SERVERLINK_DESCRIPTION.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLEV2_SERVERLINK_DESCRIPTION.png.sha1
deleted file mode 100644
index bdc6e8c..0000000
--- a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLEV2_SERVERLINK_DESCRIPTION.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-72765005b97f9095a0db3e652b678ffccd898cb9
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLEV2_SERVERLINK_TROUBLE_ALT.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLEV2_SERVERLINK_TROUBLE_ALT.png.sha1
deleted file mode 100644
index cac448650..0000000
--- a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLEV2_SERVERLINK_TROUBLE_ALT.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-bc15915906ee7fa6ee0c2e1e76e9d8cdc443c3a4
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLE_ACTIVATE_TITLE_ALT.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLE_ACTIVATE_TITLE_ALT.png.sha1
deleted file mode 100644
index aa79a08b..0000000
--- a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLE_ACTIVATE_TITLE_ALT.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-b1aeaf10a30f189ff3c5aefc2afdeaf40cb7674d
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_SELECT_ACCOUNT.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEBAUTHN_SELECT_ACCOUNT.png.sha1
deleted file mode 100644
index eb2bdfa..0000000
--- a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_SELECT_ACCOUNT.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-8ec6ce2880de07cf46f8011a38a23048f93d0a31
\ No newline at end of file
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn
index 288b8fb4..392bbc7 100644
--- a/chrome/app/vector_icons/BUILD.gn
+++ b/chrome/app/vector_icons/BUILD.gn
@@ -174,21 +174,8 @@
     "webauthn/passkey_phone_dark.icon",
     "webauthn/passkey_usb.icon",
     "webauthn/passkey_usb_dark.icon",
-    "webauthn/webauthn_aoa.icon",
     "webauthn/webauthn_error.icon",
-    "webauthn/webauthn_error_bluetooth.icon",
-    "webauthn/webauthn_error_bluetooth_dark.icon",
     "webauthn/webauthn_error_dark.icon",
-    "webauthn/webauthn_fingerprint.icon",
-    "webauthn/webauthn_fingerprint_dark.icon",
-    "webauthn/webauthn_permission.icon",
-    "webauthn/webauthn_permission_dark.icon",
-    "webauthn/webauthn_phone.icon",
-    "webauthn/webauthn_phone_dark.icon",
-    "webauthn/webauthn_usb.icon",
-    "webauthn/webauthn_usb_dark.icon",
-    "webauthn/webauthn_welcome.icon",
-    "webauthn/webauthn_welcome_dark.icon",
     "zoom_minus.icon",
     "zoom_plus.icon",
   ]
diff --git a/chrome/app/vector_icons/webauthn/webauthn_aoa.icon b/chrome/app/vector_icons/webauthn/webauthn_aoa.icon
deleted file mode 100644
index 4816a69..0000000
--- a/chrome/app/vector_icons/webauthn/webauthn_aoa.icon
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2021 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, 448,
-NEW_PATH,
-PATH_COLOR_ARGB, 0x0A, 0x00, 0x00, 0x00,
-MOVE_TO, 0, 0,
-R_H_LINE_TO, 448,
-R_V_LINE_TO, 119,
-H_LINE_TO, 0,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xff, 0xe8, 0xe9, 0xeb,
-STROKE, 1,
-MOVE_TO, 372.49f, 33.44f,
-H_LINE_TO, 329,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-CUBIC_TO, 346.88f, 20.19f, 351.46f, 18, 356.36f, 18,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xff, 0xe8, 0xe9, 0xeb,
-STROKE, 1,
-MOVE_TO, 60.49f, 72.44f,
-H_LINE_TO, 17,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-CUBIC_TO, 34.88f, 59.19f, 39.46f, 57, 44.36f, 57,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xff, 0xbd, 0xc1, 0xc6,
-R_MOVE_TO, 213.99f, 127.93f,
-R_H_LINE_TO, -83.95f,
-R_ARC_TO, 3.85f, 3.85f, 0, 0, 1, -3.85f, -3.85f,
-R_V_LINE_TO, -4.01f,
-R_ARC_TO, 0.74f, 0.74f, 0, 0, 1, 1.49f, 0,
-R_V_LINE_TO, 4.01f,
-R_ARC_TO, 2.36f, 2.36f, 0, 0, 0, 2.36f, 2.36f,
-R_H_LINE_TO, 83.95f,
-R_ARC_TO, 2.36f, 2.36f, 0, 0, 0, 2.36f, -2.36f,
-V_LINE_TO, 71.55f,
-R_ARC_TO, 2.36f, 2.36f, 0, 0, 0, -2.36f, -2.36f,
-R_H_LINE_TO, -22.23f,
-R_ARC_TO, 0.74f, 0.74f, 0, 0, 1, 0, -1.49f,
-R_H_LINE_TO, 22.23f,
-R_ARC_TO, 3.85f, 3.85f, 0, 0, 1, 3.85f, 3.85f,
-R_V_LINE_TO, 52.54f,
-R_ARC_TO, 3.85f, 3.85f, 0, 0, 1, -3.85f, 3.85f,
-CLOSE,
-R_MOVE_TO, -87.06f, -18.26f,
-R_ARC_TO, 0.74f, 0.74f, 0, 0, 1, -0.74f, -0.74f,
-V_LINE_TO, 71.55f,
-R_ARC_TO, 3.85f, 3.85f, 0, 0, 1, 3.85f, -3.85f,
-R_H_LINE_TO, 50.59f,
-R_ARC_TO, 0.74f, 0.74f, 0, 0, 1, 0, 1.49f,
-R_H_LINE_TO, -50.59f,
-R_ARC_TO, 2.36f, 2.36f, 0, 0, 0, -2.36f, 2.36f,
-R_V_LINE_TO, 37.38f,
-R_ARC_TO, 0.74f, 0.74f, 0, 0, 1, -0.74f, 0.74f,
-CLOSE,
-ROUND_RECT, 132.16f, 73.51f, 79.69f, 48.60f, 0,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xff, 0xbd, 0xc1, 0xc6,
-R_MOVE_TO, 120.21f, 131.12f,
-R_V_LINE_TO, 1.46f,
-R_ARC_TO, 3.1f, 3.1f, 0, 0, 0, 3.1f, 3.1f,
-R_H_LINE_TO, 97.4f,
-R_ARC_TO, 3.1f, 3.1f, 0, 0, 0, 3.1f, -3.1f,
-R_V_LINE_TO, -1.46f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xff, 0x39, 0x82, 0xf8,
-R_MOVE_TO, 255.28f, 134.51f,
-R_H_LINE_TO, -28.04f,
-R_ARC_TO, 0.93f, 0.93f, 0, 1, 1, 0, -1.86f,
-R_H_LINE_TO, 28.04f,
-R_CUBIC_TO, 11.14f, 0, 19.7f, -1.61f, 26.95f, -5.07f,
-R_ARC_TO, 0.93f, 0.93f, 0, 0, 1, 0.8f, 1.68f,
-R_CUBIC_TO, -7.51f, 3.58f, -16.33f, 5.25f, -27.75f, 5.25f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xff, 0x39, 0x82, 0xf8,
-R_MOVE_TO, 320.91f, 125.47f,
-R_CUBIC_TO, -2.34f, -5.05f, -7.06f, -8.55f, -12.32f, -9.13f,
-R_CUBIC_TO, -7.87f, -0.87f, -12.24f, 2.18f, -17.3f, 5.71f,
-R_CUBIC_TO, -0.96f, 0.67f, -1.96f, 1.37f, -3.02f, 2.07f,
-R_ARC_TO, 0.93f, 0.93f, 0, 1, 0, 1.02f, 1.55f,
-R_CUBIC_TO, 1.08f, -0.71f, 2.09f, -1.41f, 3.06f, -2.09f,
-R_CUBIC_TO, 4.95f, -3.46f, 8.85f, -6.19f, 16.03f, -5.39f,
-R_CUBIC_TO, 4.62f, 0.51f, 8.77f, 3.6f, 10.84f, 8.07f,
-R_CUBIC_TO, 1.87f, 4.05f, 1.64f, 8.47f, -0.62f, 11.84f,
-R_CUBIC_TO, -3.67f, 5.46f, -9.22f, 7.54f, -15.22f, 5.71f,
-R_CUBIC_TO, -10.29f, -3.14f, -20.71f, -17.38f, -20.71f, -38.51f,
-V_LINE_TO, 92.83f,
-R_H_LINE_TO, 1.72f,
-V_LINE_TO, 85.14f,
-H_LINE_TO, 279.11f,
-R_V_LINE_TO, 7.69f,
-R_H_LINE_TO, 1.72f,
-R_V_LINE_TO, 12.45f,
-R_CUBIC_TO, 0, 10.2f, 2.35f, 19.55f, 6.8f, 27.05f,
-R_CUBIC_TO, 4.02f, 6.77f, 9.43f, 11.47f, 15.22f, 13.24f,
-R_ARC_TO, 16.38f, 16.38f, 0, 0, 0, 4.79f, 0.74f,
-R_CUBIC_TO, 4.94f, 0, 9.35f, -2.49f, 12.51f, -7.19f,
-R_CUBIC_TO, 2.63f, -3.91f, 2.92f, -9.01f, 0.77f, -13.65f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xff, 0xbd, 0xc1, 0xc6,
-R_MOVE_TO, 295.2f, 85.14f,
-R_H_LINE_TO, -26.88f,
-R_ARC_TO, 4.42f, 4.42f, 0, 0, 1, -4.42f, -4.42f,
-R_V_LINE_TO, -61.04f,
-R_ARC_TO, 0.74f, 0.74f, 0, 0, 1, 1.49f, 0,
-R_V_LINE_TO, 61.04f,
-R_ARC_TO, 2.94f, 2.94f, 0, 0, 0, 2.93f, 2.93f,
-R_H_LINE_TO, 26.86f,
-R_ARC_TO, 0.75f, 0.75f, 0, 0, 1, 0.75f, 0.74f,
-R_ARC_TO, 0.74f, 0.74f, 0, 0, 1, -0.74f, 0.74f,
-CLOSE,
-R_MOVE_TO, 3.66f, -9.16f,
-R_ARC_TO, 0.74f, 0.74f, 0, 0, 1, -0.74f, -0.74f,
-V_LINE_TO, 14.22f,
-R_ARC_TO, 2.94f, 2.94f, 0, 0, 0, -2.93f, -2.93f,
-R_H_LINE_TO, -26.86f,
-R_ARC_TO, 0.74f, 0.74f, 0, 0, 1, -0.01f, -1.49f,
-R_H_LINE_TO, 26.87f,
-R_ARC_TO, 4.42f, 4.42f, 0, 0, 1, 4.42f, 4.42f,
-R_V_LINE_TO, 61.03f,
-R_ARC_TO, 0.74f, 0.74f, 0, 0, 1, -0.74f, 0.74f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xff, 0xff, 0xff, 0xff,
-ROUND_RECT, 132.16f, 73.51f, 79.69f, 48.60f, 0,
-ROUND_RECT, 268.43f, 14.95f, 26.95f, 65.44f, 0
diff --git a/chrome/app/vector_icons/webauthn/webauthn_error_bluetooth.icon b/chrome/app/vector_icons/webauthn/webauthn_error_bluetooth.icon
deleted file mode 100644
index eef25e6..0000000
--- a/chrome/app/vector_icons/webauthn/webauthn_error_bluetooth.icon
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2019 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, 448,
-NEW_PATH,
-PATH_COLOR_ARGB, 0x0A, 0x00, 0x00, 0x00,
-MOVE_TO, 0, 0,
-R_H_LINE_TO, 448,
-R_V_LINE_TO, 119,
-H_LINE_TO, 0,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xE8, 0xE9, 0xEB,
-MOVE_TO, 318.49f, 67.44f,
-H_LINE_TO, 275,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 302.36f, 52,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-MOVE_TO, 372.49f, 33.44f,
-H_LINE_TO, 329,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 356.36f, 18,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-MOVE_TO, 60.49f, 72.44f,
-H_LINE_TO, 17,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 44.36f, 57,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xBD, 0xC1, 0xC6,
-MOVE_TO, 119.45f, 73.49f,
-R_LINE_TO, 7, 7.12f,
-R_LINE_TO, -5.96f, 6.06f,
-LINE_TO, 125.75f, 92,
-LINE_TO, 137, 80.57f,
-LINE_TO, 115.73f, 59,
-H_LINE_TO, 112,
-R_V_LINE_TO, 19.04f,
-R_LINE_TO, 7.45f, 7.57f,
-R_V_LINE_TO, -12.11f,
-CLOSE,
-MOVE_TO, 91.29f, 67,
-LINE_TO, 86, 72.25f,
-R_LINE_TO, 24.71f, 24.53f,
-R_LINE_TO, -20.96f, 20.81f,
-R_LINE_TO, 5.29f, 5.25f,
-R_LINE_TO, 17.21f, -17.08f,
-V_LINE_TO, 134,
-H_LINE_TO, 116,
-R_LINE_TO, 16.09f, -15.97f,
-R_LINE_TO, 8.63f, 8.52f,
-R_LINE_TO, 5.29f, -5.25f,
-LINE_TO, 91.29f, 67,
-CLOSE,
-MOVE_TO, 120, 120,
-R_V_LINE_TO, -14,
-R_LINE_TO, 7, 7,
-R_LINE_TO, -7, 7,
-CLOSE
diff --git a/chrome/app/vector_icons/webauthn/webauthn_error_bluetooth_dark.icon b/chrome/app/vector_icons/webauthn/webauthn_error_bluetooth_dark.icon
deleted file mode 100644
index 724a010..0000000
--- a/chrome/app/vector_icons/webauthn/webauthn_error_bluetooth_dark.icon
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2019 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, 448,
-NEW_PATH,
-PATH_COLOR_ARGB, 0x18, 0x00, 0x00, 0x00,
-MOVE_TO, 0, 0,
-R_H_LINE_TO, 448,
-R_V_LINE_TO, 119,
-H_LINE_TO, 0,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 318.49f, 67.44f,
-H_LINE_TO, 275,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 302.36f, 52,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-MOVE_TO, 372.49f, 33.44f,
-H_LINE_TO, 329,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 356.36f, 18,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-MOVE_TO, 60.49f, 72.44f,
-H_LINE_TO, 17,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 44.36f, 57,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 119.45f, 73.49f,
-R_LINE_TO, 7, 7.12f,
-R_LINE_TO, -5.96f, 6.06f,
-LINE_TO, 125.75f, 92,
-LINE_TO, 137, 80.57f,
-LINE_TO, 115.73f, 59,
-H_LINE_TO, 112,
-R_V_LINE_TO, 19.04f,
-R_LINE_TO, 7.45f, 7.57f,
-R_V_LINE_TO, -12.11f,
-CLOSE,
-MOVE_TO, 91.29f, 67,
-LINE_TO, 86, 72.25f,
-R_LINE_TO, 24.71f, 24.53f,
-R_LINE_TO, -20.96f, 20.81f,
-R_LINE_TO, 5.29f, 5.25f,
-R_LINE_TO, 17.21f, -17.08f,
-V_LINE_TO, 134,
-H_LINE_TO, 116,
-R_LINE_TO, 16.09f, -15.97f,
-R_LINE_TO, 8.63f, 8.52f,
-R_LINE_TO, 5.29f, -5.25f,
-LINE_TO, 91.29f, 67,
-CLOSE,
-MOVE_TO, 120, 120,
-R_V_LINE_TO, -14,
-R_LINE_TO, 7, 7,
-R_LINE_TO, -7, 7,
-CLOSE
diff --git a/chrome/app/vector_icons/webauthn/webauthn_fingerprint.icon b/chrome/app/vector_icons/webauthn/webauthn_fingerprint.icon
deleted file mode 100644
index 003d4b4..0000000
--- a/chrome/app/vector_icons/webauthn/webauthn_fingerprint.icon
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2020 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, 448,
-NEW_PATH,
-PATH_COLOR_ARGB, 0x0A, 0x00, 0x00, 0x00,
-MOVE_TO, 0, 0,
-R_H_LINE_TO, 448,
-R_V_LINE_TO, 119,
-H_LINE_TO, 0,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xE8, 0xE9, 0xEB,
-MOVE_TO, 318.49f, 67.44f,
-LINE_TO, 296.74f, 67.44f,
-LINE_TO, 285.51f, 67.44f,
-LINE_TO, 275, 67.44f,
-CUBIC_TO, 275.36f, 61.96f, 279.94f, 57.62f, 285.51f, 57.62f,
-CUBIC_TO, 286.69f, 57.62f, 287.87f, 57.82f, 289.01f, 58.23f,
-LINE_TO, 289.48f, 58.39f,
-LINE_TO, 289.79f, 58.01f,
-CUBIC_TO, 292.88f, 54.19f, 297.46f, 52, 302.36f, 52,
-CUBIC_TO, 311.02f, 52, 318.12f, 58.87f, 318.49f, 67.44f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xE8, 0xE9, 0xEB,
-MOVE_TO, 372.49f, 33.44f,
-LINE_TO, 350.74f, 33.44f,
-LINE_TO, 339.51f, 33.44f,
-LINE_TO, 329, 33.44f,
-CUBIC_TO, 329.36f, 27.96f, 333.94f, 23.62f, 339.51f, 23.62f,
-CUBIC_TO, 340.69f, 23.62f, 341.87f, 23.82f, 343.01f, 24.23f,
-LINE_TO, 343.48f, 24.39f,
-LINE_TO, 343.79f, 24.01f,
-CUBIC_TO, 346.88f, 20.19f, 351.46f, 18, 356.36f, 18,
-CUBIC_TO, 365.02f, 18, 372.12f, 24.87f, 372.49f, 33.44f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xE8, 0xE9, 0xEB,
-MOVE_TO, 60.49f, 72.44f,
-LINE_TO, 38.74f, 72.44f,
-LINE_TO, 27.51f, 72.44f,
-LINE_TO, 17, 72.44f,
-CUBIC_TO, 17.36f, 66.96f, 21.94f, 62.62f, 27.51f, 62.62f,
-CUBIC_TO, 28.69f, 62.62f, 29.87f, 62.82f, 31.01f, 63.23f,
-LINE_TO, 31.48f, 63.39f,
-LINE_TO, 31.79f, 63.01f,
-CUBIC_TO, 34.88f, 59.19f, 39.46f, 57, 44.36f, 57,
-CUBIC_TO, 53.02f, 57, 60.12f, 63.87f, 60.49f, 72.44f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
-CIRCLE, 128, 87, 37.0576923,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xE8, 0xE9, 0xEB,
-CIRCLE, 128, 87, 37.0576923,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xBD, 0xC0, 0xC5,
-MOVE_TO, 140.08f, 47.81f,
-CUBIC_TO, 136.26f, 46.63f, 132.21f, 46, 128, 46,
-CUBIC_TO, 122.76f, 46, 117.75f, 46.98f, 113.15f, 48.77f,
-CUBIC_TO, 107.25f, 51.07f, 102.01f, 54.69f, 97.8f, 59.27f,
-MOVE_TO, 87, 87,
-CUBIC_TO, 87, 91.36f, 87.68f, 95.56f, 88.94f, 99.5f,
-MOVE_TO, 101.58f, 118.35f,
-CUBIC_TO, 106.75f, 122.72f, 113.02f, 125.82f, 119.92f, 127.2f,
-CUBIC_TO, 122.53f, 127.73f, 125.23f, 128, 128, 128,
-CUBIC_TO, 139.43f, 128, 149.77f, 123.32f, 157.21f, 115.77f,
-CUBIC_TO, 161.97f, 110.94f, 165.55f, 104.92f, 167.45f, 98.2f,
-MOVE_TO, 169, 87,
-CUBIC_TO, 169, 80.71f, 167.59f, 74.76f, 165.06f, 69.43f,
-CUBIC_TO, 162.59f, 64.23f, 159.05f, 59.63f, 154.73f, 55.91f,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x1A, 0x73, 0xE8,
-MOVE_TO, 142.03f, 69.83f,
-CUBIC_TO, 141.84f, 69.83f, 141.65f, 69.78f, 141.48f, 69.68f,
-CUBIC_TO, 136.84f, 67.35f, 132.82f, 66.36f, 128.01f, 66.36f,
-CUBIC_TO, 123.23f, 66.36f, 118.68f, 67.47f, 114.55f, 69.68f,
-CUBIC_TO, 113.97f, 69.99f, 113.24f, 69.78f, 112.91f, 69.21f,
-CUBIC_TO, 112.59f, 68.65f, 112.81f, 67.91f, 113.39f, 67.61f,
-CUBIC_TO, 117.88f, 65.23f, 122.82f, 64, 128.01f, 64,
-CUBIC_TO, 133.16f, 64, 137.66f, 65.11f, 142.59f, 67.58f,
-CUBIC_TO, 143.19f, 67.89f, 143.41f, 68.6f, 143.1f, 69.17f,
-CUBIC_TO, 142.88f, 69.59f, 142.47f, 69.83f, 142.03f, 69.83f,
-LINE_TO, 142.03f, 69.83f,
-CLOSE,
-MOVE_TO, 107.49f, 82.77f,
-CUBIC_TO, 107.25f, 82.77f, 107.01f, 82.7f, 106.79f, 82.55f,
-CUBIC_TO, 106.24f, 82.16f, 106.12f, 81.4f, 106.5f, 80.84f,
-CUBIC_TO, 108.89f, 77.4f, 111.93f, 74.71f, 115.55f, 72.82f,
-CUBIC_TO, 123.14f, 68.84f, 132.84f, 68.82f, 140.45f, 72.79f,
-CUBIC_TO, 144.07f, 74.68f, 147.11f, 77.35f, 149.5f, 80.76f,
-CUBIC_TO, 149.88f, 81.3f, 149.76f, 82.09f, 149.21f, 82.48f,
-CUBIC_TO, 148.65f, 82.87f, 147.91f, 82.75f, 147.52f, 82.19f,
-CUBIC_TO, 145.35f, 79.1f, 142.59f, 76.67f, 139.33f, 74.98f,
-CUBIC_TO, 132.41f, 71.37f, 123.55f, 71.37f, 116.64f, 75,
-CUBIC_TO, 113.36f, 76.72f, 110.61f, 79.17f, 108.43f, 82.26f,
-CUBIC_TO, 108.24f, 82.6f, 107.88f, 82.77f, 107.49f, 82.77f,
-LINE_TO, 107.49f, 82.77f,
-CLOSE,
-MOVE_TO, 122.26f, 111.91f,
-CUBIC_TO, 121.95f, 111.91f, 121.64f, 111.79f, 121.42f, 111.55f,
-CUBIC_TO, 119.33f, 109.43f, 118.2f, 108.07f, 116.58f, 105.13f,
-CUBIC_TO, 114.92f, 102.14f, 114.06f, 98.49f, 114.06f, 94.58f,
-CUBIC_TO, 114.06f, 87.36f, 120.17f, 81.48f, 127.68f, 81.48f,
-CUBIC_TO, 135.18f, 81.48f, 141.29f, 87.36f, 141.29f, 94.58f,
-CUBIC_TO, 141.29f, 95.26f, 140.76f, 95.8f, 140.09f, 95.8f,
-CUBIC_TO, 139.42f, 95.8f, 138.89f, 95.26f, 138.89f, 94.58f,
-CUBIC_TO, 138.89f, 88.7f, 133.86f, 83.91f, 127.68f, 83.91f,
-CUBIC_TO, 121.49f, 83.91f, 116.46f, 88.7f, 116.46f, 94.58f,
-CUBIC_TO, 116.46f, 98.08f, 117.23f, 101.31f, 118.7f, 103.94f,
-CUBIC_TO, 120.24f, 106.73f, 121.3f, 107.92f, 123.15f, 109.82f,
-CUBIC_TO, 123.61f, 110.31f, 123.61f, 111.06f, 123.15f, 111.55f,
-CUBIC_TO, 122.89f, 111.79f, 122.58f, 111.91f, 122.26f, 111.91f,
-CLOSE,
-MOVE_TO, 139.38f, 108.02f,
-CUBIC_TO, 136.55f, 108.02f, 134.06f, 107.29f, 132.02f, 105.83f,
-CUBIC_TO, 128.49f, 103.34f, 126.38f, 99.3f, 126.38f, 95.01f,
-CUBIC_TO, 126.38f, 94.32f, 126.9f, 93.78f, 127.56f, 93.78f,
-CUBIC_TO, 128.23f, 93.78f, 128.75f, 94.32f, 128.75f, 95.01f,
-CUBIC_TO, 128.75f, 98.49f, 130.46f, 101.77f, 133.35f, 103.79f,
-CUBIC_TO, 135.04f, 104.97f, 137, 105.54f, 139.38f, 105.54f,
-CUBIC_TO, 139.95f, 105.54f, 140.89f, 105.46f, 141.84f, 105.29f,
-CUBIC_TO, 142.48f, 105.17f, 143.1f, 105.61f, 143.22f, 106.3f,
-CUBIC_TO, 143.34f, 106.97f, 142.91f, 107.61f, 142.25f, 107.73f,
-CUBIC_TO, 140.89f, 108, 139.71f, 108.02f, 139.38f, 108.02f,
-LINE_TO, 139.38f, 108.02f,
-CLOSE,
-MOVE_TO, 135.03f, 112.56f,
-CUBIC_TO, 134.93f, 112.56f, 134.81f, 112.53f, 134.71f, 112.51f,
-CUBIC_TO, 130.89f, 111.44f, 128.38f, 110, 125.76f, 107.4f,
-CUBIC_TO, 122.39f, 104.02f, 120.54f, 99.53f, 120.54f, 94.71f,
-CUBIC_TO, 120.54f, 90.77f, 123.86f, 87.57f, 127.95f, 87.57f,
-CUBIC_TO, 132.04f, 87.57f, 135.36f, 90.77f, 135.36f, 94.71f,
-CUBIC_TO, 135.36f, 97.31f, 137.6f, 99.43f, 140.37f, 99.43f,
-CUBIC_TO, 143.13f, 99.43f, 145.37f, 97.31f, 145.37f, 94.71f,
-CUBIC_TO, 145.37f, 85.55f, 137.55f, 78.11f, 127.93f, 78.11f,
-CUBIC_TO, 121.09f, 78.11f, 114.84f, 81.95f, 112.02f, 87.91f,
-CUBIC_TO, 111.09f, 89.87f, 110.6f, 92.18f, 110.6f, 94.71f,
-CUBIC_TO, 110.6f, 96.61f, 110.77f, 99.6f, 112.22f, 103.49f,
-CUBIC_TO, 112.46f, 104.12f, 112.14f, 104.83f, 111.52f, 105.04f,
-CUBIC_TO, 110.89f, 105.29f, 110.19f, 104.95f, 109.98f, 104.34f,
-CUBIC_TO, 108.8f, 101.16f, 108.22f, 97.99f, 108.22f, 94.71f,
-CUBIC_TO, 108.22f, 91.8f, 108.78f, 89.15f, 109.86f, 86.84f,
-CUBIC_TO, 113.06f, 80.05f, 120.16f, 75.65f, 127.93f, 75.65f,
-CUBIC_TO, 138.88f, 75.65f, 147.78f, 84.19f, 147.78f, 94.69f,
-CUBIC_TO, 147.78f, 98.63f, 144.46f, 101.84f, 140.37f, 101.84f,
-CUBIC_TO, 136.28f, 101.84f, 132.96f, 98.63f, 132.96f, 94.69f,
-CUBIC_TO, 132.96f, 92.09f, 130.72f, 89.97f, 127.95f, 89.97f,
-CUBIC_TO, 125.18f, 89.97f, 122.95f, 92.09f, 122.95f, 94.69f,
-CUBIC_TO, 122.95f, 98.85f, 124.54f, 102.74f, 127.45f, 105.65f,
-CUBIC_TO, 129.73f, 107.94f, 131.92f, 109.2f, 135.31f, 110.15f,
-CUBIC_TO, 135.96f, 110.32f, 136.33f, 111, 136.16f, 111.63f,
-CUBIC_TO, 136.04f, 112.19f, 135.53f, 112.56f, 135.03f, 112.56f,
-LINE_TO, 135.03f, 112.56f,
-CLOSE
diff --git a/chrome/app/vector_icons/webauthn/webauthn_fingerprint_dark.icon b/chrome/app/vector_icons/webauthn/webauthn_fingerprint_dark.icon
deleted file mode 100644
index 303fc91..0000000
--- a/chrome/app/vector_icons/webauthn/webauthn_fingerprint_dark.icon
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2020 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, 448,
-NEW_PATH,
-PATH_COLOR_ARGB, 0x18, 0x00, 0x00, 0x00,
-MOVE_TO, 0, 0,
-R_H_LINE_TO, 448,
-R_V_LINE_TO, 119,
-H_LINE_TO, 0,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 318.49f, 67.44f,
-LINE_TO, 296.74f, 67.44f,
-LINE_TO, 285.51f, 67.44f,
-LINE_TO, 275, 67.44f,
-CUBIC_TO, 275.36f, 61.96f, 279.94f, 57.62f, 285.51f, 57.62f,
-CUBIC_TO, 286.69f, 57.62f, 287.87f, 57.82f, 289.01f, 58.23f,
-LINE_TO, 289.48f, 58.39f,
-LINE_TO, 289.79f, 58.01f,
-CUBIC_TO, 292.88f, 54.19f, 297.46f, 52, 302.36f, 52,
-CUBIC_TO, 311.02f, 52, 318.12f, 58.87f, 318.49f, 67.44f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 372.49f, 33.44f,
-LINE_TO, 350.74f, 33.44f,
-LINE_TO, 339.51f, 33.44f,
-LINE_TO, 329, 33.44f,
-CUBIC_TO, 329.36f, 27.96f, 333.94f, 23.62f, 339.51f, 23.62f,
-CUBIC_TO, 340.69f, 23.62f, 341.87f, 23.82f, 343.01f, 24.23f,
-LINE_TO, 343.48f, 24.39f,
-LINE_TO, 343.79f, 24.01f,
-CUBIC_TO, 346.88f, 20.19f, 351.46f, 18, 356.36f, 18,
-CUBIC_TO, 365.02f, 18, 372.12f, 24.87f, 372.49f, 33.44f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 60.49f, 72.44f,
-LINE_TO, 38.74f, 72.44f,
-LINE_TO, 27.51f, 72.44f,
-LINE_TO, 17, 72.44f,
-CUBIC_TO, 17.36f, 66.96f, 21.94f, 62.62f, 27.51f, 62.62f,
-CUBIC_TO, 28.69f, 62.62f, 29.87f, 62.82f, 31.01f, 63.23f,
-LINE_TO, 31.48f, 63.39f,
-LINE_TO, 31.79f, 63.01f,
-CUBIC_TO, 34.88f, 59.19f, 39.46f, 57, 44.36f, 57,
-CUBIC_TO, 53.02f, 57, 60.12f, 63.87f, 60.49f, 72.44f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x41, 0x44, 0x47,
-CIRCLE, 128, 87, 37.0576923,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-CIRCLE, 128, 87, 37.0576923,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 140.08f, 47.81f,
-CUBIC_TO, 136.26f, 46.63f, 132.21f, 46, 128, 46,
-CUBIC_TO, 122.76f, 46, 117.75f, 46.98f, 113.15f, 48.77f,
-CUBIC_TO, 107.25f, 51.07f, 102.01f, 54.69f, 97.8f, 59.27f,
-MOVE_TO, 87, 87,
-CUBIC_TO, 87, 91.36f, 87.68f, 95.56f, 88.94f, 99.5f,
-MOVE_TO, 101.58f, 118.35f,
-CUBIC_TO, 106.75f, 122.72f, 113.02f, 125.82f, 119.92f, 127.2f,
-CUBIC_TO, 122.53f, 127.73f, 125.23f, 128, 128, 128,
-CUBIC_TO, 139.43f, 128, 149.77f, 123.32f, 157.21f, 115.77f,
-CUBIC_TO, 161.97f, 110.94f, 165.55f, 104.92f, 167.45f, 98.2f,
-MOVE_TO, 169, 87,
-CUBIC_TO, 169, 80.71f, 167.59f, 74.76f, 165.06f, 69.43f,
-CUBIC_TO, 162.59f, 64.23f, 159.05f, 59.63f, 154.73f, 55.91f,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x8A, 0xB4, 0xF8,
-MOVE_TO, 142.03f, 69.83f,
-CUBIC_TO, 141.84f, 69.83f, 141.65f, 69.78f, 141.48f, 69.68f,
-CUBIC_TO, 136.84f, 67.35f, 132.82f, 66.36f, 128.01f, 66.36f,
-CUBIC_TO, 123.23f, 66.36f, 118.68f, 67.47f, 114.55f, 69.68f,
-CUBIC_TO, 113.97f, 69.99f, 113.24f, 69.78f, 112.91f, 69.21f,
-CUBIC_TO, 112.59f, 68.65f, 112.81f, 67.91f, 113.39f, 67.61f,
-CUBIC_TO, 117.88f, 65.23f, 122.82f, 64, 128.01f, 64,
-CUBIC_TO, 133.16f, 64, 137.66f, 65.11f, 142.59f, 67.58f,
-CUBIC_TO, 143.19f, 67.89f, 143.41f, 68.6f, 143.1f, 69.17f,
-CUBIC_TO, 142.88f, 69.59f, 142.47f, 69.83f, 142.03f, 69.83f,
-LINE_TO, 142.03f, 69.83f,
-CLOSE,
-MOVE_TO, 107.49f, 82.77f,
-CUBIC_TO, 107.25f, 82.77f, 107.01f, 82.7f, 106.79f, 82.55f,
-CUBIC_TO, 106.24f, 82.16f, 106.12f, 81.4f, 106.5f, 80.84f,
-CUBIC_TO, 108.89f, 77.4f, 111.93f, 74.71f, 115.55f, 72.82f,
-CUBIC_TO, 123.14f, 68.84f, 132.84f, 68.82f, 140.45f, 72.79f,
-CUBIC_TO, 144.07f, 74.68f, 147.11f, 77.35f, 149.5f, 80.76f,
-CUBIC_TO, 149.88f, 81.3f, 149.76f, 82.09f, 149.21f, 82.48f,
-CUBIC_TO, 148.65f, 82.87f, 147.91f, 82.75f, 147.52f, 82.19f,
-CUBIC_TO, 145.35f, 79.1f, 142.59f, 76.67f, 139.33f, 74.98f,
-CUBIC_TO, 132.41f, 71.37f, 123.55f, 71.37f, 116.64f, 75,
-CUBIC_TO, 113.36f, 76.72f, 110.61f, 79.17f, 108.43f, 82.26f,
-CUBIC_TO, 108.24f, 82.6f, 107.88f, 82.77f, 107.49f, 82.77f,
-LINE_TO, 107.49f, 82.77f,
-CLOSE,
-MOVE_TO, 122.26f, 111.91f,
-CUBIC_TO, 121.95f, 111.91f, 121.64f, 111.79f, 121.42f, 111.55f,
-CUBIC_TO, 119.33f, 109.43f, 118.2f, 108.07f, 116.58f, 105.13f,
-CUBIC_TO, 114.92f, 102.14f, 114.06f, 98.49f, 114.06f, 94.58f,
-CUBIC_TO, 114.06f, 87.36f, 120.17f, 81.48f, 127.68f, 81.48f,
-CUBIC_TO, 135.18f, 81.48f, 141.29f, 87.36f, 141.29f, 94.58f,
-CUBIC_TO, 141.29f, 95.26f, 140.76f, 95.8f, 140.09f, 95.8f,
-CUBIC_TO, 139.42f, 95.8f, 138.89f, 95.26f, 138.89f, 94.58f,
-CUBIC_TO, 138.89f, 88.7f, 133.86f, 83.91f, 127.68f, 83.91f,
-CUBIC_TO, 121.49f, 83.91f, 116.46f, 88.7f, 116.46f, 94.58f,
-CUBIC_TO, 116.46f, 98.08f, 117.23f, 101.31f, 118.7f, 103.94f,
-CUBIC_TO, 120.24f, 106.73f, 121.3f, 107.92f, 123.15f, 109.82f,
-CUBIC_TO, 123.61f, 110.31f, 123.61f, 111.06f, 123.15f, 111.55f,
-CUBIC_TO, 122.89f, 111.79f, 122.58f, 111.91f, 122.26f, 111.91f,
-CLOSE,
-MOVE_TO, 139.38f, 108.02f,
-CUBIC_TO, 136.55f, 108.02f, 134.06f, 107.29f, 132.02f, 105.83f,
-CUBIC_TO, 128.49f, 103.34f, 126.38f, 99.3f, 126.38f, 95.01f,
-CUBIC_TO, 126.38f, 94.32f, 126.9f, 93.78f, 127.56f, 93.78f,
-CUBIC_TO, 128.23f, 93.78f, 128.75f, 94.32f, 128.75f, 95.01f,
-CUBIC_TO, 128.75f, 98.49f, 130.46f, 101.77f, 133.35f, 103.79f,
-CUBIC_TO, 135.04f, 104.97f, 137, 105.54f, 139.38f, 105.54f,
-CUBIC_TO, 139.95f, 105.54f, 140.89f, 105.46f, 141.84f, 105.29f,
-CUBIC_TO, 142.48f, 105.17f, 143.1f, 105.61f, 143.22f, 106.3f,
-CUBIC_TO, 143.34f, 106.97f, 142.91f, 107.61f, 142.25f, 107.73f,
-CUBIC_TO, 140.89f, 108, 139.71f, 108.02f, 139.38f, 108.02f,
-LINE_TO, 139.38f, 108.02f,
-CLOSE,
-MOVE_TO, 135.03f, 112.56f,
-CUBIC_TO, 134.93f, 112.56f, 134.81f, 112.53f, 134.71f, 112.51f,
-CUBIC_TO, 130.89f, 111.44f, 128.38f, 110, 125.76f, 107.4f,
-CUBIC_TO, 122.39f, 104.02f, 120.54f, 99.53f, 120.54f, 94.71f,
-CUBIC_TO, 120.54f, 90.77f, 123.86f, 87.57f, 127.95f, 87.57f,
-CUBIC_TO, 132.04f, 87.57f, 135.36f, 90.77f, 135.36f, 94.71f,
-CUBIC_TO, 135.36f, 97.31f, 137.6f, 99.43f, 140.37f, 99.43f,
-CUBIC_TO, 143.13f, 99.43f, 145.37f, 97.31f, 145.37f, 94.71f,
-CUBIC_TO, 145.37f, 85.55f, 137.55f, 78.11f, 127.93f, 78.11f,
-CUBIC_TO, 121.09f, 78.11f, 114.84f, 81.95f, 112.02f, 87.91f,
-CUBIC_TO, 111.09f, 89.87f, 110.6f, 92.18f, 110.6f, 94.71f,
-CUBIC_TO, 110.6f, 96.61f, 110.77f, 99.6f, 112.22f, 103.49f,
-CUBIC_TO, 112.46f, 104.12f, 112.14f, 104.83f, 111.52f, 105.04f,
-CUBIC_TO, 110.89f, 105.29f, 110.19f, 104.95f, 109.98f, 104.34f,
-CUBIC_TO, 108.8f, 101.16f, 108.22f, 97.99f, 108.22f, 94.71f,
-CUBIC_TO, 108.22f, 91.8f, 108.78f, 89.15f, 109.86f, 86.84f,
-CUBIC_TO, 113.06f, 80.05f, 120.16f, 75.65f, 127.93f, 75.65f,
-CUBIC_TO, 138.88f, 75.65f, 147.78f, 84.19f, 147.78f, 94.69f,
-CUBIC_TO, 147.78f, 98.63f, 144.46f, 101.84f, 140.37f, 101.84f,
-CUBIC_TO, 136.28f, 101.84f, 132.96f, 98.63f, 132.96f, 94.69f,
-CUBIC_TO, 132.96f, 92.09f, 130.72f, 89.97f, 127.95f, 89.97f,
-CUBIC_TO, 125.18f, 89.97f, 122.95f, 92.09f, 122.95f, 94.69f,
-CUBIC_TO, 122.95f, 98.85f, 124.54f, 102.74f, 127.45f, 105.65f,
-CUBIC_TO, 129.73f, 107.94f, 131.92f, 109.2f, 135.31f, 110.15f,
-CUBIC_TO, 135.96f, 110.32f, 136.33f, 111, 136.16f, 111.63f,
-CUBIC_TO, 136.04f, 112.19f, 135.53f, 112.56f, 135.03f, 112.56f,
-LINE_TO, 135.03f, 112.56f,
-CLOSE
diff --git a/chrome/app/vector_icons/webauthn/webauthn_permission.icon b/chrome/app/vector_icons/webauthn/webauthn_permission.icon
deleted file mode 100644
index 835e965..0000000
--- a/chrome/app/vector_icons/webauthn/webauthn_permission.icon
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2019 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, 448,
-NEW_PATH,
-PATH_COLOR_ARGB, 0x0A, 0x00, 0x00, 0x00,
-MOVE_TO, 0, 0,
-R_H_LINE_TO, 448,
-R_V_LINE_TO, 119,
-H_LINE_TO, 0,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xE8, 0xE9, 0xEB,
-MOVE_TO, 461.49f, 67.44f,
-H_LINE_TO, 418,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 445.36f, 52,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-R_MOVE_TO, -89, -34,
-H_LINE_TO, 329,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 356.36f, 18,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-R_MOVE_TO, -312, 39,
-H_LINE_TO, 17,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 44.36f, 57,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
-MOVE_TO, 169.11f, 40.08f,
-V_LINE_TO, 33.5f,
-R_ARC_TO, 4, 4, 0, 0, 1, 4, -4,
-R_H_LINE_TO, 30.94f,
-R_ARC_TO, 4, 4, 0, 0, 1, 4, 4,
-R_V_LINE_TO, 6.58f,
-H_LINE_TO, 288,
-R_ARC_TO, 2, 2, 0, 0, 1, 2, 2,
-V_LINE_TO, 131.5f,
-R_ARC_TO, 2, 2, 0, 0, 1, -2, 2,
-H_LINE_TO, 163,
-R_ARC_TO, 2, 2, 0, 0, 1, -2, -2,
-V_LINE_TO, 42.08f,
-R_ARC_TO, 2, 2, 0, 0, 1, 2, -2,
-R_H_LINE_TO, 6.11f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xE8, 0xE9, 0xEB,
-MOVE_TO, 169.11f, 40.08f,
-V_LINE_TO, 33.5f,
-R_ARC_TO, 4, 4, 0, 0, 1, 4, -4,
-R_H_LINE_TO, 30.94f,
-R_ARC_TO, 4, 4, 0, 0, 1, 4, 4,
-R_V_LINE_TO, 6.58f,
-H_LINE_TO, 288,
-R_ARC_TO, 2, 2, 0, 0, 1, 2, 2,
-V_LINE_TO, 131.5f,
-R_ARC_TO, 2, 2, 0, 0, 1, -2, 2,
-H_LINE_TO, 163,
-R_ARC_TO, 2, 2, 0, 0, 1, -2, -2,
-V_LINE_TO, 42.08f,
-R_ARC_TO, 2, 2, 0, 0, 1, 2, -2,
-R_H_LINE_TO, 6.11f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xF8, 0xF9, 0xFA,
-ROUND_RECT, 170, 48, 111, 7, 3.5,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xBD, 0xC1, 0xC6,
-CIRCLE, 147, 92.5, 31,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xff, 0xff, 0xff,
-MOVE_TO, 148.48f, 98.09f,
-R_H_LINE_TO, -2.91f,
-R_CUBIC_TO, -0.01f, -1.57f, 0.25f, -3.23f, 1.32f, -4.45f,
-R_CUBIC_TO, 1.1f, -1.47f, 2.58f, -2.62f, 3.6f, -4.15f,
-R_CUBIC_TO, 0.69f, -1.43f, 0.67f, -3.35f, -0.4f, -4.59f,
-R_CUBIC_TO, -1.19f, -1.23f, -3.25f, -1.17f, -4.66f, -0.36f,
-R_CUBIC_TO, -0.98f, 0.44f, -1.34f, 1.63f, -1.42f, 2.54f,
-R_H_LINE_TO, -2.84f,
-R_CUBIC_TO, -0.04f, -1.82f, 0.89f, -3.64f, 2.48f, -4.57f,
-R_CUBIC_TO, 2.03f, -1.26f, 4.67f, -1.37f, 6.89f, -0.56f,
-R_CUBIC_TO, 2, 0.75f, 3.27f, 2.83f, 3.31f, 4.93f,
-R_CUBIC_TO, 0.16f, 1.78f, -0.51f, 3.56f, -1.69f, 4.88f,
-R_CUBIC_TO, -0.78f, 1.03f, -1.75f, 1.91f, -2.64f, 2.84f,
-R_CUBIC_TO, -0.78f, 0.98f, -1.04f, 2.27f, -1.03f, 3.5f,
-CLOSE,
-R_MOVE_TO, -3.03f, 4.95f,
-R_CUBIC_TO, -0.09f, -1.19f, 1.21f, -1.97f, 2.28f, -1.6f,
-R_CUBIC_TO, 1.43f, 0.32f, 1.54f, 2.64f, 0.17f, 3.12f,
-R_CUBIC_TO, -1.01f, 0.43f, -2.4f, -0.16f, -2.44f, -1.35f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xAC, 0xB0, 0xB5,
-MOVE_TO, 161, 64.83f,
-CUBIC_TO, 171.09f, 69.94f, 178, 80.41f, 178, 92.49f,
-R_CUBIC_TO, 0, 12.04f, -6.87f, 22.48f, -16.9f, 27.62f,
-R_ARC_TO, 2, 2, 0, 0, 1, -0.1f, -0.62f,
-V_LINE_TO, 64.83f,
-CLOSE
diff --git a/chrome/app/vector_icons/webauthn/webauthn_permission_dark.icon b/chrome/app/vector_icons/webauthn/webauthn_permission_dark.icon
deleted file mode 100644
index c3b2385..0000000
--- a/chrome/app/vector_icons/webauthn/webauthn_permission_dark.icon
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2019 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, 448,
-NEW_PATH,
-PATH_COLOR_ARGB, 0x18, 0x00, 0x00, 0x00,
-MOVE_TO, 0, 0,
-R_H_LINE_TO, 448,
-R_V_LINE_TO, 119,
-H_LINE_TO, 0,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 461.49f, 67.44f,
-H_LINE_TO, 418,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 445.36f, 52,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-R_MOVE_TO, -89, -34,
-H_LINE_TO, 329,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 356.36f, 18,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-R_MOVE_TO, -312, 39,
-H_LINE_TO, 17,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 44.36f, 57,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x41, 0x44, 0x47,
-MOVE_TO, 169.11f, 40.08f,
-V_LINE_TO, 33.5f,
-R_ARC_TO, 4, 4, 0, 0, 1, 4, -4,
-R_H_LINE_TO, 30.94f,
-R_ARC_TO, 4, 4, 0, 0, 1, 4, 4,
-R_V_LINE_TO, 6.58f,
-H_LINE_TO, 288,
-R_ARC_TO, 2, 2, 0, 0, 1, 2, 2,
-V_LINE_TO, 131.5f,
-R_ARC_TO, 2, 2, 0, 0, 1, -2, 2,
-H_LINE_TO, 163,
-R_ARC_TO, 2, 2, 0, 0, 1, -2, -2,
-V_LINE_TO, 42.08f,
-R_ARC_TO, 2, 2, 0, 0, 1, 2, -2,
-R_H_LINE_TO, 6.11f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 169.11f, 40.08f,
-V_LINE_TO, 33.5f,
-R_ARC_TO, 4, 4, 0, 0, 1, 4, -4,
-R_H_LINE_TO, 30.94f,
-R_ARC_TO, 4, 4, 0, 0, 1, 4, 4,
-R_V_LINE_TO, 6.58f,
-H_LINE_TO, 288,
-R_ARC_TO, 2, 2, 0, 0, 1, 2, 2,
-V_LINE_TO, 131.5f,
-R_ARC_TO, 2, 2, 0, 0, 1, -2, 2,
-H_LINE_TO, 163,
-R_ARC_TO, 2, 2, 0, 0, 1, -2, -2,
-V_LINE_TO, 42.08f,
-R_ARC_TO, 2, 2, 0, 0, 1, 2, -2,
-R_H_LINE_TO, 6.11f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-ROUND_RECT, 170, 48, 111, 7, 3.5,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-CIRCLE, 147, 92.5, 31,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xff, 0xff, 0xff,
-MOVE_TO, 148.48f, 98.09f,
-R_H_LINE_TO, -2.91f,
-R_CUBIC_TO, -0.01f, -1.57f, 0.25f, -3.23f, 1.32f, -4.45f,
-R_CUBIC_TO, 1.1f, -1.47f, 2.58f, -2.62f, 3.6f, -4.15f,
-R_CUBIC_TO, 0.69f, -1.43f, 0.67f, -3.35f, -0.4f, -4.59f,
-R_CUBIC_TO, -1.19f, -1.23f, -3.25f, -1.17f, -4.66f, -0.36f,
-R_CUBIC_TO, -0.98f, 0.44f, -1.34f, 1.63f, -1.42f, 2.54f,
-R_H_LINE_TO, -2.84f,
-R_CUBIC_TO, -0.04f, -1.82f, 0.89f, -3.64f, 2.48f, -4.57f,
-R_CUBIC_TO, 2.03f, -1.26f, 4.67f, -1.37f, 6.89f, -0.56f,
-R_CUBIC_TO, 2, 0.75f, 3.27f, 2.83f, 3.31f, 4.93f,
-R_CUBIC_TO, 0.16f, 1.78f, -0.51f, 3.56f, -1.69f, 4.88f,
-R_CUBIC_TO, -0.78f, 1.03f, -1.75f, 1.91f, -2.64f, 2.84f,
-R_CUBIC_TO, -0.78f, 0.98f, -1.04f, 2.27f, -1.03f, 3.5f,
-CLOSE,
-R_MOVE_TO, -3.03f, 4.95f,
-R_CUBIC_TO, -0.09f, -1.19f, 1.21f, -1.97f, 2.28f, -1.6f,
-R_CUBIC_TO, 1.43f, 0.32f, 1.54f, 2.64f, 0.17f, 3.12f,
-R_CUBIC_TO, -1.01f, 0.43f, -2.4f, -0.16f, -2.44f, -1.35f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x53, 0x57, 0x5C,
-MOVE_TO, 161, 64.83f,
-CUBIC_TO, 171.09f, 69.94f, 178, 80.41f, 178, 92.49f,
-R_CUBIC_TO, 0, 12.04f, -6.87f, 22.48f, -16.9f, 27.62f,
-R_ARC_TO, 2, 2, 0, 0, 1, -0.1f, -0.62f,
-V_LINE_TO, 64.83f,
-CLOSE
diff --git a/chrome/app/vector_icons/webauthn/webauthn_phone.icon b/chrome/app/vector_icons/webauthn/webauthn_phone.icon
deleted file mode 100644
index 7e3f7bc..0000000
--- a/chrome/app/vector_icons/webauthn/webauthn_phone.icon
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright 2019 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, 448,
-NEW_PATH,
-PATH_COLOR_ARGB, 0x0A, 0x00, 0x00, 0x00,
-MOVE_TO, 0, 0,
-R_H_LINE_TO, 448,
-R_V_LINE_TO, 119,
-H_LINE_TO, 0,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xE8, 0xE9, 0xEB,
-MOVE_TO, 318.49f, 67.44f,
-H_LINE_TO, 275,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 302.36f, 52,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-MOVE_TO, 372.49f, 33.44f,
-H_LINE_TO, 329,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 356.36f, 18,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-MOVE_TO, 60.49f, 72.44f,
-H_LINE_TO, 17,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 44.36f, 57,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
-MOVE_TO, 103.99f, 34,
-R_CUBIC_TO, -3.3f, 0, -5.99f, 2.62f, -5.99f, 5.83f,
-R_V_LINE_TO, 86.34f,
-R_CUBIC_TO, 0, 3.22f, 2.69f, 5.83f, 5.99f, 5.83f,
-R_H_LINE_TO, 37.03f,
-R_CUBIC_TO, 3.3f, 0, 5.98f, -2.62f, 5.98f, -5.83f,
-V_LINE_TO, 39.83f,
-R_CUBIC_TO, 0, -3.22f, -2.68f, -5.83f, -5.98f, -5.83f,
-R_H_LINE_TO, -37.03f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xE8, 0xE9, 0xEB,
-MOVE_TO, 103.99f, 34,
-R_CUBIC_TO, -3.3f, 0, -5.99f, 2.62f, -5.99f, 5.83f,
-R_V_LINE_TO, 86.34f,
-R_CUBIC_TO, 0, 3.22f, 2.69f, 5.83f, 5.99f, 5.83f,
-R_H_LINE_TO, 37.03f,
-R_CUBIC_TO, 3.3f, 0, 5.98f, -2.62f, 5.98f, -5.83f,
-V_LINE_TO, 39.83f,
-R_CUBIC_TO, 0, -3.22f, -2.68f, -5.83f, -5.98f, -5.83f,
-R_H_LINE_TO, -37.03f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xBD, 0xC0, 0xC5,
-MOVE_TO, 137, 30,
-R_H_LINE_TO, 3.71f,
-R_CUBIC_TO, 5.52f, 0, 10, 4.48f, 10, 10,
-R_V_LINE_TO, 72.19f,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xF7, 0xBB, 0x2A,
-MOVE_TO, 137, 61.5f,
-R_CUBIC_TO, 0, -11.87f, 9.63f, -21.5f, 21.5f, -21.5f,
-CUBIC_TO_SHORTHAND, 180, 49.63f, 180, 61.5f,
-CUBIC_TO_SHORTHAND, 170.37f, 83, 158.5f, 83,
-CUBIC_TO_SHORTHAND, 137, 73.37f, 137, 61.5f,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xE8, 0xAF, 0x25,
-MOVE_TO, 147, 43.33f,
-R_V_LINE_TO, 36.34f,
-R_CUBIC_TO, -6.01f, -3.81f, -10, -10.53f, -10, -18.17f,
-R_CUBIC_TO, 0, -7.64f, 3.99f, -14.36f, 10, -18.17f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x42, 0x85, 0xF4,
-MOVE_TO, 150.75f, 120,
-R_V_LINE_TO, 6.01f,
-R_CUBIC_TO, 0, 5.52f, -4.48f, 10, -10, 10,
-H_LINE_TO, 133,
-MOVE_TO, 150.75f, 120,
-R_V_LINE_TO, 6.01f,
-R_CUBIC_TO, 0, 5.52f, -4.48f, 10, -10, 10,
-H_LINE_TO, 133,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xBD, 0xC0, 0xC5,
-MOVE_TO, 126.3f, 30,
-H_LINE_TO, 104,
-R_CUBIC_TO, -5.52f, 0, -10, 4.48f, -10, 10,
-R_V_LINE_TO, 86,
-R_CUBIC_TO, 0, 5.52f, 4.48f, 10, 10, 10,
-R_H_LINE_TO, 19.52f,
-R_MOVE_TO, 2.77f, -106,
-H_LINE_TO, 104,
-R_CUBIC_TO, -5.52f, 0, -10, 4.48f, -10, 10,
-R_V_LINE_TO, 86,
-R_CUBIC_TO, 0, 5.52f, 4.48f, 10, 10, 10,
-R_H_LINE_TO, 19.52f,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
-MOVE_TO, 155.64f, 60.06f,
-R_V_LINE_TO, -3.21f,
-R_ARC_TO, 2.14f, 2.14f, 0, 0, 1, 4.29f, 0,
-R_V_LINE_TO, 3.21f,
-R_ARC_TO, 3.85f, 3.85f, 0, 0, 0, 1.71f, -3.21f,
-ARC_TO, 3.85f, 3.85f, 0, 0, 0, 157.79f, 53,
-R_ARC_TO, 3.85f, 3.85f, 0, 0, 0, -3.86f, 3.86f,
-R_CUBIC_TO, 0, 1.34f, 0.68f, 2.51f, 1.71f, 3.21f,
-CLOSE,
-R_MOVE_TO, 8.43f, 3.97f,
-R_LINE_TO, -3.89f, -1.94f,
-R_CUBIC_TO, -0.15f, -0.06f, -0.3f, -0.09f, -0.46f, -0.09f,
-R_H_LINE_TO, -0.65f,
-R_V_LINE_TO, -5.14f,
-R_CUBIC_TO, 0, -0.71f, -0.57f, -1.29f, -1.28f, -1.29f,
-R_CUBIC_TO, -0.71f, 0, -1.29f, 0.57f, -1.29f, 1.29f,
-R_V_LINE_TO, 9.21f,
-R_LINE_TO, -2.94f, -0.62f,
-R_CUBIC_TO, -0.07f, -0.01f, -0.13f, -0.03f, -0.21f, -0.03f,
-R_ARC_TO, 0.96f, 0.96f, 0, 0, 0, -0.68f, 0.28f,
-R_LINE_TO, -0.68f, 0.69f,
-R_LINE_TO, 4.23f, 4.23f,
-R_CUBIC_TO, 0.23f, 0.23f, 0.56f, 0.38f, 0.91f, 0.38f,
-R_H_LINE_TO, 5.82f,
-R_CUBIC_TO, 0.64f, 0, 1.14f, -0.47f, 1.23f, -1.1f,
-R_LINE_TO, 0.64f, -4.52f,
-R_CUBIC_TO, 0.01f, -0.06f, 0.02f, -0.12f, 0.02f, -0.17f,
-R_CUBIC_TO, 0, -0.53f, -0.33f, -0.99f, -0.78f, -1.18f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xF7, 0xBB, 0x2A,
-MOVE_TO, 155.64f, 60.06f,
-R_V_LINE_TO, -3.21f,
-R_ARC_TO, 2.14f, 2.14f, 0, 0, 1, 4.29f, 0,
-R_V_LINE_TO, 3.21f,
-R_ARC_TO, 3.85f, 3.85f, 0, 0, 0, 1.71f, -3.21f,
-ARC_TO, 3.85f, 3.85f, 0, 0, 0, 157.79f, 53,
-R_ARC_TO, 3.85f, 3.85f, 0, 0, 0, -3.86f, 3.86f,
-R_CUBIC_TO, 0, 1.34f, 0.68f, 2.51f, 1.71f, 3.21f,
-CLOSE,
-R_MOVE_TO, 8.43f, 3.97f,
-R_LINE_TO, -3.89f, -1.94f,
-R_CUBIC_TO, -0.15f, -0.06f, -0.3f, -0.09f, -0.46f, -0.09f,
-R_H_LINE_TO, -0.65f,
-R_V_LINE_TO, -5.14f,
-R_CUBIC_TO, 0, -0.71f, -0.57f, -1.29f, -1.28f, -1.29f,
-R_CUBIC_TO, -0.71f, 0, -1.29f, 0.57f, -1.29f, 1.29f,
-R_V_LINE_TO, 9.21f,
-R_LINE_TO, -2.94f, -0.62f,
-R_CUBIC_TO, -0.07f, -0.01f, -0.13f, -0.03f, -0.21f, -0.03f,
-R_ARC_TO, 0.96f, 0.96f, 0, 0, 0, -0.68f, 0.28f,
-R_LINE_TO, -0.68f, 0.69f,
-R_LINE_TO, 4.23f, 4.23f,
-R_CUBIC_TO, 0.23f, 0.23f, 0.56f, 0.38f, 0.91f, 0.38f,
-R_H_LINE_TO, 5.82f,
-R_CUBIC_TO, 0.64f, 0, 1.14f, -0.47f, 1.23f, -1.1f,
-R_LINE_TO, 0.64f, -4.52f,
-R_CUBIC_TO, 0.01f, -0.06f, 0.02f, -0.12f, 0.02f, -0.17f,
-R_CUBIC_TO, 0, -0.53f, -0.33f, -0.99f, -0.78f, -1.18f,
-CLOSE
diff --git a/chrome/app/vector_icons/webauthn/webauthn_phone_dark.icon b/chrome/app/vector_icons/webauthn/webauthn_phone_dark.icon
deleted file mode 100644
index cc2a788..0000000
--- a/chrome/app/vector_icons/webauthn/webauthn_phone_dark.icon
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright 2019 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, 448,
-NEW_PATH,
-PATH_COLOR_ARGB, 0x18, 0x00, 0x00, 0x00,
-MOVE_TO, 0, 0,
-R_H_LINE_TO, 448,
-R_V_LINE_TO, 119,
-H_LINE_TO, 0,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 318.49f, 67.44f,
-H_LINE_TO, 275,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 302.36f, 52,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-MOVE_TO, 372.49f, 33.44f,
-H_LINE_TO, 329,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 356.36f, 18,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-MOVE_TO, 60.49f, 72.44f,
-H_LINE_TO, 17,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 44.36f, 57,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x41, 0x44, 0x47,
-MOVE_TO, 103.99f, 34,
-R_CUBIC_TO, -3.3f, 0, -5.99f, 2.62f, -5.99f, 5.83f,
-R_V_LINE_TO, 86.34f,
-R_CUBIC_TO, 0, 3.22f, 2.69f, 5.83f, 5.99f, 5.83f,
-R_H_LINE_TO, 37.03f,
-R_CUBIC_TO, 3.3f, 0, 5.98f, -2.62f, 5.98f, -5.83f,
-V_LINE_TO, 39.83f,
-R_CUBIC_TO, 0, -3.22f, -2.68f, -5.83f, -5.98f, -5.83f,
-R_H_LINE_TO, -37.03f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 103.99f, 34,
-R_CUBIC_TO, -3.3f, 0, -5.99f, 2.62f, -5.99f, 5.83f,
-R_V_LINE_TO, 86.34f,
-R_CUBIC_TO, 0, 3.22f, 2.69f, 5.83f, 5.99f, 5.83f,
-R_H_LINE_TO, 37.03f,
-R_CUBIC_TO, 3.3f, 0, 5.98f, -2.62f, 5.98f, -5.83f,
-V_LINE_TO, 39.83f,
-R_CUBIC_TO, 0, -3.22f, -2.68f, -5.83f, -5.98f, -5.83f,
-R_H_LINE_TO, -37.03f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 137, 30,
-R_H_LINE_TO, 3.71f,
-R_CUBIC_TO, 5.52f, 0, 10, 4.48f, 10, 10,
-R_V_LINE_TO, 72.19f,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xF7, 0xBB, 0x2A,
-MOVE_TO, 137, 61.5f,
-R_CUBIC_TO, 0, -11.87f, 9.63f, -21.5f, 21.5f, -21.5f,
-CUBIC_TO_SHORTHAND, 180, 49.63f, 180, 61.5f,
-CUBIC_TO_SHORTHAND, 170.37f, 83, 158.5f, 83,
-CUBIC_TO_SHORTHAND, 137, 73.37f, 137, 61.5f,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xE8, 0xAF, 0x25,
-MOVE_TO, 147, 43.33f,
-R_V_LINE_TO, 36.34f,
-R_CUBIC_TO, -6.01f, -3.81f, -10, -10.53f, -10, -18.17f,
-R_CUBIC_TO, 0, -7.64f, 3.99f, -14.36f, 10, -18.17f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x8A, 0xB4, 0xF8,
-MOVE_TO, 150.75f, 120,
-R_V_LINE_TO, 6.01f,
-R_CUBIC_TO, 0, 5.52f, -4.48f, 10, -10, 10,
-H_LINE_TO, 133,
-MOVE_TO, 150.75f, 120,
-R_V_LINE_TO, 6.01f,
-R_CUBIC_TO, 0, 5.52f, -4.48f, 10, -10, 10,
-H_LINE_TO, 133,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 126.3f, 30,
-H_LINE_TO, 104,
-R_CUBIC_TO, -5.52f, 0, -10, 4.48f, -10, 10,
-R_V_LINE_TO, 86,
-R_CUBIC_TO, 0, 5.52f, 4.48f, 10, 10, 10,
-R_H_LINE_TO, 19.52f,
-R_MOVE_TO, 2.77f, -106,
-H_LINE_TO, 104,
-R_CUBIC_TO, -5.52f, 0, -10, 4.48f, -10, 10,
-R_V_LINE_TO, 86,
-R_CUBIC_TO, 0, 5.52f, 4.48f, 10, 10, 10,
-R_H_LINE_TO, 19.52f,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
-MOVE_TO, 155.64f, 60.06f,
-R_V_LINE_TO, -3.21f,
-R_ARC_TO, 2.14f, 2.14f, 0, 0, 1, 4.29f, 0,
-R_V_LINE_TO, 3.21f,
-R_ARC_TO, 3.85f, 3.85f, 0, 0, 0, 1.71f, -3.21f,
-ARC_TO, 3.85f, 3.85f, 0, 0, 0, 157.79f, 53,
-R_ARC_TO, 3.85f, 3.85f, 0, 0, 0, -3.86f, 3.86f,
-R_CUBIC_TO, 0, 1.34f, 0.68f, 2.51f, 1.71f, 3.21f,
-CLOSE,
-R_MOVE_TO, 8.43f, 3.97f,
-R_LINE_TO, -3.89f, -1.94f,
-R_CUBIC_TO, -0.15f, -0.06f, -0.3f, -0.09f, -0.46f, -0.09f,
-R_H_LINE_TO, -0.65f,
-R_V_LINE_TO, -5.14f,
-R_CUBIC_TO, 0, -0.71f, -0.57f, -1.29f, -1.28f, -1.29f,
-R_CUBIC_TO, -0.71f, 0, -1.29f, 0.57f, -1.29f, 1.29f,
-R_V_LINE_TO, 9.21f,
-R_LINE_TO, -2.94f, -0.62f,
-R_CUBIC_TO, -0.07f, -0.01f, -0.13f, -0.03f, -0.21f, -0.03f,
-R_ARC_TO, 0.96f, 0.96f, 0, 0, 0, -0.68f, 0.28f,
-R_LINE_TO, -0.68f, 0.69f,
-R_LINE_TO, 4.23f, 4.23f,
-R_CUBIC_TO, 0.23f, 0.23f, 0.56f, 0.38f, 0.91f, 0.38f,
-R_H_LINE_TO, 5.82f,
-R_CUBIC_TO, 0.64f, 0, 1.14f, -0.47f, 1.23f, -1.1f,
-R_LINE_TO, 0.64f, -4.52f,
-R_CUBIC_TO, 0.01f, -0.06f, 0.02f, -0.12f, 0.02f, -0.17f,
-R_CUBIC_TO, 0, -0.53f, -0.33f, -0.99f, -0.78f, -1.18f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xF7, 0xBB, 0x2A,
-MOVE_TO, 155.64f, 60.06f,
-R_V_LINE_TO, -3.21f,
-R_ARC_TO, 2.14f, 2.14f, 0, 0, 1, 4.29f, 0,
-R_V_LINE_TO, 3.21f,
-R_ARC_TO, 3.85f, 3.85f, 0, 0, 0, 1.71f, -3.21f,
-ARC_TO, 3.85f, 3.85f, 0, 0, 0, 157.79f, 53,
-R_ARC_TO, 3.85f, 3.85f, 0, 0, 0, -3.86f, 3.86f,
-R_CUBIC_TO, 0, 1.34f, 0.68f, 2.51f, 1.71f, 3.21f,
-CLOSE,
-R_MOVE_TO, 8.43f, 3.97f,
-R_LINE_TO, -3.89f, -1.94f,
-R_CUBIC_TO, -0.15f, -0.06f, -0.3f, -0.09f, -0.46f, -0.09f,
-R_H_LINE_TO, -0.65f,
-R_V_LINE_TO, -5.14f,
-R_CUBIC_TO, 0, -0.71f, -0.57f, -1.29f, -1.28f, -1.29f,
-R_CUBIC_TO, -0.71f, 0, -1.29f, 0.57f, -1.29f, 1.29f,
-R_V_LINE_TO, 9.21f,
-R_LINE_TO, -2.94f, -0.62f,
-R_CUBIC_TO, -0.07f, -0.01f, -0.13f, -0.03f, -0.21f, -0.03f,
-R_ARC_TO, 0.96f, 0.96f, 0, 0, 0, -0.68f, 0.28f,
-R_LINE_TO, -0.68f, 0.69f,
-R_LINE_TO, 4.23f, 4.23f,
-R_CUBIC_TO, 0.23f, 0.23f, 0.56f, 0.38f, 0.91f, 0.38f,
-R_H_LINE_TO, 5.82f,
-R_CUBIC_TO, 0.64f, 0, 1.14f, -0.47f, 1.23f, -1.1f,
-R_LINE_TO, 0.64f, -4.52f,
-R_CUBIC_TO, 0.01f, -0.06f, 0.02f, -0.12f, 0.02f, -0.17f,
-R_CUBIC_TO, 0, -0.53f, -0.33f, -0.99f, -0.78f, -1.18f,
-CLOSE
diff --git a/chrome/app/vector_icons/webauthn/webauthn_usb.icon b/chrome/app/vector_icons/webauthn/webauthn_usb.icon
deleted file mode 100644
index 2fcd829..0000000
--- a/chrome/app/vector_icons/webauthn/webauthn_usb.icon
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright 2019 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, 448,
-NEW_PATH,
-PATH_COLOR_ARGB, 0x0A, 0x00, 0x00, 0x00,
-MOVE_TO, 0, 0,
-R_H_LINE_TO, 448,
-R_V_LINE_TO, 119,
-H_LINE_TO, 0,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xE8, 0xE9, 0xEB,
-MOVE_TO, 318.49f, 67.44f,
-H_LINE_TO, 275,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 302.36f, 52,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-MOVE_TO, 372.49f, 33.44f,
-H_LINE_TO, 329,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 356.36f, 18,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-MOVE_TO, 60.49f, 72.44f,
-H_LINE_TO, 17,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 44.36f, 57,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
-MOVE_TO, 137.35f, 54.4f,
-H_LINE_TO, 146,
-R_ARC_TO, 1, 1, 0, 0, 1, 1, 1,
-V_LINE_TO, 128,
-R_ARC_TO, 8, 8, 0, 0, 1, -8, 8,
-H_LINE_TO, 109,
-R_ARC_TO, 8, 8, 0, 0, 1, -8, -8,
-V_LINE_TO, 55.4f,
-R_ARC_TO, 1, 1, 0, 0, 1, 1, -1,
-R_H_LINE_TO, 8.65f,
-V_LINE_TO, 34,
-R_H_LINE_TO, 26.71f,
-R_V_LINE_TO, 20.4f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xE8, 0xE9, 0xEB,
-MOVE_TO, 137.35f, 54.4f,
-H_LINE_TO, 146,
-R_ARC_TO, 1, 1, 0, 0, 1, 1, 1,
-V_LINE_TO, 128,
-R_ARC_TO, 8, 8, 0, 0, 1, -8, 8,
-H_LINE_TO, 109,
-R_ARC_TO, 8, 8, 0, 0, 1, -8, -8,
-V_LINE_TO, 55.4f,
-R_ARC_TO, 1, 1, 0, 0, 1, 1, -1,
-R_H_LINE_TO, 8.65f,
-V_LINE_TO, 34,
-R_H_LINE_TO, 26.71f,
-R_V_LINE_TO, 20.4f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xE5, 0x44, 0x40,
-MOVE_TO, 96, 54.71f,
-CUBIC_TO, 96, 51.56f, 98.53f, 49, 101.65f, 49,
-R_H_LINE_TO, 3.83f,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xBD, 0xC0, 0xC5,
-MOVE_TO, 105, 30,
-R_H_LINE_TO, 35.96f,
-R_V_LINE_TO, 20.25f,
-R_H_LINE_TO, 3.83f,
-R_CUBIC_TO, 3.12f, 0, 5.66f, 2.56f, 5.66f, 5.71f,
-V_LINE_TO, 129.59f,
-MOVE_TO, 139.62f, 140.43f,
-R_H_LINE_TO, -32.31f,
-CUBIC_TO, 101.06f, 140.43f, 96, 135.31f, 96, 129,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xF0, 0xF0, 0xF0,
-MOVE_TO, 115, 38,
-R_H_LINE_TO, 11,
-R_V_LINE_TO, 16,
-H_LINE_TO, 115,
-CLOSE,
-MOVE_TO, 129, 38,
-R_H_LINE_TO, 5,
-R_V_LINE_TO, 16,
-R_H_LINE_TO, -5,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xBD, 0xC0, 0xC5,
-CIRCLE, 125, 96, 12,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xBD, 0xC0, 0xC5,
-MOVE_TO, 95.5f, 63.5f,
-R_V_LINE_TO, 38.01f,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x42, 0x85, 0xF4,
-MOVE_TO, 182, 76.5f,
-CUBIC_TO, 182, 88.37f, 172.38f, 98, 160.5f, 98,
-CUBIC_TO_SHORTHAND, 139, 88.37f, 139, 76.5f,
-CUBIC_TO_SHORTHAND, 148.63f, 55, 160.5f, 55,
-CUBIC_TO_SHORTHAND, 182, 64.63f, 182, 76.5f,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
-MOVE_TO, 162.9f, 73.65f,
-R_V_LINE_TO, 3.1f,
-R_H_LINE_TO, 0.78f,
-R_V_LINE_TO, 1.55f,
-R_H_LINE_TO, -2.32f,
-R_V_LINE_TO, -6.2f,
-R_H_LINE_TO, 1.55f,
-LINE_TO, 160.58f, 69,
-R_LINE_TO, -2.32f, 3.1f,
-R_H_LINE_TO, 1.55f,
-R_V_LINE_TO, 6.2f,
-R_H_LINE_TO, -2.32f,
-R_V_LINE_TO, -1.6f,
-R_CUBIC_TO, 0.54f, -0.29f, 0.93f, -0.84f, 0.93f, -1.49f,
-R_ARC_TO, 1.71f, 1.71f, 0, 0, 0, -1.7f, -1.7f,
-ARC_TO, 1.71f, 1.71f, 0, 0, 0, 155, 75.2f,
-R_CUBIC_TO, 0, 0.66f, 0.39f, 1.21f, 0.93f, 1.5f,
-R_V_LINE_TO, 1.6f,
-R_CUBIC_TO, 0, 0.86f, 0.69f, 1.55f, 1.55f, 1.55f,
-R_H_LINE_TO, 2.32f,
-R_V_LINE_TO, 2.36f,
-R_CUBIC_TO, -0.55f, 0.29f, -0.93f, 0.85f, -0.93f, 1.51f,
-R_ARC_TO, 1.7f, 1.7f, 0, 0, 0, 3.41f, 0,
-R_CUBIC_TO, 0, -0.66f, -0.38f, -1.22f, -0.93f, -1.51f,
-R_V_LINE_TO, -2.36f,
-R_H_LINE_TO, 2.32f,
-R_CUBIC_TO, 0.86f, 0, 1.55f, -0.69f, 1.55f, -1.55f,
-R_V_LINE_TO, -1.55f,
-H_LINE_TO, 166,
-R_V_LINE_TO, -3.1f,
-R_H_LINE_TO, -3.1f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x42, 0x85, 0xF4,
-MOVE_TO, 162.9f, 73.65f,
-R_V_LINE_TO, 3.1f,
-R_H_LINE_TO, 0.78f,
-R_V_LINE_TO, 1.55f,
-R_H_LINE_TO, -2.32f,
-R_V_LINE_TO, -6.2f,
-R_H_LINE_TO, 1.55f,
-LINE_TO, 160.58f, 69,
-R_LINE_TO, -2.32f, 3.1f,
-R_H_LINE_TO, 1.55f,
-R_V_LINE_TO, 6.2f,
-R_H_LINE_TO, -2.32f,
-R_V_LINE_TO, -1.6f,
-R_CUBIC_TO, 0.54f, -0.29f, 0.93f, -0.84f, 0.93f, -1.49f,
-R_ARC_TO, 1.71f, 1.71f, 0, 0, 0, -1.7f, -1.7f,
-ARC_TO, 1.71f, 1.71f, 0, 0, 0, 155, 75.2f,
-R_CUBIC_TO, 0, 0.66f, 0.39f, 1.21f, 0.93f, 1.5f,
-R_V_LINE_TO, 1.6f,
-R_CUBIC_TO, 0, 0.86f, 0.69f, 1.55f, 1.55f, 1.55f,
-R_H_LINE_TO, 2.32f,
-R_V_LINE_TO, 2.36f,
-R_CUBIC_TO, -0.55f, 0.29f, -0.93f, 0.85f, -0.93f, 1.51f,
-R_ARC_TO, 1.7f, 1.7f, 0, 0, 0, 3.41f, 0,
-R_CUBIC_TO, 0, -0.66f, -0.38f, -1.22f, -0.93f, -1.51f,
-R_V_LINE_TO, -2.36f,
-R_H_LINE_TO, 2.32f,
-R_CUBIC_TO, 0.86f, 0, 1.55f, -0.69f, 1.55f, -1.55f,
-R_V_LINE_TO, -1.55f,
-H_LINE_TO, 166,
-R_V_LINE_TO, -3.1f,
-R_H_LINE_TO, -3.1f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x33, 0x6A, 0xC4,
-MOVE_TO, 147, 93.23f,
-R_CUBIC_TO, -4.88f, -3.94f, -8, -9.97f, -8, -16.73f,
-R_CUBIC_TO, 0, -6.76f, 3.12f, -12.79f, 8, -16.73f,
-R_V_LINE_TO, 33.47f,
-CLOSE
diff --git a/chrome/app/vector_icons/webauthn/webauthn_usb_dark.icon b/chrome/app/vector_icons/webauthn/webauthn_usb_dark.icon
deleted file mode 100644
index 3255e92..0000000
--- a/chrome/app/vector_icons/webauthn/webauthn_usb_dark.icon
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright 2019 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, 448,
-NEW_PATH,
-PATH_COLOR_ARGB, 0x18, 0x00, 0x00, 0x00,
-MOVE_TO, 0, 0,
-R_H_LINE_TO, 448,
-R_V_LINE_TO, 119,
-H_LINE_TO, 0,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 318.49f, 67.44f,
-H_LINE_TO, 275,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 302.36f, 52,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-MOVE_TO, 372.49f, 33.44f,
-H_LINE_TO, 329,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 356.36f, 18,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-MOVE_TO, 60.49f, 72.44f,
-H_LINE_TO, 17,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 44.36f, 57,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x41, 0x44, 0x47,
-MOVE_TO, 137.35f, 54.4f,
-H_LINE_TO, 146,
-R_ARC_TO, 1, 1, 0, 0, 1, 1, 1,
-V_LINE_TO, 128,
-R_ARC_TO, 8, 8, 0, 0, 1, -8, 8,
-H_LINE_TO, 109,
-R_ARC_TO, 8, 8, 0, 0, 1, -8, -8,
-V_LINE_TO, 55.4f,
-R_ARC_TO, 1, 1, 0, 0, 1, 1, -1,
-R_H_LINE_TO, 8.65f,
-V_LINE_TO, 34,
-R_H_LINE_TO, 26.71f,
-R_V_LINE_TO, 20.4f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 137.35f, 54.4f,
-H_LINE_TO, 146,
-R_ARC_TO, 1, 1, 0, 0, 1, 1, 1,
-V_LINE_TO, 128,
-R_ARC_TO, 8, 8, 0, 0, 1, -8, 8,
-H_LINE_TO, 109,
-R_ARC_TO, 8, 8, 0, 0, 1, -8, -8,
-V_LINE_TO, 55.4f,
-R_ARC_TO, 1, 1, 0, 0, 1, 1, -1,
-R_H_LINE_TO, 8.65f,
-V_LINE_TO, 34,
-R_H_LINE_TO, 26.71f,
-R_V_LINE_TO, 20.4f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xF2, 0x8B, 0x82,
-MOVE_TO, 96, 54.71f,
-CUBIC_TO, 96, 51.56f, 98.53f, 49, 101.65f, 49,
-R_H_LINE_TO, 3.83f,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 105, 30,
-R_H_LINE_TO, 35.96f,
-R_V_LINE_TO, 20.25f,
-R_H_LINE_TO, 3.83f,
-R_CUBIC_TO, 3.12f, 0, 5.66f, 2.56f, 5.66f, 5.71f,
-V_LINE_TO, 129.59f,
-MOVE_TO, 139.62f, 140.43f,
-R_H_LINE_TO, -32.31f,
-CUBIC_TO, 101.06f, 140.43f, 96, 135.31f, 96, 129,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 115, 38,
-R_H_LINE_TO, 11,
-R_V_LINE_TO, 16,
-H_LINE_TO, 115,
-CLOSE,
-MOVE_TO, 129, 38,
-R_H_LINE_TO, 5,
-R_V_LINE_TO, 16,
-R_H_LINE_TO, -5,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-CIRCLE, 125, 96, 12,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 95.5f, 63.5f,
-R_V_LINE_TO, 38.01f,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x8A, 0xB4, 0xF8,
-MOVE_TO, 182, 76.5f,
-CUBIC_TO, 182, 88.37f, 172.38f, 98, 160.5f, 98,
-CUBIC_TO_SHORTHAND, 139, 88.37f, 139, 76.5f,
-CUBIC_TO_SHORTHAND, 148.63f, 55, 160.5f, 55,
-CUBIC_TO_SHORTHAND, 182, 64.63f, 182, 76.5f,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
-MOVE_TO, 162.9f, 73.65f,
-R_V_LINE_TO, 3.1f,
-R_H_LINE_TO, 0.78f,
-R_V_LINE_TO, 1.55f,
-R_H_LINE_TO, -2.32f,
-R_V_LINE_TO, -6.2f,
-R_H_LINE_TO, 1.55f,
-LINE_TO, 160.58f, 69,
-R_LINE_TO, -2.32f, 3.1f,
-R_H_LINE_TO, 1.55f,
-R_V_LINE_TO, 6.2f,
-R_H_LINE_TO, -2.32f,
-R_V_LINE_TO, -1.6f,
-R_CUBIC_TO, 0.54f, -0.29f, 0.93f, -0.84f, 0.93f, -1.49f,
-R_ARC_TO, 1.71f, 1.71f, 0, 0, 0, -1.7f, -1.7f,
-ARC_TO, 1.71f, 1.71f, 0, 0, 0, 155, 75.2f,
-R_CUBIC_TO, 0, 0.66f, 0.39f, 1.21f, 0.93f, 1.5f,
-R_V_LINE_TO, 1.6f,
-R_CUBIC_TO, 0, 0.86f, 0.69f, 1.55f, 1.55f, 1.55f,
-R_H_LINE_TO, 2.32f,
-R_V_LINE_TO, 2.36f,
-R_CUBIC_TO, -0.55f, 0.29f, -0.93f, 0.85f, -0.93f, 1.51f,
-R_ARC_TO, 1.7f, 1.7f, 0, 0, 0, 3.41f, 0,
-R_CUBIC_TO, 0, -0.66f, -0.38f, -1.22f, -0.93f, -1.51f,
-R_V_LINE_TO, -2.36f,
-R_H_LINE_TO, 2.32f,
-R_CUBIC_TO, 0.86f, 0, 1.55f, -0.69f, 1.55f, -1.55f,
-R_V_LINE_TO, -1.55f,
-H_LINE_TO, 166,
-R_V_LINE_TO, -3.1f,
-R_H_LINE_TO, -3.1f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x8A, 0xB4, 0xF8,
-MOVE_TO, 162.9f, 73.65f,
-R_V_LINE_TO, 3.1f,
-R_H_LINE_TO, 0.78f,
-R_V_LINE_TO, 1.55f,
-R_H_LINE_TO, -2.32f,
-R_V_LINE_TO, -6.2f,
-R_H_LINE_TO, 1.55f,
-LINE_TO, 160.58f, 69,
-R_LINE_TO, -2.32f, 3.1f,
-R_H_LINE_TO, 1.55f,
-R_V_LINE_TO, 6.2f,
-R_H_LINE_TO, -2.32f,
-R_V_LINE_TO, -1.6f,
-R_CUBIC_TO, 0.54f, -0.29f, 0.93f, -0.84f, 0.93f, -1.49f,
-R_ARC_TO, 1.71f, 1.71f, 0, 0, 0, -1.7f, -1.7f,
-ARC_TO, 1.71f, 1.71f, 0, 0, 0, 155, 75.2f,
-R_CUBIC_TO, 0, 0.66f, 0.39f, 1.21f, 0.93f, 1.5f,
-R_V_LINE_TO, 1.6f,
-R_CUBIC_TO, 0, 0.86f, 0.69f, 1.55f, 1.55f, 1.55f,
-R_H_LINE_TO, 2.32f,
-R_V_LINE_TO, 2.36f,
-R_CUBIC_TO, -0.55f, 0.29f, -0.93f, 0.85f, -0.93f, 1.51f,
-R_ARC_TO, 1.7f, 1.7f, 0, 0, 0, 3.41f, 0,
-R_CUBIC_TO, 0, -0.66f, -0.38f, -1.22f, -0.93f, -1.51f,
-R_V_LINE_TO, -2.36f,
-R_H_LINE_TO, 2.32f,
-R_CUBIC_TO, 0.86f, 0, 1.55f, -0.69f, 1.55f, -1.55f,
-R_V_LINE_TO, -1.55f,
-H_LINE_TO, 166,
-R_V_LINE_TO, -3.1f,
-R_H_LINE_TO, -3.1f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x66, 0x9D, 0xF6,
-MOVE_TO, 147, 93.23f,
-R_CUBIC_TO, -4.88f, -3.94f, -8, -9.97f, -8, -16.73f,
-R_CUBIC_TO, 0, -6.76f, 3.12f, -12.79f, 8, -16.73f,
-R_V_LINE_TO, 33.47f,
-CLOSE
diff --git a/chrome/app/vector_icons/webauthn/webauthn_welcome.icon b/chrome/app/vector_icons/webauthn/webauthn_welcome.icon
deleted file mode 100644
index e4f59ad2..0000000
--- a/chrome/app/vector_icons/webauthn/webauthn_welcome.icon
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright 2019 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, 448,
-NEW_PATH,
-PATH_COLOR_ARGB, 0x0A, 0x00, 0x00, 0x00,
-MOVE_TO, 0, 0,
-R_H_LINE_TO, 448,
-R_V_LINE_TO, 119,
-H_LINE_TO, 0,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xe8, 0xe9, 0xeb,
-MOVE_TO, 461.49f, 67.44f,
-H_LINE_TO, 418,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 445.36f, 52,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-MOVE_TO, 372.49f, 33.44f,
-H_LINE_TO, 329,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 356.36f, 18,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-MOVE_TO, 60.49f, 72.44f,
-H_LINE_TO, 17,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 44.36f, 57,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xff, 0xff, 0xff,
-MOVE_TO, 169.11f, 39.58f,
-V_LINE_TO, 33,
-R_ARC_TO, 4, 4, 0, 0, 1, 4, -4,
-R_H_LINE_TO, 30.94f,
-R_ARC_TO, 4, 4, 0, 0, 1, 4, 4,
-R_V_LINE_TO, 6.58f,
-H_LINE_TO, 288,
-R_ARC_TO, 2, 2, 0, 0, 1, 2, 2,
-V_LINE_TO, 131,
-R_ARC_TO, 2, 2, 0, 0, 1, -2, 2,
-H_LINE_TO, 163,
-R_ARC_TO, 2, 2, 0, 0, 1, -2, -2,
-V_LINE_TO, 41.58f,
-R_ARC_TO, 2, 2, 0, 0, 1, 2, -2,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xe8, 0xe9, 0xeb,
-MOVE_TO, 169.11f, 39.58f,
-V_LINE_TO, 33,
-R_ARC_TO, 4, 4, 0, 0, 1, 4, -4,
-R_H_LINE_TO, 30.94f,
-R_ARC_TO, 4, 4, 0, 0, 1, 4, 4,
-R_V_LINE_TO, 6.58f,
-H_LINE_TO, 288,
-R_ARC_TO, 2, 2, 0, 0, 1, 2, 2,
-V_LINE_TO, 131,
-R_ARC_TO, 2, 2, 0, 0, 1, -2, 2,
-H_LINE_TO, 163,
-R_ARC_TO, 2, 2, 0, 0, 1, -2, -2,
-V_LINE_TO, 41.58f,
-R_ARC_TO, 2, 2, 0, 0, 1, 2, -2,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xf8, 0xf9, 0xfa,
-ROUND_RECT, 170, 48, 111, 7, 3.5,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xfb, 0xbc, 0x06,
-MOVE_TO, 128.73f, 37.21f,
-R_CUBIC_TO, 1.11f, 1.77f, 1.66f, 3.19f, 1.66f, 4.28f,
-R_CUBIC_TO, 0, 1.21f, -0.69f, 3.05f, -2.06f, 5.56f,
-R_CUBIC_TO, 2.02f, -1.28f, 3.74f, -1.92f, 5.18f, -1.92f,
-R_CUBIC_TO, 1.44f, 0, 3.16f, 0.64f, 5.18f, 1.92f,
-R_CUBIC_TO, -1.37f, -2.51f, -2.06f, -4.35f, -2.06f, -5.56f,
-R_CUBIC_TO, 0, -1.09f, 0.56f, -2.51f, 1.66f, -4.28f,
-R_CUBIC_TO, -1.85f, 1.12f, -3.44f, 1.68f, -4.78f, 1.68f,
-R_CUBIC_TO, -1.34f, 0, -2.93f, -0.56f, -4.78f, -1.68f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xfb, 0xbc, 0x06,
-MOVE_TO, 147.01f, 18.31f,
-R_CUBIC_TO, -0.22f, 0.69f, -0.49f, 1.19f, -0.82f, 1.51f,
-R_CUBIC_TO, -0.39f, 0.39f, -1.11f, 0.76f, -2.16f, 1.12f,
-R_CUBIC_TO, 0.87f, 0.27f, 1.52f, 0.62f, 1.97f, 1.07f,
-R_CUBIC_TO, 0.45f, 0.45f, 0.8f, 1.1f, 1.07f, 1.97f,
-R_CUBIC_TO, 0.36f, -1.05f, 0.72f, -1.76f, 1.12f, -2.16f,
-R_CUBIC_TO, 0.33f, -0.33f, 0.83f, -0.59f, 1.51f, -0.82f,
-R_CUBIC_TO, -0.74f, -0.26f, -1.31f, -0.58f, -1.71f, -0.98f,
-R_CUBIC_TO, -0.4f, -0.4f, -0.72f, -0.97f, -0.98f, -1.71f,
-CLOSE,
-MOVE_TO, 298.02f, 22.86f,
-R_CUBIC_TO, -0.6f, 2.85f, -1.4f, 4.79f, -2.43f, 5.81f,
-R_CUBIC_TO, -1.11f, 1.11f, -3.52f, 2.18f, -7.26f, 3.24f,
-R_CUBIC_TO, 3.2f, 0.66f, 5.46f, 1.65f, 6.8f, 2.99f,
-R_CUBIC_TO, 1.34f, 1.34f, 2.33f, 3.6f, 2.99f, 6.8f,
-R_CUBIC_TO, 1.06f, -3.74f, 2.13f, -6.15f, 3.24f, -7.26f,
-R_CUBIC_TO, 1.03f, -1.03f, 2.96f, -1.83f, 5.81f, -2.43f,
-R_CUBIC_TO, -2.92f, -0.66f, -5.01f, -1.61f, -6.28f, -2.87f,
-R_CUBIC_TO, -1.27f, -1.26f, -2.21f, -3.35f, -2.87f, -6.28f,
-CLOSE,
-MOVE_TO, 283.02f, 17.31f,
-R_CUBIC_TO, -0.22f, 0.69f, -0.49f, 1.19f, -0.82f, 1.51f,
-R_CUBIC_TO, -0.39f, 0.39f, -1.11f, 0.76f, -2.16f, 1.12f,
-R_CUBIC_TO, 0.87f, 0.27f, 1.52f, 0.62f, 1.97f, 1.07f,
-R_CUBIC_TO, 0.45f, 0.45f, 0.8f, 1.1f, 1.07f, 1.97f,
-R_CUBIC_TO, 0.36f, -1.05f, 0.72f, -1.76f, 1.12f, -2.16f,
-R_CUBIC_TO, 0.33f, -0.33f, 0.83f, -0.59f, 1.51f, -0.82f,
-R_CUBIC_TO, -0.74f, -0.26f, -1.31f, -0.58f, -1.71f, -0.98f,
-R_CUBIC_TO, -0.4f, -0.4f, -0.72f, -0.97f, -0.98f, -1.71f,
-CLOSE,
-MOVE_TO, 311.02f, 20.31f,
-R_CUBIC_TO, -0.22f, 0.69f, -0.49f, 1.19f, -0.82f, 1.51f,
-R_CUBIC_TO, -0.39f, 0.39f, -1.11f, 0.76f, -2.16f, 1.12f,
-R_CUBIC_TO, 0.87f, 0.27f, 1.52f, 0.62f, 1.97f, 1.07f,
-R_CUBIC_TO, 0.45f, 0.45f, 0.8f, 1.1f, 1.07f, 1.97f,
-R_CUBIC_TO, 0.36f, -1.05f, 0.72f, -1.76f, 1.12f, -2.16f,
-R_CUBIC_TO, 0.33f, -0.33f, 0.83f, -0.59f, 1.51f, -0.82f,
-R_CUBIC_TO, -0.74f, -0.26f, -1.31f, -0.58f, -1.71f, -0.98f,
-R_CUBIC_TO, -0.4f, -0.4f, -0.72f, -0.97f, -0.98f, -1.71f,
-CLOSE,
-MOVE_TO, 303.02f, 84.31f,
-R_CUBIC_TO, -0.22f, 0.69f, -0.49f, 1.19f, -0.82f, 1.51f,
-R_CUBIC_TO, -0.39f, 0.39f, -1.11f, 0.76f, -2.16f, 1.12f,
-R_CUBIC_TO, 0.87f, 0.27f, 1.52f, 0.62f, 1.97f, 1.07f,
-R_CUBIC_TO, 0.45f, 0.45f, 0.8f, 1.1f, 1.07f, 1.97f,
-R_CUBIC_TO, 0.36f, -1.05f, 0.72f, -1.76f, 1.12f, -2.16f,
-R_CUBIC_TO, 0.33f, -0.33f, 0.83f, -0.59f, 1.51f, -0.82f,
-R_CUBIC_TO, -0.74f, -0.26f, -1.31f, -0.58f, -1.71f, -0.98f,
-R_CUBIC_TO, -0.4f, -0.4f, -0.72f, -0.97f, -0.98f, -1.71f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x1a, 0x73, 0xe8,
-CIRCLE, 147, 92, 31,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xff, 0xff, 0xff,
-MOVE_TO, 147, 92,
-R_CUBIC_TO, 3.04f, 0, 5.5f, -2.46f, 5.5f, -5.5f,
-CUBIC_TO_SHORTHAND, 150.04f, 81, 147, 81,
-R_CUBIC_TO, -3.04f, 0, -5.5f, 2.46f, -5.5f, 5.5f,
-CUBIC_TO_SHORTHAND, 143.96f, 92, 147, 92,
-CLOSE,
-R_MOVE_TO, 0, 2.75f,
-R_CUBIC_TO, -3.67f, 0, -11, 1.84f, -11, 5.5f,
-V_LINE_TO, 103,
-R_H_LINE_TO, 22,
-R_V_LINE_TO, -2.75f,
-R_CUBIC_TO, 0, -3.66f, -7.33f, -5.5f, -11, -5.5f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x16, 0x63, 0xc8,
-MOVE_TO, 161, 64.33f,
-CUBIC_TO, 171.09f, 69.44f, 178, 79.91f, 178, 91.99f,
-R_CUBIC_TO, 0, 12.04f, -6.87f, 22.48f, -16.9f, 27.62f,
-R_ARC_TO, 2, 2, 0, 0, 1, -0.1f, -0.62f,
-V_LINE_TO, 64.33f,
-CLOSE
diff --git a/chrome/app/vector_icons/webauthn/webauthn_welcome_dark.icon b/chrome/app/vector_icons/webauthn/webauthn_welcome_dark.icon
deleted file mode 100644
index 7ad18e0..0000000
--- a/chrome/app/vector_icons/webauthn/webauthn_welcome_dark.icon
+++ /dev/null
@@ -1,226 +0,0 @@
-// Copyright 2019 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, 448,
-NEW_PATH,
-PATH_COLOR_ARGB, 0x18, 0x00, 0x00, 0x00,
-MOVE_TO, 0, 0,
-R_H_LINE_TO, 448,
-R_V_LINE_TO, 119,
-H_LINE_TO, 0,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 461.49f, 67.44f,
-H_LINE_TO, 418,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 445.36f, 52,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-MOVE_TO, 372.49f, 33.44f,
-H_LINE_TO, 329,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 356.36f, 18,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-MOVE_TO, 60.49f, 72.44f,
-H_LINE_TO, 17,
-R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
-R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
-R_LINE_TO, 0.47f, 0.17f,
-R_LINE_TO, 0.31f, -0.39f,
-ARC_TO, 16.09f, 16.09f, 0, 0, 1, 44.36f, 57,
-R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x41, 0x44, 0x47,
-MOVE_TO, 169.11f, 39.58f,
-V_LINE_TO, 33,
-R_ARC_TO, 4, 4, 0, 0, 1, 4, -4,
-R_H_LINE_TO, 30.94f,
-R_ARC_TO, 4, 4, 0, 0, 1, 4, 4,
-R_V_LINE_TO, 6.58f,
-H_LINE_TO, 288,
-R_ARC_TO, 2, 2, 0, 0, 1, 2, 2,
-V_LINE_TO, 131,
-R_ARC_TO, 2, 2, 0, 0, 1, -2, 2,
-H_LINE_TO, 163,
-R_ARC_TO, 2, 2, 0, 0, 1, -2, -2,
-V_LINE_TO, 41.58f,
-R_ARC_TO, 2, 2, 0, 0, 1, 2, -2,
-R_H_LINE_TO, 6.11f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-MOVE_TO, 169.11f, 39.58f,
-V_LINE_TO, 33,
-R_ARC_TO, 4, 4, 0, 0, 1, 4, -4,
-R_H_LINE_TO, 30.94f,
-R_ARC_TO, 4, 4, 0, 0, 1, 4, 4,
-R_V_LINE_TO, 6.58f,
-H_LINE_TO, 288,
-R_ARC_TO, 2, 2, 0, 0, 1, 2, 2,
-V_LINE_TO, 131,
-R_ARC_TO, 2, 2, 0, 0, 1, -2, 2,
-H_LINE_TO, 163,
-R_ARC_TO, 2, 2, 0, 0, 1, -2, -2,
-V_LINE_TO, 41.58f,
-R_ARC_TO, 2, 2, 0, 0, 1, 2, -2,
-R_H_LINE_TO, 6.11f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
-ROUND_RECT, 170, 48, 111, 7, 3.5,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xFE, 0xD5, 0x63,
-MOVE_TO, 128.73f, 37.21f,
-R_CUBIC_TO, 1.11f, 1.77f, 1.66f, 3.19f, 1.66f, 4.28f,
-R_CUBIC_TO, 0, 1.21f, -0.69f, 3.05f, -2.06f, 5.56f,
-R_CUBIC_TO, 2.02f, -1.28f, 3.74f, -1.92f, 5.18f, -1.92f,
-R_CUBIC_TO, 1.44f, 0, 3.16f, 0.64f, 5.18f, 1.92f,
-R_CUBIC_TO, -1.37f, -2.51f, -2.06f, -4.35f, -2.06f, -5.56f,
-R_CUBIC_TO, 0, -1.09f, 0.56f, -2.51f, 1.66f, -4.28f,
-R_CUBIC_TO, -1.85f, 1.12f, -3.44f, 1.68f, -4.78f, 1.68f,
-R_CUBIC_TO, -1.34f, 0, -2.93f, -0.56f, -4.78f, -1.68f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xFE, 0xD5, 0x63,
-MOVE_TO, 147.01f, 18.31f,
-R_CUBIC_TO, -0.22f, 0.69f, -0.49f, 1.19f, -0.82f, 1.51f,
-R_CUBIC_TO, -0.39f, 0.39f, -1.11f, 0.76f, -2.16f, 1.12f,
-R_CUBIC_TO, 0.87f, 0.27f, 1.52f, 0.62f, 1.97f, 1.07f,
-R_CUBIC_TO, 0.44f, 0.44f, 0.8f, 1.1f, 1.07f, 1.97f,
-R_CUBIC_TO, 0.36f, -1.05f, 0.72f, -1.76f, 1.12f, -2.16f,
-R_CUBIC_TO, 0.33f, -0.33f, 0.83f, -0.59f, 1.51f, -0.82f,
-R_CUBIC_TO, -0.74f, -0.26f, -1.31f, -0.58f, -1.71f, -0.98f,
-R_CUBIC_TO, -0.4f, -0.4f, -0.72f, -0.97f, -0.98f, -1.71f,
-CLOSE,
-MOVE_TO, 298.02f, 22.86f,
-R_CUBIC_TO, -0.6f, 2.85f, -1.4f, 4.79f, -2.43f, 5.81f,
-R_CUBIC_TO, -1.11f, 1.11f, -3.52f, 2.18f, -7.26f, 3.24f,
-R_CUBIC_TO, 3.2f, 0.66f, 5.46f, 1.65f, 6.8f, 2.99f,
-R_CUBIC_TO, 1.34f, 1.34f, 2.33f, 3.6f, 2.99f, 6.8f,
-R_CUBIC_TO, 1.06f, -3.74f, 2.13f, -6.15f, 3.24f, -7.26f,
-R_CUBIC_TO, 1.03f, -1.03f, 2.96f, -1.83f, 5.81f, -2.43f,
-R_CUBIC_TO, -2.92f, -0.66f, -5.01f, -1.61f, -6.28f, -2.87f,
-R_CUBIC_TO, -1.26f, -1.26f, -2.21f, -3.35f, -2.87f, -6.28f,
-CLOSE,
-MOVE_TO, 283.02f, 17.31f,
-R_CUBIC_TO, -0.22f, 0.69f, -0.49f, 1.19f, -0.82f, 1.51f,
-R_CUBIC_TO, -0.39f, 0.39f, -1.11f, 0.76f, -2.16f, 1.12f,
-R_CUBIC_TO, 0.87f, 0.27f, 1.52f, 0.62f, 1.97f, 1.07f,
-R_CUBIC_TO, 0.44f, 0.44f, 0.8f, 1.1f, 1.07f, 1.97f,
-R_CUBIC_TO, 0.36f, -1.05f, 0.72f, -1.76f, 1.12f, -2.16f,
-R_CUBIC_TO, 0.33f, -0.33f, 0.83f, -0.59f, 1.51f, -0.82f,
-R_CUBIC_TO, -0.74f, -0.26f, -1.31f, -0.58f, -1.71f, -0.98f,
-R_CUBIC_TO, -0.4f, -0.4f, -0.72f, -0.97f, -0.98f, -1.71f,
-CLOSE,
-MOVE_TO, 311.02f, 20.31f,
-R_CUBIC_TO, -0.22f, 0.69f, -0.49f, 1.19f, -0.82f, 1.51f,
-R_CUBIC_TO, -0.39f, 0.39f, -1.11f, 0.76f, -2.16f, 1.12f,
-R_CUBIC_TO, 0.87f, 0.27f, 1.52f, 0.62f, 1.97f, 1.07f,
-R_CUBIC_TO, 0.44f, 0.44f, 0.8f, 1.1f, 1.07f, 1.97f,
-R_CUBIC_TO, 0.36f, -1.05f, 0.72f, -1.76f, 1.12f, -2.16f,
-R_CUBIC_TO, 0.33f, -0.33f, 0.83f, -0.59f, 1.51f, -0.82f,
-R_CUBIC_TO, -0.74f, -0.26f, -1.31f, -0.58f, -1.71f, -0.98f,
-R_CUBIC_TO, -0.4f, -0.4f, -0.72f, -0.97f, -0.98f, -1.71f,
-CLOSE,
-MOVE_TO, 303.02f, 84.31f,
-R_CUBIC_TO, -0.22f, 0.69f, -0.49f, 1.19f, -0.82f, 1.51f,
-R_CUBIC_TO, -0.39f, 0.39f, -1.11f, 0.76f, -2.16f, 1.12f,
-R_CUBIC_TO, 0.87f, 0.27f, 1.52f, 0.62f, 1.97f, 1.07f,
-R_CUBIC_TO, 0.44f, 0.44f, 0.8f, 1.1f, 1.07f, 1.97f,
-R_CUBIC_TO, 0.36f, -1.05f, 0.72f, -1.76f, 1.12f, -2.16f,
-R_CUBIC_TO, 0.33f, -0.33f, 0.83f, -0.59f, 1.51f, -0.82f,
-R_CUBIC_TO, -0.74f, -0.26f, -1.31f, -0.58f, -1.71f, -0.98f,
-R_CUBIC_TO, -0.4f, -0.4f, -0.72f, -0.97f, -0.98f, -1.71f,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-PATH_COLOR_ARGB, 0xFF, 0xFE, 0xD5, 0x63,
-MOVE_TO, 147.01f, 18.31f,
-R_CUBIC_TO, -0.22f, 0.69f, -0.49f, 1.19f, -0.82f, 1.51f,
-R_CUBIC_TO, -0.39f, 0.39f, -1.11f, 0.76f, -2.16f, 1.12f,
-R_CUBIC_TO, 0.87f, 0.27f, 1.52f, 0.62f, 1.97f, 1.07f,
-R_CUBIC_TO, 0.44f, 0.44f, 0.8f, 1.1f, 1.07f, 1.97f,
-R_CUBIC_TO, 0.36f, -1.05f, 0.72f, -1.76f, 1.12f, -2.16f,
-R_CUBIC_TO, 0.33f, -0.33f, 0.83f, -0.59f, 1.51f, -0.82f,
-R_CUBIC_TO, -0.74f, -0.26f, -1.31f, -0.58f, -1.71f, -0.98f,
-R_CUBIC_TO, -0.4f, -0.4f, -0.72f, -0.97f, -0.98f, -1.71f,
-CLOSE,
-MOVE_TO, 298.02f, 22.86f,
-R_CUBIC_TO, -0.6f, 2.85f, -1.4f, 4.79f, -2.43f, 5.81f,
-R_CUBIC_TO, -1.11f, 1.11f, -3.52f, 2.18f, -7.26f, 3.24f,
-R_CUBIC_TO, 3.2f, 0.66f, 5.46f, 1.65f, 6.8f, 2.99f,
-R_CUBIC_TO, 1.34f, 1.34f, 2.33f, 3.6f, 2.99f, 6.8f,
-R_CUBIC_TO, 1.06f, -3.74f, 2.13f, -6.15f, 3.24f, -7.26f,
-R_CUBIC_TO, 1.03f, -1.03f, 2.96f, -1.83f, 5.81f, -2.43f,
-R_CUBIC_TO, -2.92f, -0.66f, -5.01f, -1.61f, -6.28f, -2.87f,
-R_CUBIC_TO, -1.26f, -1.26f, -2.21f, -3.35f, -2.87f, -6.28f,
-CLOSE,
-MOVE_TO, 283.02f, 17.31f,
-R_CUBIC_TO, -0.22f, 0.69f, -0.49f, 1.19f, -0.82f, 1.51f,
-R_CUBIC_TO, -0.39f, 0.39f, -1.11f, 0.76f, -2.16f, 1.12f,
-R_CUBIC_TO, 0.87f, 0.27f, 1.52f, 0.62f, 1.97f, 1.07f,
-R_CUBIC_TO, 0.44f, 0.44f, 0.8f, 1.1f, 1.07f, 1.97f,
-R_CUBIC_TO, 0.36f, -1.05f, 0.72f, -1.76f, 1.12f, -2.16f,
-R_CUBIC_TO, 0.33f, -0.33f, 0.83f, -0.59f, 1.51f, -0.82f,
-R_CUBIC_TO, -0.74f, -0.26f, -1.31f, -0.58f, -1.71f, -0.98f,
-R_CUBIC_TO, -0.4f, -0.4f, -0.72f, -0.97f, -0.98f, -1.71f,
-CLOSE,
-MOVE_TO, 311.02f, 20.31f,
-R_CUBIC_TO, -0.22f, 0.69f, -0.49f, 1.19f, -0.82f, 1.51f,
-R_CUBIC_TO, -0.39f, 0.39f, -1.11f, 0.76f, -2.16f, 1.12f,
-R_CUBIC_TO, 0.87f, 0.27f, 1.52f, 0.62f, 1.97f, 1.07f,
-R_CUBIC_TO, 0.44f, 0.44f, 0.8f, 1.1f, 1.07f, 1.97f,
-R_CUBIC_TO, 0.36f, -1.05f, 0.72f, -1.76f, 1.12f, -2.16f,
-R_CUBIC_TO, 0.33f, -0.33f, 0.83f, -0.59f, 1.51f, -0.82f,
-R_CUBIC_TO, -0.74f, -0.26f, -1.31f, -0.58f, -1.71f, -0.98f,
-R_CUBIC_TO, -0.4f, -0.4f, -0.72f, -0.97f, -0.98f, -1.71f,
-CLOSE,
-MOVE_TO, 303.02f, 84.31f,
-R_CUBIC_TO, -0.22f, 0.69f, -0.49f, 1.19f, -0.82f, 1.51f,
-R_CUBIC_TO, -0.39f, 0.39f, -1.11f, 0.76f, -2.16f, 1.12f,
-R_CUBIC_TO, 0.87f, 0.27f, 1.52f, 0.62f, 1.97f, 1.07f,
-R_CUBIC_TO, 0.44f, 0.44f, 0.8f, 1.1f, 1.07f, 1.97f,
-R_CUBIC_TO, 0.36f, -1.05f, 0.72f, -1.76f, 1.12f, -2.16f,
-R_CUBIC_TO, 0.33f, -0.33f, 0.83f, -0.59f, 1.51f, -0.82f,
-R_CUBIC_TO, -0.74f, -0.26f, -1.31f, -0.58f, -1.71f, -0.98f,
-R_CUBIC_TO, -0.4f, -0.4f, -0.72f, -0.97f, -0.98f, -1.71f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x8A, 0xB4, 0xF8,
-CIRCLE, 147, 92, 31,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
-MOVE_TO, 147, 92,
-R_CUBIC_TO, 3.04f, 0, 5.5f, -2.46f, 5.5f, -5.5f,
-CUBIC_TO_SHORTHAND, 150.04f, 81, 147, 81,
-R_ARC_TO, 5.5f, 5.5f, 0, 0, 0, -5.5f, 5.5f,
-R_CUBIC_TO, 0, 3.04f, 2.46f, 5.5f, 5.5f, 5.5f,
-CLOSE,
-R_MOVE_TO, 0, 2.75f,
-R_CUBIC_TO, -3.67f, 0, -11, 1.84f, -11, 5.5f,
-V_LINE_TO, 103,
-R_H_LINE_TO, 22,
-R_V_LINE_TO, -2.75f,
-R_CUBIC_TO, 0, -3.66f, -7.33f, -5.5f, -11, -5.5f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x66, 0x9D, 0xF6,
-MOVE_TO, 161, 64.33f,
-CUBIC_TO, 171.09f, 69.44f, 178, 79.91f, 178, 91.99f,
-R_CUBIC_TO, 0, 12.04f, -6.87f, 22.48f, -16.9f, 27.62f,
-R_ARC_TO, 2, 2, 0, 0, 1, -0.1f, -0.62f,
-V_LINE_TO, 64.33f,
-CLOSE
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index 0b618c0..305f12f 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -294,7 +294,6 @@
   "+components/segmentation_platform/public",
   "+components/send_tab_to_self",
   "+components/services/app_service/public",
-  "+components/services/app_service/public/mojom",
   "+components/services/filesystem/public/mojom",
   "+components/services/heap_profiling",
   "+components/services/language_detection/public/cpp",
@@ -585,5 +584,8 @@
   ],
   "browsing_data_model_browsertest.cc" : [
     "+components/services/storage/shared_storage/shared_storage_manager.h",
+  ],
+  "render_view_context_menu_browsertest.cc" : [
+    "+third_party/libwebp/src/src/webp/decode.h",
   ]
 }
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index c3fa702..514a1f0 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -4542,6 +4542,11 @@
      flag_descriptions::kBackGestureRefactorAndroidName,
      flag_descriptions::kBackGestureRefactorAndroidDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(chrome::android::kBackGestureRefactorAndroid)},
+    {"back-gesture-refactor-activity-android",
+     flag_descriptions::kBackGestureRefactorActivityAndroidName,
+     flag_descriptions::kBackGestureRefactorActivityAndroidDescription,
+     kOsAndroid,
+     FEATURE_VALUE_TYPE(chrome::android::kBackGestureRefactorActivityAndroid)},
     {"infobar-scroll-optimization",
      flag_descriptions::kInfobarScrollOptimizationName,
      flag_descriptions::kInfobarScrollOptimizationDescription, kOsAndroid,
@@ -5026,11 +5031,6 @@
      flag_descriptions::kDisableCameraFrameRotationAtSourceName,
      flag_descriptions::kDisableCameraFrameRotationAtSourceDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(media::features::kDisableCameraFrameRotationAtSource)},
-    {"drive-fs-bidirectional-native-messaging",
-     flag_descriptions::kDriveFsBidirectionalNativeMessagingName,
-     flag_descriptions::kDriveFsBidirectionalNativeMessagingDescription,
-     kOsCrOS,
-     FEATURE_VALUE_TYPE(ash::features::kDriveFsBidirectionalNativeMessaging)},
     {"drive-fs-chrome-networking",
      flag_descriptions::kDriveFsChromeNetworkingName,
      flag_descriptions::kDriveFsChromeNetworkingDescription, kOsCrOS,
@@ -6618,6 +6618,11 @@
      flag_descriptions::kFastPairDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(ash::features::kFastPair)},
 
+    {"fast-pair-handshake-refactor",
+     flag_descriptions::kFastPairHandshakeRefactorName,
+     flag_descriptions::kFastPairHandshakeRefactorDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(ash::features::kFastPairHandshakeRefactor)},
+
     {"fast-pair-low-power", flag_descriptions::kFastPairLowPowerName,
      flag_descriptions::kFastPairLowPowerDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(ash::features::kFastPairLowPower)},
@@ -9136,10 +9141,6 @@
                                     "BindingManagerConnectionLimit")},
 #endif
 
-    {"webauthn-new-desktop-ui", flag_descriptions::kWebAuthnNewDesktopUIName,
-     flag_descriptions::kWebAuthnNewDesktopUIDescription, kOsDesktop,
-     FEATURE_VALUE_TYPE(device::kWebAuthnNewDiscoverableCredentialsUi)},
-
     {"webui-omnibox-popup", flag_descriptions::kWebUIOmniboxPopupName,
      flag_descriptions::kWebUIOmniboxPopupDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(omnibox::kWebUIOmniboxPopup)},
diff --git a/chrome/browser/android/ssl/mock_cert_verifier_rule_android.cc b/chrome/browser/android/ssl/mock_cert_verifier_rule_android.cc
index 4eb8487..8a8104da 100644
--- a/chrome/browser/android/ssl/mock_cert_verifier_rule_android.cc
+++ b/chrome/browser/android/ssl/mock_cert_verifier_rule_android.cc
@@ -13,22 +13,15 @@
 
 MockCertVerifierRuleAndroid::MockCertVerifierRuleAndroid() = default;
 
-void MockCertVerifierRuleAndroid::SetResult(
-    JNIEnv* env,
-    const base::android::JavaParamRef<jobject>& obj,
-    int result) {
+void MockCertVerifierRuleAndroid::SetResult(JNIEnv* env, int result) {
   mock_cert_verifier_.mock_cert_verifier()->set_default_result(result);
 }
 
-void MockCertVerifierRuleAndroid::SetUp(
-    JNIEnv* env,
-    const base::android::JavaParamRef<jobject>& obj) {
+void MockCertVerifierRuleAndroid::SetUp(JNIEnv* env) {
   mock_cert_verifier_.SetUpCommandLine(base::CommandLine::ForCurrentProcess());
   mock_cert_verifier_.SetUpInProcessBrowserTestFixture();
 }
 
-void MockCertVerifierRuleAndroid::TearDown(
-    JNIEnv* env,
-    const base::android::JavaParamRef<jobject>& obj) {
+void MockCertVerifierRuleAndroid::TearDown(JNIEnv* env) {
   mock_cert_verifier_.TearDownInProcessBrowserTestFixture();
 }
diff --git a/chrome/browser/android/ssl/mock_cert_verifier_rule_android.h b/chrome/browser/android/ssl/mock_cert_verifier_rule_android.h
index cf0537c6..c949d3c 100644
--- a/chrome/browser/android/ssl/mock_cert_verifier_rule_android.h
+++ b/chrome/browser/android/ssl/mock_cert_verifier_rule_android.h
@@ -18,12 +18,9 @@
       delete;
 
   // Sets the certificate verification result to force.
-  void SetResult(JNIEnv* env,
-                 const base::android::JavaParamRef<jobject>& obj,
-                 int result);
-
-  void SetUp(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
-  void TearDown(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void SetResult(JNIEnv* env, int result);
+  void SetUp(JNIEnv* env);
+  void TearDown(JNIEnv* env);
 
  private:
   content::ContentMockCertVerifier mock_cert_verifier_;
diff --git a/chrome/browser/android/vr/gvr_graphics_delegate.cc b/chrome/browser/android/vr/gvr_graphics_delegate.cc
index f32ee5a..86c4df3 100644
--- a/chrome/browser/android/vr/gvr_graphics_delegate.cc
+++ b/chrome/browser/android/vr/gvr_graphics_delegate.cc
@@ -174,7 +174,8 @@
 
   gl::GLDisplay* display = nullptr;
   if (gl::GetGLImplementation() == gl::kGLImplementationNone) {
-    display = gl::init::InitializeGLOneOff(/*system_device_id=*/0);
+    display = gl::init::InitializeGLOneOff(
+        /*gpu_preference=*/gl::GpuPreference::kDefault);
     if (!display) {
       LOG(ERROR) << "gl::init::InitializeGLOneOff failed";
       browser_->ForceExitVr();
diff --git a/chrome/browser/apps/app_service/package_id_unittest.cc b/chrome/browser/apps/app_service/package_id_unittest.cc
index 85295ac7..b0a6aa2 100644
--- a/chrome/browser/apps/app_service/package_id_unittest.cc
+++ b/chrome/browser/apps/app_service/package_id_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/apps/app_service/package_id.h"
 
+#include "base/strings/string_piece.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace apps {
diff --git a/chrome/browser/apps/app_service/publishers/app_publisher.cc b/chrome/browser/apps/app_service/publishers/app_publisher.cc
index e77ed10b..0061e5a 100644
--- a/chrome/browser/apps/app_service/publishers/app_publisher.cc
+++ b/chrome/browser/apps/app_service/publishers/app_publisher.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/apps/app_service/publishers/app_publisher.h"
 
+#include "base/logging.h"
 #include "base/notreached.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "components/services/app_service/public/cpp/capability_access.h"
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn
index 0753a4c..5aa1332 100644
--- a/chrome/browser/ash/BUILD.gn
+++ b/chrome/browser/ash/BUILD.gn
@@ -2716,6 +2716,8 @@
     "printing/history/print_job_reporting_service_factory.cc",
     "printing/history/print_job_reporting_service_factory.h",
     "printing/history/print_job_reporting_service_impl.cc",
+    "printing/ipp_client_info_calculator.cc",
+    "printing/ipp_client_info_calculator.h",
     "printing/oauth2/authorization_server_data.cc",
     "printing/oauth2/authorization_server_data.h",
     "printing/oauth2/authorization_server_session.cc",
@@ -3535,8 +3537,6 @@
     "//components/services/app_service/public/cpp:icon_types",
     "//components/services/app_service/public/cpp:instance_update",
     "//components/services/app_service/public/cpp:intents",
-    "//components/services/app_service/public/mojom",
-    "//components/services/app_service/public/mojom:types_headers",
     "//components/services/unzip/public/cpp",
     "//components/session_manager:base",
     "//components/session_manager/core",
@@ -3883,7 +3883,6 @@
     "//components/safe_browsing/core/common:safe_browsing_prefs",
     "//components/services/app_service/public/cpp:app_file_handling",
     "//components/services/app_service/public/cpp:types",
-    "//components/services/app_service/public/mojom:types",
     "//components/services/app_service/public/protos",
     "//components/services/filesystem/public/mojom",
     "//components/services/screen_ai/public/cpp:screen_ai_chromeos_installer",
@@ -5186,6 +5185,7 @@
     "printing/history/print_job_history_service_impl_unittest.cc",
     "printing/history/print_job_info_proto_conversions_unittest.cc",
     "printing/history/print_job_reporting_service_unittest.cc",
+    "printing/ipp_client_info_calculator_unittest.cc",
     "printing/oauth2/authorization_server_data_unittest.cc",
     "printing/oauth2/authorization_server_session_unittest.cc",
     "printing/oauth2/authorization_zone_unittest.cc",
@@ -5627,7 +5627,6 @@
     "//components/services/app_service/public/cpp:instance_update",
     "//components/services/app_service/public/cpp:intents",
     "//components/services/app_service/public/cpp:test_support",
-    "//components/services/app_service/public/mojom:types",
     "//components/services/app_service/public/protos",
     "//components/services/filesystem/public/mojom",
     "//components/session_manager:base",
diff --git a/chrome/browser/ash/app_list/internal_app/internal_app_metadata.cc b/chrome/browser/ash/app_list/internal_app/internal_app_metadata.cc
index 2936d03..eea68a4b 100644
--- a/chrome/browser/ash/app_list/internal_app/internal_app_metadata.cc
+++ b/chrome/browser/ash/app_list/internal_app/internal_app_metadata.cc
@@ -23,7 +23,6 @@
 #include "chrome/browser/ash/plugin_vm/plugin_vm_util.h"
 #include "chrome/browser/ash/release_notes/release_notes_storage.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sync/session_sync_service_factory.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h"
 #include "chrome/browser/ui/extensions/app_launch_params.h"
 #include "chrome/browser/ui/settings_window_manager_chromeos.h"
@@ -31,11 +30,6 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/crx_file/id_util.h"
 #include "components/sessions/core/serialized_navigation_entry.h"
-#include "components/sync/driver/sync_service.h"
-#include "components/sync/protocol/sync_enums.pb.h"
-#include "components/sync_sessions/open_tabs_ui_delegate.h"
-#include "components/sync_sessions/session_sync_service.h"
-#include "components/sync_sessions/synced_session.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/extension.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -83,8 +77,9 @@
 
 const InternalApp* FindInternalApp(const std::string& app_id) {
   for (const auto& app : GetInternalAppListImpl(true, nullptr)) {
-    if (app_id == app.app_id)
+    if (app_id == app.app_id) {
       return &app;
+    }
   }
   return nullptr;
 }
@@ -93,69 +88,6 @@
   return !!FindInternalApp(app_id);
 }
 
-bool HasRecommendableForeignTab(
-    Profile* profile,
-    std::u16string* title,
-    GURL* url,
-    sync_sessions::OpenTabsUIDelegate* test_delegate) {
-  sync_sessions::SessionSyncService* service =
-      SessionSyncServiceFactory::GetForProfile(profile);
-  std::vector<const sync_sessions::SyncedSession*> foreign_sessions;
-  sync_sessions::OpenTabsUIDelegate* delegate =
-      test_delegate ? test_delegate : service->GetOpenTabsUIDelegate();
-  if (delegate)
-    delegate->GetAllForeignSessions(&foreign_sessions);
-
-  constexpr int kMaxForeignTabAgeInMinutes = 120;
-  base::Time latest_timestamp;
-  bool has_recommendation = false;
-  for (const sync_sessions::SyncedSession* session : foreign_sessions) {
-    if (latest_timestamp > session->modified_time)
-      continue;
-
-    auto device_form_factor = session->GetDeviceFormFactor();
-    if (device_form_factor != syncer::DeviceInfo::FormFactor::kPhone &&
-        device_form_factor != syncer::DeviceInfo::FormFactor::kTablet) {
-      continue;
-    }
-
-    for (const auto& key_value : session->windows) {
-      for (const std::unique_ptr<sessions::SessionTab>& tab :
-           key_value.second->wrapped_window.tabs) {
-        if (tab->navigations.empty())
-          continue;
-
-        const sessions::SerializedNavigationEntry& navigation =
-            tab->navigations.back();
-        const GURL& virtual_url = navigation.virtual_url();
-
-        // Only show pages with http or https.
-        if (!virtual_url.SchemeIsHTTPOrHTTPS())
-          continue;
-
-        // Only show pages recently opened.
-        const base::TimeDelta tab_age = base::Time::Now() - tab->timestamp;
-        if (tab_age > base::Minutes(kMaxForeignTabAgeInMinutes))
-          continue;
-
-        if (latest_timestamp < tab->timestamp) {
-          has_recommendation = true;
-          latest_timestamp = tab->timestamp;
-          if (title) {
-            *title = navigation.title().empty()
-                         ? base::UTF8ToUTF16(virtual_url.spec())
-                         : navigation.title();
-          }
-
-          if (url)
-            *url = virtual_url;
-        }
-      }
-    }
-  }
-  return has_recommendation;
-}
-
 size_t GetNumberOfInternalAppsShowInLauncherForTest(std::string* apps_name,
                                                     const Profile* profile) {
   size_t num_of_internal_apps_show_in_launcher = 0u;
@@ -169,8 +101,9 @@
       }
     }
   }
-  if (apps_name)
+  if (apps_name) {
     *apps_name = base::JoinString(internal_apps_name, ",");
+  }
   return num_of_internal_apps_show_in_launcher;
 }
 
diff --git a/chrome/browser/ash/app_list/internal_app/internal_app_metadata.h b/chrome/browser/ash/app_list/internal_app/internal_app_metadata.h
index e2236af..b87edf8 100644
--- a/chrome/browser/ash/app_list/internal_app/internal_app_metadata.h
+++ b/chrome/browser/ash/app_list/internal_app/internal_app_metadata.h
@@ -11,16 +11,11 @@
 #include "ui/gfx/image/image_skia.h"
 
 class Profile;
-class GURL;
 
 namespace apps {
 enum class BuiltInAppName;
 }
 
-namespace sync_sessions {
-class OpenTabsUIDelegate;
-}  // namespace sync_sessions
-
 namespace app_list {
 
 // Metadata about an internal app.
@@ -63,18 +58,6 @@
 // Returns true if |app_id| corresponds to an internal app.
 bool IsInternalApp(const std::string& app_id);
 
-// Returns true if there is a recommendable foreign tab.
-// If |title| is not nullptr, it will be replaced with the title of the foreign
-// tab's last navigation.
-// If |url| is not nullptr, it will be replaced with the url of the foreign
-// tab's last navigation.
-// |test_delegate| is used to mock OpenTabsUIDelegate in test.
-bool HasRecommendableForeignTab(
-    Profile* profile,
-    std::u16string* title,
-    GURL* url,
-    sync_sessions::OpenTabsUIDelegate* test_delegate);
-
 // Returns the number of internal apps which can show in launcher.
 // If |apps_name| is not nullptr, it will be the concatenated string of these
 // internal apps' name.
diff --git a/chrome/browser/ash/app_list/search/app_search_data_source.cc b/chrome/browser/ash/app_list/search/app_search_data_source.cc
index 68ab9909..8b7c2e1 100644
--- a/chrome/browser/ash/app_list/search/app_search_data_source.cc
+++ b/chrome/browser/ash/app_list/search/app_search_data_source.cc
@@ -20,7 +20,6 @@
 #include "chrome/browser/ash/app_list/search/app_service_app_result.h"
 #include "chrome/browser/ash/extensions/gfx_utils.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sync/session_sync_service_factory.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.h"
 #include "chromeos/ash/components/string_matching/tokenized_string.h"
@@ -28,7 +27,6 @@
 #include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/cpp/app_update.h"
 #include "components/services/app_service/public/cpp/types_util.h"
-#include "components/sync_sessions/session_sync_service.h"
 
 using ::ash::string_matching::FuzzyTokenizedStringMatch;
 using ::ash::string_matching::TokenizedString;
@@ -65,8 +63,9 @@
 //    -1 if the app is not a default app.
 int GetDefaultAppRank(const std::string app_id) {
   for (size_t i = 0; i < std::size(ranked_default_app_ids); ++i) {
-    if (app_id == ranked_default_app_ids[i])
+    if (app_id == ranked_default_app_ids[i]) {
       return i;
+    }
   }
   return -1;
 }
@@ -77,8 +76,9 @@
 void MaybeAddResult(SearchProvider::Results* results,
                     std::unique_ptr<AppResult> app_result,
                     std::set<std::string>* seen_or_filtered_apps) {
-  if (seen_or_filtered_apps->count(app_result->app_id()))
+  if (seen_or_filtered_apps->count(app_result->app_id())) {
     return;
+  }
 
   seen_or_filtered_apps->insert(app_result->app_id());
 
@@ -90,8 +90,9 @@
   }
 
   for (const auto& duplicate_app_id : duplicate_app_ids) {
-    if (seen_or_filtered_apps->count(duplicate_app_id))
+    if (seen_or_filtered_apps->count(duplicate_app_id)) {
       return;
+    }
   }
 
   results->emplace_back(std::move(app_result));
@@ -106,10 +107,12 @@
 // |score| is assumed to be within [0.0, 1.0]; if it's greater than 1.0
 // then max is returned; if it's less than 0.0, then min is returned.
 double ReRange(const double score, const double min, const double max) {
-  if (score >= 1.0)
+  if (score >= 1.0) {
     return max;
-  if (score <= 0.0)
+  }
+  if (score <= 0.0) {
     return min;
+  }
 
   return min + score * (max - min);
 }
@@ -118,11 +121,13 @@
 // set, and install time  for non-internal apps otherwise.
 base::Time GetAppLastActivityTime(const apps::AppUpdate& update) {
   base::Time last_launch_time = update.LastLaunchTime();
-  if (!last_launch_time.is_null())
+  if (!last_launch_time.is_null()) {
     return last_launch_time;
+  }
 
-  if (!update.InstalledInternally())
+  if (!update.InstalledInternally()) {
     return update.InstallTime();
+  }
 
   return base::Time();
 }
@@ -149,8 +154,9 @@
       // Sort decreasing by last activity time, then increasing by App ID.
       base::Time t1 = app1->last_activity_time();
       base::Time t2 = app2->last_activity_time();
-      if (t1 != t2)
+      if (t1 != t2) {
         return t1 > t2;
+      }
       return app1->id_ < app2->id_;
     }
   };
@@ -159,29 +165,33 @@
     // Tokenizing a string is expensive. Don't pay the price for it at
     // construction of every App, but rather, only when needed (i.e. when the
     // query is not empty and cache the result.
-    if (!tokenized_indexed_name_)
+    if (!tokenized_indexed_name_) {
       tokenized_indexed_name_ = std::make_unique<TokenizedString>(name_);
+    }
     return tokenized_indexed_name_.get();
   }
 
   bool MatchSearchableTextExactly(const TokenizedString& query) {
-    if (searchable_text_.empty())
+    if (searchable_text_.empty()) {
       return false;
+    }
 
     EnsureTokenizedIndexedSearchableText();
 
     TokenizedStringMatch match;
     for (const auto& curr_text : tokenized_indexed_searchable_text_) {
-      if (match.Calculate(query, *curr_text) > 0)
+      if (match.Calculate(query, *curr_text) > 0) {
         return true;
+      }
     }
 
     return false;
   }
 
   bool FuzzyMatchSearchableText(const TokenizedString& query) {
-    if (searchable_text_.empty())
+    if (searchable_text_.empty()) {
       return false;
+    }
 
     EnsureTokenizedIndexedSearchableText();
 
@@ -213,8 +223,9 @@
 
  private:
   void EnsureTokenizedIndexedSearchableText() {
-    if (!tokenized_indexed_searchable_text_.empty())
+    if (!tokenized_indexed_searchable_text_.empty()) {
       return;
+    }
 
     for (const std::u16string& curr_text : searchable_text_) {
       tokenized_indexed_searchable_text_.push_back(
@@ -243,16 +254,6 @@
       proxy_(apps::AppServiceProxyFactory::GetForProfile(profile)),
       icon_cache_(proxy_, apps::IconCache::GarbageCollectionPolicy::kExplicit) {
   Observe(&proxy_->AppRegistryCache());
-
-  sync_sessions::SessionSyncService* service =
-      SessionSyncServiceFactory::GetInstance()->GetForProfile(profile);
-  if (!service)
-    return;
-  // base::Unretained() is safe below because the subscription itself is a
-  // class member field and handles destruction well.
-  foreign_session_updated_subscription_ =
-      service->SubscribeToForeignSessionsChanged(base::BindRepeating(
-          &AppSearchDataSource::ScheduleRefresh, base::Unretained(this)));
 }
 
 AppSearchDataSource::~AppSearchDataSource() = default;
@@ -263,8 +264,9 @@
 }
 
 void AppSearchDataSource::RefreshIfNeeded() {
-  if (!apps_.empty() && !refresh_apps_factory_.HasWeakPtrs())
+  if (!apps_.empty() && !refresh_apps_factory_.HasWeakPtrs()) {
     return;
+  }
 
   Refresh();
 }
@@ -278,8 +280,9 @@
 
   for (auto& app : apps_) {
     // Skip apps which cannot be shown as a suggested app.
-    if (!app->recommendable())
+    if (!app->recommendable()) {
       continue;
+    }
 
     std::u16string title = app->name();
     std::unique_ptr<AppResult> result = CreateResult(app->id(), true);
@@ -326,8 +329,9 @@
   const TokenizedString query_terms(query);
 
   for (auto& app : apps_) {
-    if (!app->searchable())
+    if (!app->searchable()) {
       continue;
+    }
 
     TokenizedString* indexed_name = app->GetTokenizedIndexedName();
     TokenizedStringMatch match;
@@ -361,8 +365,9 @@
   const TokenizedString query_terms(query);
 
   for (auto& app : apps_) {
-    if (!app->searchable())
+    if (!app->searchable()) {
       continue;
+    }
 
     TokenizedString* indexed_name = app->GetTokenizedIndexedName();
     FuzzyTokenizedStringMatch match;
@@ -448,8 +453,9 @@
   if (update.Readiness() == apps::Readiness::kReady) {
     ScheduleRefresh();
   } else {
-    if (update.ReadinessChanged())
+    if (update.ReadinessChanged()) {
       Refresh();
+    }
   }
 }
 
@@ -459,8 +465,9 @@
 }
 
 void AppSearchDataSource::ScheduleRefresh() {
-  if (refresh_apps_factory_.HasWeakPtrs())
+  if (refresh_apps_factory_.HasWeakPtrs()) {
     return;
+  }
 
   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
       FROM_HERE, base::BindOnce(&AppSearchDataSource::Refresh,
diff --git a/chrome/browser/ash/app_list/search/ranking/best_match_ranker.cc b/chrome/browser/ash/app_list/search/ranking/best_match_ranker.cc
index a8a23bfc..bf40567 100644
--- a/chrome/browser/ash/app_list/search/ranking/best_match_ranker.cc
+++ b/chrome/browser/ash/app_list/search/ranking/best_match_ranker.cc
@@ -10,6 +10,7 @@
 #include "base/containers/flat_set.h"
 #include "chrome/browser/ash/app_list/search/chrome_search_result.h"
 #include "chrome/browser/ash/app_list/search/ranking/constants.h"
+#include "chrome/browser/ash/app_list/search/search_features.h"
 #include "chrome/browser/ash/app_list/search/types.h"
 
 namespace app_list {
@@ -125,7 +126,13 @@
       continue;
     }
     Scoring& scoring = result->scoring();
-    if (scoring.BestMatchScore() >= kBestMatchThreshold) {
+
+    double threshold = kBestMatchThreshold;
+    if (search_features::IsLauncherKeywordExtractionScoringEnabled()) {
+      threshold = kBestMatchThresholdWithKeywordRanking;
+    }
+
+    if (scoring.BestMatchScore() >= threshold) {
       best_matches_.push_back(result->GetWeakPtr());
     }
   }
diff --git a/chrome/browser/ash/app_list/search/ranking/constants.h b/chrome/browser/ash/app_list/search/ranking/constants.h
index 51905cb..52dd190e 100644
--- a/chrome/browser/ash/app_list/search/ranking/constants.h
+++ b/chrome/browser/ash/app_list/search/ranking/constants.h
@@ -22,6 +22,10 @@
 // The score threshold before we consider a result a best match.
 constexpr double kBestMatchThreshold = 0.8;
 
+// The score threshold used when there's keyword ranking.
+// This is given by tanh(2.65 * 0.8) where 0.8 is original best match threshold.
+constexpr double kBestMatchThresholdWithKeywordRanking = 0.97159407725;
+
 }  // namespace app_list
 
 #endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_CONSTANTS_H_
diff --git a/chrome/browser/ash/app_list/search/ranking/keyword_ranker.cc b/chrome/browser/ash/app_list/search/ranking/keyword_ranker.cc
index 978dc32..06bdb8a1 100644
--- a/chrome/browser/ash/app_list/search/ranking/keyword_ranker.cc
+++ b/chrome/browser/ash/app_list/search/ranking/keyword_ranker.cc
@@ -16,8 +16,7 @@
 void KeywordRanker::Start(const std::u16string& query,
                           ResultsMap& results,
                           CategoriesList& categories) {
-  // TODO(b/263059094): when the user start input, this function will
-  // be called.
+  // When the user start input, this function will be called.
   last_query_ = query;
 
   // Stores the providers that match with the keyword within the input query.
@@ -36,13 +35,10 @@
 
 void KeywordRanker::UpdateResultRanks(ResultsMap& results,
                                       ProviderType provider) {
-  // TODO(b/263059094): update the result by boost the scores that
-  // match certain keywords, the rest remain unchanged.
-
-  // Return if the given provider matched a keyword in the query
+  // Return if the given provider does not matched a keyword in the query
   // as this does not require modification of results.
   if (std::find(matched_providers_.begin(), matched_providers_.end(),
-                provider) != matched_providers_.end()) {
+                provider) == matched_providers_.end()) {
     return;
   }
 
@@ -52,7 +48,7 @@
   }
 
   for (auto& result : it->second) {
-    result->scoring().set_keyword_multiplier(0.9);
+    result->scoring().set_keyword_multiplier(1.2);
   }
 }
 
diff --git a/chrome/browser/ash/app_list/search/ranking/keyword_ranker_unittest.cc b/chrome/browser/ash/app_list/search/ranking/keyword_ranker_unittest.cc
index 84a6bbd8..a8d2966 100644
--- a/chrome/browser/ash/app_list/search/ranking/keyword_ranker_unittest.cc
+++ b/chrome/browser/ash/app_list/search/ranking/keyword_ranker_unittest.cc
@@ -53,7 +53,7 @@
 
   // As no detection of keywords for this result type,
   // therefore the keyword multiplier is down-weighted.
-  ExpectKeywordMultiplier(results_1, ResultType::kInstalledApp, 0.9);
+  ExpectKeywordMultiplier(results_1, ResultType::kInstalledApp, 1.0);
 }
 
 // Test the input query only match one provider.
@@ -78,8 +78,8 @@
   ASSERT_EQ(results_1[ResultType::kInstalledApp].size(), 2u);
   ASSERT_EQ(results_1[ResultType::kHelpApp].size(), 2u);
 
-  ExpectKeywordMultiplier(results_1, ResultType::kInstalledApp, 0.9);
-  ExpectKeywordMultiplier(results_1, ResultType::kHelpApp, 1.0);
+  ExpectKeywordMultiplier(results_1, ResultType::kInstalledApp, 1.0);
+  ExpectKeywordMultiplier(results_1, ResultType::kHelpApp, 1.2);
 }
 
 // Test the input query match multiple provider.
@@ -108,9 +108,9 @@
   ASSERT_EQ(results_1[ResultType::kFileSearch].size(), 2u);
   ASSERT_EQ(results_1[ResultType::kDriveSearch].size(), 2u);
 
-  ExpectKeywordMultiplier(results_1, ResultType::kInstalledApp, 0.9);
-  ExpectKeywordMultiplier(results_1, ResultType::kFileSearch, 1.0);
-  ExpectKeywordMultiplier(results_1, ResultType::kDriveSearch, 1.0);
+  ExpectKeywordMultiplier(results_1, ResultType::kInstalledApp, 1.0);
+  ExpectKeywordMultiplier(results_1, ResultType::kFileSearch, 1.2);
+  ExpectKeywordMultiplier(results_1, ResultType::kDriveSearch, 1.2);
 }
 
 }  // namespace app_list::test
diff --git a/chrome/browser/ash/app_list/search/scoring.cc b/chrome/browser/ash/app_list/search/scoring.cc
index 525ccba..cfc5f32 100644
--- a/chrome/browser/ash/app_list/search/scoring.cc
+++ b/chrome/browser/ash/app_list/search/scoring.cc
@@ -5,24 +5,41 @@
 #include "chrome/browser/ash/app_list/search/scoring.h"
 
 #include <algorithm>
+#include <cmath>
 
 #include "base/strings/stringprintf.h"
+#include "chrome/browser/ash/app_list/search/search_features.h"
 
 namespace app_list {
 
+namespace {
+
+// The expression of tanh ensures that the scores stay below 1
+// regardless of the constants and controls how quickly scores asymptote to 1.
+// The constant 2.65 is chosen so that the score of 1 will be converted to 0.99.
+constexpr double kKeywordScale = 2.65;
+
+}  // namespace
+
 double Scoring::FinalScore() const {
   if (filtered_ && !override_filter_for_test_) {
     return -1.0;
   }
-  return ftrl_result_score_ * keyword_multiplier_;
+  if (search_features::IsLauncherKeywordExtractionScoringEnabled()) {
+    return tanh(kKeywordScale * ftrl_result_score_ * keyword_multiplier_);
+  }
+  return ftrl_result_score_;
 }
 
 double Scoring::BestMatchScore() const {
   if (filtered_) {
     return -1.0;
   } else {
-    return std::max(mrfu_result_score_, normalized_relevance_) *
-           keyword_multiplier_;
+    double score = std::max(mrfu_result_score_, normalized_relevance_);
+    if (search_features::IsLauncherKeywordExtractionScoringEnabled()) {
+      return tanh(kKeywordScale * score * keyword_multiplier_);
+    }
+    return score;
   }
 }
 
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_service_launcher_unittest.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_service_launcher_unittest.cc
index e35676b..c7d40e5 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_service_launcher_unittest.cc
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_service_launcher_unittest.cc
@@ -309,9 +309,6 @@
 
   EXEC_AND_WAIT_FOR_CALL(launcher()->LaunchApp(), observer(), OnAppLaunched());
 
-  EXPECT_EQ(app_data()->status(), WebKioskAppData::Status::kInstalled);
-  EXPECT_EQ(app_data()->launch_url(), kAppLaunchUrl);
-
   // App isn't always ready by the time it's being launched. Therefore we check
   // the total count of kLaunchAppReadinessUMA instead of individual cases.
   histogram.ExpectTotalCount(KioskAppServiceLauncher::kLaunchAppReadinessUMA,
diff --git a/chrome/browser/ash/arc/keymaster/arc_keymaster_bridge.cc b/chrome/browser/ash/arc/keymaster/arc_keymaster_bridge.cc
index be43a81..06b9e78e2 100644
--- a/chrome/browser/ash/arc/keymaster/arc_keymaster_bridge.cc
+++ b/chrome/browser/ash/arc/keymaster/arc_keymaster_bridge.cc
@@ -13,7 +13,6 @@
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "base/process/process_handle.h"
-#include "chrome/services/keymaster/public/mojom/cert_store.mojom.h"
 #include "chromeos/ash/components/dbus/arc/arc_keymaster_client.h"
 #include "mojo/core/embedder/embedder.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chrome/browser/ash/arc/keymaster/arc_keymaster_bridge.h b/chrome/browser/ash/arc/keymaster/arc_keymaster_bridge.h
index faf148c..4193ab9 100644
--- a/chrome/browser/ash/arc/keymaster/arc_keymaster_bridge.h
+++ b/chrome/browser/ash/arc/keymaster/arc_keymaster_bridge.h
@@ -5,12 +5,10 @@
 #ifndef CHROME_BROWSER_ASH_ARC_KEYMASTER_ARC_KEYMASTER_BRIDGE_H_
 #define CHROME_BROWSER_ASH_ARC_KEYMASTER_ARC_KEYMASTER_BRIDGE_H_
 
-#include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "ash/components/arc/mojom/keymaster.mojom.h"
 #include "base/functional/callback_forward.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ash/arc/keymaster/cert_store_bridge.h"
-#include "chrome/services/keymaster/public/mojom/cert_store.mojom.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
@@ -18,6 +16,8 @@
 class BrowserContext;
 }  // namespace content
 
+class BrowserContextKeyedServiceFactory;
+
 namespace arc {
 
 class ArcBridgeService;
diff --git a/chrome/browser/ash/crosapi/local_printer_ash.cc b/chrome/browser/ash/crosapi/local_printer_ash.cc
index 4ad2970..8c8a2c2 100644
--- a/chrome/browser/ash/crosapi/local_printer_ash.cc
+++ b/chrome/browser/ash/crosapi/local_printer_ash.cc
@@ -18,7 +18,6 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/metrics/histogram_functions.h"
-#include "base/notreached.h"
 #include "base/values.h"
 #include "chrome/browser/ash/printing/cups_print_job.h"
 #include "chrome/browser/ash/printing/cups_print_job_manager.h"
@@ -26,6 +25,7 @@
 #include "chrome/browser/ash/printing/cups_printers_manager.h"
 #include "chrome/browser/ash/printing/cups_printers_manager_factory.h"
 #include "chrome/browser/ash/printing/history/print_job_info.pb.h"
+#include "chrome/browser/ash/printing/ipp_client_info_calculator.h"
 #include "chrome/browser/ash/printing/oauth2/authorization_zones_manager.h"
 #include "chrome/browser/ash/printing/oauth2/authorization_zones_manager_factory.h"
 #include "chrome/browser/ash/printing/oauth2/status_code.h"
@@ -46,6 +46,7 @@
 #include "chrome/common/pref_names.h"
 #include "chromeos/crosapi/mojom/local_printer.mojom.h"
 #include "chromeos/printing/ppd_provider.h"
+#include "chromeos/printing/printer_configuration.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
@@ -144,17 +145,41 @@
   }
 }
 
+bool IsActiveUserAffiliated() {
+  // TODO(b/265832837): Figure out if we can rely on `UserManager` always being
+  // initialized at this point. Currently it is initialized before
+  // `LocalPrinterAsh` so `UserManager::IsInitialized()` may be unnecessary.
+  // Also figure out if `GetActiveUser()` can return nullptr. This could happen
+  // if this function is called before login.
+  const user_manager::User* user =
+      user_manager::UserManager::IsInitialized()
+          ? user_manager::UserManager::Get()->GetActiveUser()
+          : nullptr;
+  return user ? user->IsAffiliated() : false;
+}
+
+bool IsManagedPrinter(const chromeos::Printer& printer) {
+  return printer.source() == chromeos::Printer::SRC_POLICY;
+}
+
+bool IsSecureIppPrinter(const chromeos::Printer& printer) {
+  return printer.GetProtocol() == chromeos::Printer::PrinterProtocol::kIpps ||
+         printer.GetProtocol() == chromeos::Printer::PrinterProtocol::kIppUsb;
+}
+
 }  // namespace
 
 LocalPrinterAsh::LocalPrinterAsh()
     : profile_manager_(g_browser_process->profile_manager()) {
-  if (profile_manager_)
+  if (profile_manager_) {
     profile_manager_->AddObserver(this);
+  }
 }
 
 LocalPrinterAsh::~LocalPrinterAsh() {
-  if (profile_manager_)
+  if (profile_manager_) {
     profile_manager_->RemoveObserver(this);
+  }
 }
 
 // static
@@ -185,8 +210,9 @@
   ptr->printer_id = status.GetPrinterId();
   ptr->timestamp = status.GetTimestamp();
   for (const auto& reason : status.GetStatusReasons()) {
-    if (reason.GetReason() == mojom::StatusReason::Reason::kNoError)
+    if (reason.GetReason() == mojom::StatusReason::Reason::kNoError) {
       continue;
+    }
     ptr->status_reasons.push_back(
         mojom::StatusReason::New(reason.GetReason(), reason.GetSeverity()));
   }
@@ -274,24 +300,29 @@
     LOG(WARNING) << "Ignoring invalid print job";
     return;
   }
-  for (auto& remote : print_job_remotes_)
+  for (auto& remote : print_job_remotes_) {
     remote->OnPrintJobUpdate(job->printer().id(), job->job_id(), status);
-  if (job->source() != mojom::PrintJob::Source::EXTENSION)
+  }
+  if (job->source() != mojom::PrintJob::Source::EXTENSION) {
     return;
-  for (auto& remote : extension_print_job_remotes_)
+  }
+  for (auto& remote : extension_print_job_remotes_) {
     remote->OnPrintJobUpdate(job->printer().id(), job->job_id(), status);
+  }
 }
 
 void LocalPrinterAsh::OnPrintServersChanged(
     const ash::PrintServersConfig& config) {
-  for (auto& remote : print_server_remotes_)
+  for (auto& remote : print_server_remotes_) {
     remote->OnPrintServersChanged(LocalPrinterAsh::ConfigToMojom(config));
+  }
 }
 
 void LocalPrinterAsh::OnServerPrintersChanged(
     const std::vector<ash::PrinterDetector::DetectedPrinter>&) {
-  for (auto& remote : print_server_remotes_)
+  for (auto& remote : print_server_remotes_) {
     remote->OnServerPrintersChanged();
+  }
 }
 
 void LocalPrinterAsh::GetPrinters(GetPrintersCallback callback) {
@@ -491,28 +522,34 @@
     }
   }
 
-  if (prefs->HasPrefPath(prefs::kPrintingAllowedColorModes))
+  if (prefs->HasPrefPath(prefs::kPrintingAllowedColorModes)) {
     policies->allowed_color_modes =
         prefs->GetInteger(prefs::kPrintingAllowedColorModes);
-  if (prefs->HasPrefPath(prefs::kPrintingAllowedDuplexModes))
+  }
+  if (prefs->HasPrefPath(prefs::kPrintingAllowedDuplexModes)) {
     policies->allowed_duplex_modes =
         prefs->GetInteger(prefs::kPrintingAllowedDuplexModes);
-  if (prefs->HasPrefPath(prefs::kPrintingAllowedPinModes))
+  }
+  if (prefs->HasPrefPath(prefs::kPrintingAllowedPinModes)) {
     policies->allowed_pin_modes =
         static_cast<printing::mojom::PinModeRestriction>(
             prefs->GetInteger(prefs::kPrintingAllowedPinModes));
-  if (prefs->HasPrefPath(prefs::kPrintingColorDefault))
+  }
+  if (prefs->HasPrefPath(prefs::kPrintingColorDefault)) {
     policies->default_color_mode =
         static_cast<printing::mojom::ColorModeRestriction>(
             prefs->GetInteger(prefs::kPrintingColorDefault));
-  if (prefs->HasPrefPath(prefs::kPrintingDuplexDefault))
+  }
+  if (prefs->HasPrefPath(prefs::kPrintingDuplexDefault)) {
     policies->default_duplex_mode =
         static_cast<printing::mojom::DuplexModeRestriction>(
             prefs->GetInteger(prefs::kPrintingDuplexDefault));
-  if (prefs->HasPrefPath(prefs::kPrintingPinDefault))
+  }
+  if (prefs->HasPrefPath(prefs::kPrintingPinDefault)) {
     policies->default_pin_mode =
         static_cast<printing::mojom::PinModeRestriction>(
             prefs->GetInteger(prefs::kPrintingPinDefault));
+  }
 
   if (prefs->HasPrefPath(prefs::kPrintPdfAsImageDefault)) {
     policies->default_print_pdf_as_image =
@@ -553,14 +590,15 @@
   for (const base::Value& deny_list_value : deny_list_from_prefs.GetList()) {
     const std::string& deny_list_str = deny_list_value.GetString();
     printing::mojom::PrinterType printer_type;
-    if (deny_list_str == "extension")
+    if (deny_list_str == "extension") {
       printer_type = printing::mojom::PrinterType::kExtension;
-    else if (deny_list_str == "pdf")
+    } else if (deny_list_str == "pdf") {
       printer_type = printing::mojom::PrinterType::kPdf;
-    else if (deny_list_str == "local")
+    } else if (deny_list_str == "local") {
       printer_type = printing::mojom::PrinterType::kLocal;
-    else
+    } else {
       continue;
+    }
 
     deny_list.push_back(printer_type);
   }
@@ -625,10 +663,33 @@
 
 void LocalPrinterAsh::GetIppClientInfo(const std::string& printer_id,
                                        GetIppClientInfoCallback callback) {
-  // TODO(ust): Return 2 client-info values: one with OS info and
-  // another one with admin-configured client-name field.
-  NOTIMPLEMENTED_LOG_ONCE();
-  std::move(callback).Run({});
+  if (!ash::features::IsIppClientInfoEnabled()) {
+    std::move(callback).Run({});
+    return;
+  }
+  Profile* profile = GetProfile();
+  DCHECK(profile);
+  ash::CupsPrintersManager* printers_manager =
+      ash::CupsPrintersManagerFactory::GetForBrowserContext(profile);
+  DCHECK(printers_manager);
+  absl::optional<chromeos::Printer> printer =
+      printers_manager->GetPrinter(printer_id);
+  if (!printer) {
+    std::move(callback).Run({});
+    return;
+  }
+  std::vector<printing::mojom::IppClientInfoPtr> result;
+  result.emplace_back(GetIppClientInfoCalculator()->GetOsInfo());
+  if (IsManagedPrinter(*printer) && IsSecureIppPrinter(*printer) &&
+      IsActiveUserAffiliated()) {
+    printing::mojom::IppClientInfoPtr device_info =
+        GetIppClientInfoCalculator()->GetDeviceInfo();
+    if (device_info) {
+      result.push_back(std::move(device_info));
+    }
+  }
+
+  std::move(callback).Run(std::move(result));
 }
 
 scoped_refptr<chromeos::PpdProvider> LocalPrinterAsh::CreatePpdProvider(
@@ -641,4 +702,13 @@
   return ash::PrinterConfigurer::Create(profile);
 }
 
+ash::printing::IppClientInfoCalculator*
+LocalPrinterAsh::GetIppClientInfoCalculator() {
+  if (!ipp_client_info_calculator_) {
+    ipp_client_info_calculator_ =
+        ash::printing::IppClientInfoCalculator::Create();
+  }
+  return ipp_client_info_calculator_.get();
+}
+
 }  // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/local_printer_ash.h b/chrome/browser/ash/crosapi/local_printer_ash.h
index 9df8fe0..2f86fea6 100644
--- a/chrome/browser/ash/crosapi/local_printer_ash.h
+++ b/chrome/browser/ash/crosapi/local_printer_ash.h
@@ -25,6 +25,10 @@
 namespace ash {
 class PrinterConfigurer;
 struct PrintServersConfig;
+
+namespace printing {
+class IppClientInfoCalculator;
+}
 }  // namespace ash
 
 namespace chromeos {
@@ -131,11 +135,15 @@
       Profile* profile);
   virtual std::unique_ptr<ash::PrinterConfigurer> CreatePrinterConfigurer(
       Profile* profile);
+  virtual ash::printing::IppClientInfoCalculator* GetIppClientInfoCalculator();
 
   ProfileManager* profile_manager_ = nullptr;
 
   bool observers_registered_ = false;
 
+  std::unique_ptr<ash::printing::IppClientInfoCalculator>
+      ipp_client_info_calculator_;
+
   // This class supports any number of connections. This allows the client to
   // have multiple, potentially thread-affine, remotes.
   mojo::ReceiverSet<mojom::LocalPrinter> receivers_;
diff --git a/chrome/browser/ash/crosapi/local_printer_ash_unittest.cc b/chrome/browser/ash/crosapi/local_printer_ash_unittest.cc
index 0495eaa..49797d6 100644
--- a/chrome/browser/ash/crosapi/local_printer_ash_unittest.cc
+++ b/chrome/browser/ash/crosapi/local_printer_ash_unittest.cc
@@ -22,6 +22,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/ash/crosapi/test_local_printer_ash.h"
 #include "chrome/browser/ash/printing/cups_printers_manager_factory.h"
+#include "chrome/browser/ash/printing/ipp_client_info_calculator.h"
 #include "chrome/browser/ash/printing/oauth2/authorization_zones_manager_factory.h"
 #include "chrome/browser/ash/printing/oauth2/mock_authorization_zones_manager.h"
 #include "chrome/browser/ash/printing/oauth2/status_code.h"
@@ -40,6 +41,8 @@
 #include "components/prefs/pref_service.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "components/user_manager/fake_user_manager.h"
+#include "components/user_manager/scoped_user_manager.h"
 #include "components/user_manager/user.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/test/browser_task_environment.h"
@@ -47,6 +50,8 @@
 #include "printing/backend/printing_restrictions.h"
 #include "printing/backend/test_print_backend.h"
 #include "printing/buildflags/buildflags.h"
+#include "printing/mojom/print.mojom-forward.h"
+#include "printing/mojom/print.mojom.h"
 #include "printing/printing_features.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -63,12 +68,19 @@
 
 using ::chromeos::Printer;
 using ::chromeos::PrinterClass;
+using testing::ByMove;
+using testing::NiceMock;
+using testing::Return;
 
 namespace printing {
 
 namespace {
 
 constexpr char kPrinterUri[] = "http://localhost:80";
+const AccountId kAffiliatedUserAccountId =
+    AccountId::FromUserEmail("user@example.com");
+const AccountId kUnaffiliatedUserAccountId =
+    AccountId::FromUserEmail("user@gmail.com");
 
 // Used as a callback to `GetPrinters()` in tests.
 // Records list returned by `GetPrinters()`.
@@ -96,6 +108,13 @@
   std::move(closure).Run();
 }
 
+void RecordIppClientInfo(std::vector<printing::mojom::IppClientInfoPtr>& out,
+                         base::OnceClosure closure,
+                         std::vector<printing::mojom::IppClientInfoPtr> param) {
+  out = std::move(param);
+  std::move(closure).Run();
+}
+
 Printer CreateTestPrinter(const std::string& id,
                           const std::string& name,
                           const std::string& description) {
@@ -1177,4 +1196,220 @@
   EXPECT_EQ(result->get_token()->token, "access_token");
 }
 
+// LocalPrinterAsh implementation that overrides `GetIppClientInfoCalculator()`
+// for testing.
+class TestLocalPrinterAshWithClientInfoCalculator : public TestLocalPrinterAsh {
+ public:
+  TestLocalPrinterAshWithClientInfoCalculator(
+      Profile* profile,
+      scoped_refptr<chromeos::PpdProvider> ppd_provider,
+      ash::printing::IppClientInfoCalculator* client_info_calculator)
+      : TestLocalPrinterAsh(profile, ppd_provider),
+        client_info_calculator_(client_info_calculator) {}
+  TestLocalPrinterAshWithClientInfoCalculator(
+      const TestLocalPrinterAshWithClientInfoCalculator&) = delete;
+  TestLocalPrinterAshWithClientInfoCalculator& operator=(
+      const TestLocalPrinterAshWithClientInfoCalculator&) = delete;
+  ~TestLocalPrinterAshWithClientInfoCalculator() override = default;
+
+  ash::printing::IppClientInfoCalculator* GetIppClientInfoCalculator()
+      override {
+    return client_info_calculator_;
+  }
+
+ private:
+  ash::printing::IppClientInfoCalculator* client_info_calculator_;
+};
+
+struct MockIppClientInfoCalculator : ash::printing::IppClientInfoCalculator {
+  MOCK_METHOD(printing::mojom::IppClientInfoPtr, GetOsInfo, (), (const));
+  MOCK_METHOD(printing::mojom::IppClientInfoPtr, GetDeviceInfo, (), (const));
+};
+
+//
+class LocalPrinterAshWithIppClientInfoTest : public LocalPrinterAshTest {
+ public:
+  LocalPrinterAshWithIppClientInfoTest() = default;
+  LocalPrinterAshWithIppClientInfoTest(
+      const LocalPrinterAshWithIppClientInfoTest&) = delete;
+  LocalPrinterAshWithIppClientInfoTest& operator=(
+      const LocalPrinterAshWithIppClientInfoTest&) = delete;
+  ~LocalPrinterAshWithIppClientInfoTest() override = default;
+
+  void SetUp() override {
+    user_manager_ = new user_manager::FakeUserManager();
+    scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>(
+        base::WrapUnique(user_manager_));
+    user_manager_->AddUserWithAffiliation(kAffiliatedUserAccountId,
+                                          /*is_affiliated*/ true);
+    user_manager_->AddUserWithAffiliation(kUnaffiliatedUserAccountId,
+                                          /*is_affiliated*/ false);
+    SetActiveUser(kUnaffiliatedUserAccountId);
+    ash::ProfileHelper::Get()->SetProfileToUserMappingForTesting(
+        &primary_user_);
+    auto ppd_provider = base::MakeRefCounted<FakePpdProvider>();
+    ash::CupsPrintersManagerFactory::GetInstance()->SetTestingFactoryAndUse(
+        &profile_,
+        base::BindLambdaForTesting([this](content::BrowserContext* context)
+                                       -> std::unique_ptr<KeyedService> {
+          auto printers_manager =
+              std::make_unique<ash::TestCupsPrintersManager>();
+          printers_manager_ = printers_manager.get();
+          return printers_manager;
+        }));
+    local_printer_ash_ =
+        std::make_unique<TestLocalPrinterAshWithClientInfoCalculator>(
+            &profile_, ppd_provider, &client_info_calculator_);
+  }
+
+  void SetActiveUser(AccountId account_id) {
+    user_manager_->SwitchActiveUser(account_id);
+  }
+
+ protected:
+  ash::TestCupsPrintersManager& printers_manager() {
+    DCHECK(printers_manager_);
+    return *printers_manager_;
+  }
+
+  crosapi::LocalPrinterAsh* local_printer_ash() {
+    return local_printer_ash_.get();
+  }
+
+  MockIppClientInfoCalculator& client_info_calculator() {
+    return client_info_calculator_;
+  }
+
+ private:
+  user_manager::FakeUserManager* user_manager_;
+  std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_;
+  // Must outlive `printers_manager_`.
+  TestingProfile profile_;
+  FakeUser primary_user_;
+  ash::TestCupsPrintersManager* printers_manager_ = nullptr;
+  NiceMock<MockIppClientInfoCalculator> client_info_calculator_;
+  std::unique_ptr<crosapi::LocalPrinterAsh> local_printer_ash_;
+};
+
+// Checks that `GetIppClientInfo()` returns an empty result if called with a
+// `printer_id` that has no associated printer.
+TEST_F(LocalPrinterAshWithIppClientInfoTest, GetIppClientInfoMissingPrinter) {
+  std::vector<printing::mojom::IppClientInfoPtr> result;
+  base::RunLoop loop;
+  local_printer_ash()->GetIppClientInfo(
+      "id", base::BindOnce(&RecordIppClientInfo, std::ref(result),
+                           loop.QuitClosure()));
+  loop.Run();
+
+  ASSERT_TRUE(result.empty());
+}
+
+// Checks that `GetIppClientInfo()` returns only OS info for a printer that uses
+// an insecure protocol.
+TEST_F(LocalPrinterAshWithIppClientInfoTest, GetIppClientInfoInsecurePrinter) {
+  SetActiveUser(kAffiliatedUserAccountId);
+  Printer printer = CreateTestPrinter("id", "name", "description");
+  printer.SetUri("ipp://localhost");
+  printer.set_source(Printer::Source::SRC_POLICY);
+  printers_manager().AddPrinter(printer, PrinterClass::kSaved);
+
+  std::vector<printing::mojom::IppClientInfoPtr> result;
+  base::RunLoop loop;
+  const mojom::IppClientInfoPtr expected = mojom::IppClientInfo::New(
+      mojom::IppClientInfo::ClientType::kOperatingSystem, "ChromeOS",
+      absl::nullopt, "1.2.3", absl::nullopt);
+  EXPECT_CALL(client_info_calculator(), GetOsInfo)
+      .WillOnce(Return(ByMove(expected.Clone())));
+  local_printer_ash()->GetIppClientInfo(
+      "id", base::BindOnce(&RecordIppClientInfo, std::ref(result),
+                           loop.QuitClosure()));
+  loop.Run();
+
+  ASSERT_EQ(result.size(), 1u);
+  EXPECT_EQ(result[0], expected);
+}
+
+// Checks that `GetIppClientInfo()` returns only OS info if the current user is
+// unaffiliated.
+TEST_F(LocalPrinterAshWithIppClientInfoTest, GetIppClientInfoUnaffiliatedUser) {
+  SetActiveUser(kUnaffiliatedUserAccountId);
+  Printer printer = CreateTestPrinter("id", "name", "description");
+  printer.SetUri("ipps://localhost");
+  printer.set_source(Printer::Source::SRC_POLICY);
+  printers_manager().AddPrinter(printer, PrinterClass::kSaved);
+
+  std::vector<printing::mojom::IppClientInfoPtr> result;
+  base::RunLoop loop;
+  const mojom::IppClientInfoPtr expected = mojom::IppClientInfo::New(
+      mojom::IppClientInfo::ClientType::kOperatingSystem, "ChromeOS",
+      absl::nullopt, "1.2.3", absl::nullopt);
+  EXPECT_CALL(client_info_calculator(), GetOsInfo)
+      .WillOnce(Return(ByMove(expected.Clone())));
+  local_printer_ash()->GetIppClientInfo(
+      "id", base::BindOnce(&RecordIppClientInfo, std::ref(result),
+                           loop.QuitClosure()));
+  loop.Run();
+
+  ASSERT_EQ(result.size(), 1u);
+  EXPECT_EQ(result[0], expected);
+}
+
+// Checks that `GetIppClientInfo()` returns only OS info for an unmanaged
+// printer.
+TEST_F(LocalPrinterAshWithIppClientInfoTest, GetIppClientInfoUnmanagedPrinter) {
+  SetActiveUser(kAffiliatedUserAccountId);
+  Printer printer = CreateTestPrinter("id", "name", "description");
+  printer.SetUri("ipps://localhost");
+  printer.set_source(Printer::Source::SRC_USER_PREFS);
+  printers_manager().AddPrinter(printer, PrinterClass::kSaved);
+
+  std::vector<printing::mojom::IppClientInfoPtr> result;
+  base::RunLoop loop;
+  const mojom::IppClientInfoPtr expected = mojom::IppClientInfo::New(
+      mojom::IppClientInfo::ClientType::kOperatingSystem, "ChromeOS",
+      absl::nullopt, "1.2.3", absl::nullopt);
+  EXPECT_CALL(client_info_calculator(), GetOsInfo)
+      .WillOnce(Return(ByMove(expected.Clone())));
+  local_printer_ash()->GetIppClientInfo(
+      "id", base::BindOnce(&RecordIppClientInfo, std::ref(result),
+                           loop.QuitClosure()));
+  loop.Run();
+
+  ASSERT_EQ(result.size(), 1u);
+  EXPECT_EQ(result[0], expected);
+}
+
+// Checks that `GetIppClientInfo()` returns both OS info and device info for a
+// managed printer that uses a secure protocol if the current user is
+// affiliated.
+TEST_F(LocalPrinterAshWithIppClientInfoTest,
+       GetIppClientInfoSecureManagedPrinterAffiliatedUser) {
+  SetActiveUser(kAffiliatedUserAccountId);
+  Printer printer = CreateTestPrinter("id", "name", "description");
+  printer.SetUri("ipps://localhost");
+  printer.set_source(Printer::Source::SRC_POLICY);
+  printers_manager().AddPrinter(printer, PrinterClass::kSaved);
+
+  std::vector<printing::mojom::IppClientInfoPtr> result;
+  base::RunLoop loop;
+  const mojom::IppClientInfo expected_os_info =
+      mojom::IppClientInfo(mojom::IppClientInfo::ClientType::kOperatingSystem,
+                           "ChromeOS", absl::nullopt, "1.2.3", absl::nullopt);
+  const mojom::IppClientInfo expected_device_info =
+      mojom::IppClientInfo(mojom::IppClientInfo::ClientType::kOther, "abc",
+                           absl::nullopt, "", absl::nullopt);
+  EXPECT_CALL(client_info_calculator(), GetOsInfo)
+      .WillOnce(Return(ByMove(expected_os_info.Clone())));
+  EXPECT_CALL(client_info_calculator(), GetDeviceInfo)
+      .WillOnce(Return(ByMove(expected_device_info.Clone())));
+  local_printer_ash()->GetIppClientInfo(
+      "id", base::BindOnce(&RecordIppClientInfo, std::ref(result),
+                           loop.QuitClosure()));
+  loop.Run();
+
+  EXPECT_THAT(result, testing::UnorderedElementsAre(
+                          testing::Pointee(expected_os_info),
+                          testing::Pointee(expected_device_info)));
+}
+
 }  // namespace printing
diff --git a/chrome/browser/ash/net/secure_dns_manager.cc b/chrome/browser/ash/net/secure_dns_manager.cc
index 2b831d7e..7b0e155 100644
--- a/chrome/browser/ash/net/secure_dns_manager.cc
+++ b/chrome/browser/ash/net/secure_dns_manager.cc
@@ -101,7 +101,7 @@
   const bool want_all = doh_providers.DictEmpty();
   for (const auto& provider : local_doh_providers_) {
     const std::string& server_template = provider.first.server_template();
-    if (want_all || doh_providers.FindKey(server_template)) {
+    if (want_all || doh_providers.GetDict().contains(server_template)) {
       doh_providers.SetKey(server_template, base::Value(provider.second));
     }
   }
diff --git a/chrome/browser/ash/printing/ipp_client_info_calculator.cc b/chrome/browser/ash/printing/ipp_client_info_calculator.cc
new file mode 100644
index 0000000..24c6ba2
--- /dev/null
+++ b/chrome/browser/ash/printing/ipp_client_info_calculator.cc
@@ -0,0 +1,147 @@
+// 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 "chrome/browser/ash/printing/ipp_client_info_calculator.h"
+
+#include <cstdint>
+#include <memory>
+
+#include "base/check.h"
+#include "base/functional/bind.h"
+#include "base/memory/raw_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "base/system/sys_info.h"
+#include "chrome/browser/ash/policy/core/device_attributes.h"
+#include "chrome/browser/ash/policy/core/device_attributes_impl.h"
+#include "chrome/browser/ash/settings/cros_settings.h"
+#include "chromeos/ash/components/settings/cros_settings_names.h"
+#include "components/version_info/version_info.h"
+#include "printing/mojom/print.mojom.h"
+
+namespace ash::printing {
+
+namespace {
+
+using ::printing::mojom::IppClientInfo;
+using ::printing::mojom::IppClientInfoPtr;
+
+constexpr char kOsInfoClientName[] = "ChromeOS";
+constexpr char kDeviceDirectoryApiIdPlaceholder[] =
+    "${DEVICE_DIRECTORY_API_ID}";
+constexpr char kDeviceSerialNumberPlaceholder[] = "${DEVICE_SERIAL_NUMBER}";
+constexpr char kDeviceAssetIdPlaceholder[] = "${DEVICE_ASSET_ID}";
+constexpr char kDeviceAnnotatedLocationPlaceholder[] =
+    "${DEVICE_ANNOTATED_LOCATION}";
+
+// Replace device variables found in `str` with the provided values.
+std::string ReplaceDeviceVariables(std::string template_with_vars,
+                                   base::StringPiece api_id,
+                                   base::StringPiece serial,
+                                   base::StringPiece asset_id,
+                                   base::StringPiece location) {
+  base::ReplaceSubstringsAfterOffset(&template_with_vars, 0,
+                                     kDeviceDirectoryApiIdPlaceholder, api_id);
+  base::ReplaceSubstringsAfterOffset(&template_with_vars, 0,
+                                     kDeviceSerialNumberPlaceholder, serial);
+  base::ReplaceSubstringsAfterOffset(&template_with_vars, 0,
+                                     kDeviceAssetIdPlaceholder, asset_id);
+  base::ReplaceSubstringsAfterOffset(
+      &template_with_vars, 0, kDeviceAnnotatedLocationPlaceholder, location);
+  return template_with_vars;
+}
+
+class IppClientInfoCalculatorImpl : public IppClientInfoCalculator {
+ public:
+  IppClientInfoCalculatorImpl(
+      std::unique_ptr<policy::DeviceAttributes> device_attributes,
+      const std::string& chrome_milestone)
+      : cros_settings_(CrosSettings::Get()),
+        device_attributes_(std::move(device_attributes)) {
+    // Calculate the initial client-info values. The admin-configured
+    // `client-info` value with device information can change later if the
+    // `kDevicePrintingClientNameTemplate` setting changes.
+    CalculateClientInfoWithDeviceValues();
+    CalculateClientInfoWithOSVersion(chrome_milestone);
+
+    // Recalculate `client-info` with device information when
+    // `kDevicePrintingClientNameTemplate` setting changes.
+    // base::Unretained(this) is safe here because the subscription is scoped to
+    // the lifetime of `this` already.
+    auto callback = base::BindRepeating(
+        &IppClientInfoCalculatorImpl::CalculateClientInfoWithDeviceValues,
+        base::Unretained(this));
+    client_name_template_subscription_ =
+        CrosSettings::Get()->AddSettingsObserver(
+            kDevicePrintingClientNameTemplate, std::move(callback));
+  }
+
+ private:
+  IppClientInfoPtr GetOsInfo() const override {
+    DCHECK(os_info_);
+    return os_info_.Clone();
+  }
+
+  IppClientInfoPtr GetDeviceInfo() const override {
+    return device_info_.Clone();
+  }
+
+  void CalculateClientInfoWithDeviceValues() {
+    std::string client_name_template = GetClientNameTemplateFromCrosSettings();
+    if (client_name_template.empty()) {
+      return;
+    }
+    std::string serial = device_attributes_->GetDeviceSerialNumber();
+    std::string asset_id = device_attributes_->GetDeviceAssetID();
+    std::string location = device_attributes_->GetDeviceAnnotatedLocation();
+    std::string directory_api_id = device_attributes_->GetDirectoryApiID();
+    std::string client_name =
+        ReplaceDeviceVariables(std::move(client_name_template),
+                               directory_api_id, serial, asset_id, location);
+    device_info_ = IppClientInfo::New(IppClientInfo::ClientType::kOther,
+                                      std::move(client_name),
+                                      /*client_patches=*/absl::nullopt,
+                                      /*client_string_version=*/std::string(),
+                                      /*client_version=*/absl::nullopt);
+  }
+
+  void CalculateClientInfoWithOSVersion(const std::string& chrome_milestone) {
+    DCHECK(base::SysInfo::IsRunningOnChromeOS());
+    os_info_ = IppClientInfo::New(
+        IppClientInfo::ClientType::kOperatingSystem, kOsInfoClientName,
+        base::SysInfo::OperatingSystemVersion(), chrome_milestone,
+        /*client_version=*/absl::nullopt);
+  }
+
+  std::string GetClientNameTemplateFromCrosSettings() {
+    std::string client_name_template;
+    cros_settings_->GetString(kDevicePrintingClientNameTemplate,
+                              &client_name_template);
+    return client_name_template;
+  }
+
+  raw_ptr<const CrosSettings> cros_settings_;
+  std::unique_ptr<policy::DeviceAttributes> device_attributes_;
+  IppClientInfoPtr device_info_;
+  IppClientInfoPtr os_info_;
+  base::CallbackListSubscription client_name_template_subscription_;
+};
+
+}  // namespace
+
+std::unique_ptr<IppClientInfoCalculator> IppClientInfoCalculator::Create() {
+  return std::make_unique<IppClientInfoCalculatorImpl>(
+      std::make_unique<policy::DeviceAttributesImpl>(),
+      version_info::GetMajorVersionNumber());
+}
+
+std::unique_ptr<IppClientInfoCalculator>
+IppClientInfoCalculator::CreateForTesting(
+    std::unique_ptr<policy::DeviceAttributes> device_attributes,
+    const std::string& chrome_milestone) {
+  return std::make_unique<IppClientInfoCalculatorImpl>(
+      std::move(device_attributes), chrome_milestone);
+}
+
+}  // namespace ash::printing
diff --git a/chrome/browser/ash/printing/ipp_client_info_calculator.h b/chrome/browser/ash/printing/ipp_client_info_calculator.h
new file mode 100644
index 0000000..d0bb526
--- /dev/null
+++ b/chrome/browser/ash/printing/ipp_client_info_calculator.h
@@ -0,0 +1,45 @@
+// 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 CHROME_BROWSER_ASH_PRINTING_IPP_CLIENT_INFO_CALCULATOR_H_
+#define CHROME_BROWSER_ASH_PRINTING_IPP_CLIENT_INFO_CALCULATOR_H_
+
+#include <memory>
+#include <string>
+
+#include "printing/mojom/print.mojom-forward.h"
+
+namespace policy {
+class DeviceAttributes;
+}
+
+namespace ash::printing {
+
+// Calculates and keeps track of `client-info` values that could be sent to IPP
+// printers to identify the print job origin.
+class IppClientInfoCalculator {
+ public:
+  IppClientInfoCalculator() = default;
+  virtual ~IppClientInfoCalculator() = default;
+
+  // Returns an IPP `client-info` value containing OS version information.
+  // Cannot be `nullptr`.
+  virtual ::printing::mojom::IppClientInfoPtr GetOsInfo() const = 0;
+
+  // Returns an IPP `client-info` value corresponding to the current value of
+  // the `kDevicePrintingClientNameTemplate` policy. Returns `nullptr` if
+  // the policy is not set.
+  virtual ::printing::mojom::IppClientInfoPtr GetDeviceInfo() const = 0;
+
+  static std::unique_ptr<IppClientInfoCalculator> Create();
+
+  // Factory function that allows injected dependencies, for testing.
+  static std::unique_ptr<IppClientInfoCalculator> CreateForTesting(
+      std::unique_ptr<policy::DeviceAttributes> device_attributes,
+      const std::string& chrome_milestone);
+};
+
+}  // namespace ash::printing
+
+#endif  // CHROME_BROWSER_ASH_PRINTING_IPP_CLIENT_INFO_CALCULATOR_H_
diff --git a/chrome/browser/ash/printing/ipp_client_info_calculator_unittest.cc b/chrome/browser/ash/printing/ipp_client_info_calculator_unittest.cc
new file mode 100644
index 0000000..9cd76ef
--- /dev/null
+++ b/chrome/browser/ash/printing/ipp_client_info_calculator_unittest.cc
@@ -0,0 +1,142 @@
+// 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 "chrome/browser/ash/printing/ipp_client_info_calculator.h"
+
+#include <memory>
+
+#include "base/strings/string_piece.h"
+#include "base/test/scoped_chromeos_version_info.h"
+#include "base/time/time.h"
+#include "chrome/browser/ash/policy/core/device_attributes_fake.h"
+#include "chrome/browser/ash/settings/scoped_testing_cros_settings.h"
+#include "chrome/browser/ash/settings/stub_cros_settings_provider.h"
+#include "chromeos/ash/components/settings/cros_settings_names.h"
+#include "printing/mojom/print.mojom-forward.h"
+#include "printing/mojom/print.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ash::printing {
+
+namespace {
+
+using ::printing::mojom::IppClientInfo;
+using ::printing::mojom::IppClientInfoPtr;
+
+constexpr char kLsbRelease[] =
+    "CHROMEOS_RELEASE_NAME=Chrome OS\n"
+    "CHROMEOS_RELEASE_VERSION=15183.69.3\n";
+
+void ExpectClientInfoEqual(const IppClientInfo& lhs, const IppClientInfo& rhs) {
+  EXPECT_EQ(lhs.client_name, rhs.client_name);
+  EXPECT_EQ(lhs.client_type, rhs.client_type);
+  EXPECT_EQ(lhs.client_patches, rhs.client_patches);
+  EXPECT_EQ(lhs.client_string_version, rhs.client_string_version);
+  EXPECT_EQ(lhs.client_version, rhs.client_version);
+}
+
+// Test fixture to test `IppClientInfoCalculator` with fake ChromeOS version,
+// device attributes and `DevicePrintingClientNameTemplate` policy.
+class IppClientInfoCalculatorTest : public testing::Test {
+ public:
+  IppClientInfoCalculatorTest() {
+    auto fake_device_attibutes =
+        std::make_unique<policy::FakeDeviceAttributes>();
+    device_attributes_ = fake_device_attibutes.get();
+    client_info_calculator_ = IppClientInfoCalculator::CreateForTesting(
+        std::move(fake_device_attibutes), "42");
+  }
+
+  void SetClientNameTemplatePolicy(base::StringPiece value) {
+    testing_cros_settings_.device_settings()->Set(
+        kDevicePrintingClientNameTemplate, base::Value(value));
+  }
+
+  policy::FakeDeviceAttributes* DeviceAttributes() {
+    return device_attributes_;
+  }
+
+  IppClientInfoPtr GetOsInfo() const {
+    return client_info_calculator_->GetOsInfo();
+  }
+
+  IppClientInfoPtr GetDeviceInfo() const {
+    return client_info_calculator_->GetDeviceInfo();
+  }
+
+ private:
+  base::test::ScopedChromeOSVersionInfo cros_version_info_{kLsbRelease,
+                                                           base::Time()};
+  ScopedTestingCrosSettings testing_cros_settings_;
+  policy::FakeDeviceAttributes* device_attributes_;
+  std::unique_ptr<IppClientInfoCalculator> client_info_calculator_;
+};
+
+TEST_F(IppClientInfoCalculatorTest, OsInfo) {
+  const IppClientInfoPtr os_info = GetOsInfo();
+  const IppClientInfo expected(IppClientInfo::ClientType::kOperatingSystem,
+                               "ChromeOS", "15183.69.3", "42", absl::nullopt);
+  ASSERT_TRUE(os_info);
+  ExpectClientInfoEqual(*os_info, expected);
+}
+
+TEST_F(IppClientInfoCalculatorTest, DeviceInfoUnsetPolicy) {
+  const IppClientInfoPtr device_info = GetDeviceInfo();
+  ASSERT_FALSE(device_info);
+}
+
+TEST_F(IppClientInfoCalculatorTest, DeviceInfoSimplePolicy) {
+  SetClientNameTemplatePolicy("chromebook");
+
+  const IppClientInfoPtr device_info = GetDeviceInfo();
+  const IppClientInfo expected(IppClientInfo::ClientType::kOther, "chromebook",
+                               absl::nullopt, "", absl::nullopt);
+  ASSERT_TRUE(device_info);
+  ExpectClientInfoEqual(*device_info, expected);
+}
+
+TEST_F(IppClientInfoCalculatorTest, DeviceInfoPolicyWithVariables) {
+  DeviceAttributes()->SetFakeDeviceAssetId("asset-id");
+  DeviceAttributes()->SetFakeDirectoryApiId("1234-abcd");
+  DeviceAttributes()->SetFakeDeviceSerialNumber("serial");
+  DeviceAttributes()->SetFakeDeviceAnnotatedLocation("location");
+  SetClientNameTemplatePolicy(
+      "chromebook_${DEVICE_ASSET_ID}_${DEVICE_DIRECTORY_API_ID}_${DEVICE_"
+      "SERIAL_NUMBER}_${DEVICE_ANNOTATED_LOCATION}");
+
+  const IppClientInfoPtr device_info = GetDeviceInfo();
+  const IppClientInfo expected(IppClientInfo::ClientType::kOther,
+                               "chromebook_asset-id_1234-abcd_serial_location",
+                               absl::nullopt, "", absl::nullopt);
+  ASSERT_TRUE(device_info);
+  ExpectClientInfoEqual(*device_info, expected);
+}
+
+TEST_F(IppClientInfoCalculatorTest, DeviceInfoPolicyChange) {
+  {
+    const IppClientInfoPtr device_info = GetDeviceInfo();
+    ASSERT_FALSE(device_info);
+  }
+  {
+    SetClientNameTemplatePolicy("initial");
+    const IppClientInfoPtr device_info = GetDeviceInfo();
+    const IppClientInfo expected(IppClientInfo::ClientType::kOther, "initial",
+                                 absl::nullopt, "", absl::nullopt);
+    ASSERT_TRUE(device_info);
+    ExpectClientInfoEqual(*device_info, expected);
+  }
+
+  {
+    SetClientNameTemplatePolicy("changed");
+    const IppClientInfoPtr device_info = GetDeviceInfo();
+    const IppClientInfo expected(IppClientInfo::ClientType::kOther, "changed",
+                                 absl::nullopt, "", absl::nullopt);
+    ASSERT_TRUE(device_info);
+    ExpectClientInfoEqual(*device_info, expected);
+  }
+}
+
+}  // namespace
+
+}  // namespace ash::printing
diff --git a/chrome/browser/ash/startup_settings_cache.cc b/chrome/browser/ash/startup_settings_cache.cc
index e84d54e4..b7a4ca7 100644
--- a/chrome/browser/ash/startup_settings_cache.cc
+++ b/chrome/browser/ash/startup_settings_cache.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ash/startup_settings_cache.h"
 
+#include <string>
+
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/json/json_reader.h"
@@ -46,14 +48,11 @@
   if (!settings.has_value())
     return std::string();
 
-  base::Value* app_locale_setting = settings->FindKey(kAppLocaleKey);
-  if (!app_locale_setting)
-    return std::string();
-
+  const std::string* app_locale_setting =
+      settings->GetDict().FindString(kAppLocaleKey);
   // The locale is already an "actual locale", so this does not need to call
   // language::ConvertToActualUILocale().
-  return app_locale_setting->is_string() ? app_locale_setting->GetString()
-                                         : std::string();
+  return app_locale_setting ? *app_locale_setting : std::string();
 }
 
 void WriteAppLocale(std::string app_locale) {
diff --git a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java
index e120bc0..5c82c55d 100644
--- a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java
+++ b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java
@@ -79,6 +79,13 @@
     }
 
     /**
+     * @return True if the back gesture refactor is enabled for secondary activities.
+     */
+    public static boolean isSecondaryActivityEnabled() {
+        return ChromeFeatureList.sBackGestureRefactorActivityAndroid.isEnabled();
+    }
+
+    /**
      * Record when the back press is consumed by a certain feature.
      * @param type The {@link Type} which consumes the back press event.
      */
diff --git a/chrome/browser/creator/android/creator_api_bridge.cc b/chrome/browser/creator/android/creator_api_bridge.cc
index c48150e..1793738b 100644
--- a/chrome/browser/creator/android/creator_api_bridge.cc
+++ b/chrome/browser/creator/android/creator_api_bridge.cc
@@ -17,6 +17,8 @@
 #include "components/creator/public/creator_api.h"
 #include "url/android/gurl_android.h"
 
+using base::android::ConvertUTF8ToJavaString;
+
 namespace creator {
 
 namespace {
@@ -34,6 +36,12 @@
   std::move(callback).Run(Creator{u"alexainsley.com", u"Alex Ainsley"});
 }
 
+// TODO(crbug/1374058): Replace this with actual access to creator api stub.
+void DoGetWebId(std::string url,
+                base::OnceCallback<void(std::string)> callback) {
+  std::move(callback).Run(std::string("wId/12345"));
+}
+
 }  // namespace
 
 static void JNI_CreatorApiBridge_GetCreator(
@@ -51,4 +59,19 @@
                    base::android::ScopedJavaGlobalRef(j_callback)));
 }
 
+static void JNI_CreatorApiBridge_GetWebId(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jstring>& j_url,
+    const base::android::JavaParamRef<jobject>& j_callback) {
+  DoGetWebId(base::android::ConvertJavaStringToUTF8(env, j_url),
+             base::BindOnce(
+                 [](const base::android::JavaRef<jobject>& j_callback,
+                    std::string webid) {
+                   JNIEnv* env = base::android::AttachCurrentThread();
+                   base::android::RunObjectCallbackAndroid(
+                       j_callback, ConvertUTF8ToJavaString(env, webid));
+                 },
+                 base::android::ScopedJavaGlobalRef(j_callback)));
+}
+
 }  // namespace creator
diff --git a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorApiBridge.java b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorApiBridge.java
index 4ade1d6..3f8f2a9 100644
--- a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorApiBridge.java
+++ b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorApiBridge.java
@@ -14,6 +14,9 @@
  */
 @JNINamespace("creator")
 public class CreatorApiBridge {
+    /**
+     * A Java Class to store creator metadata.
+     */
     public static class Creator {
         public final String url;
         public final String title;
@@ -29,8 +32,13 @@
         CreatorApiBridgeJni.get().getCreator(webChannelId, callback);
     }
 
+    public static void getWebId(String url, Callback<String> callback) {
+        CreatorApiBridgeJni.get().getWebId(url, callback);
+    }
+
     @NativeMethods
     interface Natives {
         void getCreator(String webChannelId, Callback<Creator> callback);
+        void getWebId(String url, Callback<String> callback);
     }
 }
diff --git a/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc b/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc
index a2b8fe0..4978e29 100644
--- a/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc
+++ b/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc
@@ -1354,7 +1354,7 @@
 
   std::vector<std::pair<base::Time, std::string>> entries;
   entries.reserve(value.DictSize());
-  for (auto entry : value.DictItems()) {
+  for (auto entry : value.GetDict()) {
     // Don't evict the default ID.
     if (entry.first == kDefaultLastPickedDirectoryKey)
       continue;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index faf05d0..5e8b07c8 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -661,6 +661,11 @@
     "expiry_milestone": 110
   },
   {
+    "name": "back-gesture-refactor-activity-android",
+    "owners": ["lazzzis@google.com", "jinsukkim", "twellington"],
+    "expiry_milestone": 118
+  },
+  {
     "name": "back-gesture-refactor-android",
     "owners": ["lazzzis@google.com", "jinsukkim", "twellington"],
     "expiry_milestone": 115
@@ -1097,7 +1102,7 @@
   {
     "name": "content-languages-in-language-picker",
     "owners": [ "sclittle", "basiaz@google.com", "chrome-language@google.com" ],
-    "expiry_milestone": 110
+    "expiry_milestone": 114
   },
   {
     "name": "content-suggestions-ui-module-refresh",
@@ -1570,11 +1575,6 @@
     "expiry_milestone": 98
   },
   {
-    "name": "drive-fs-bidirectional-native-messaging",
-    "owners": [ "austinct@chromium.org", "simmonsjosh@google.com" ],
-    "expiry_milestone": 108
-  },
-  {
     "name": "drive-fs-chrome-networking",
     "owners": [ "travislane@google.com" ],
     "expiry_milestone": 112
@@ -3615,6 +3615,11 @@
     "expiry_milestone": 112
   },
   {
+    "name": "fast-pair-handshake-refactor",
+    "owners": [ "//ash/quick_pair/OWNERS", "akingsb@google.com" ],
+    "expiry_milestone": 112
+  },
+  {
     "name": "fast-pair-low-power",
     "owners": [
       "//ash/quick_pair/OWNERS",
@@ -6737,7 +6742,7 @@
   {
     "name": "translate-message-ui",
     "owners": [ "sclittle", "chrome-language@google.com" ],
-    "expiry_milestone": 112
+    "expiry_milestone": 114
   },
   {
     "name": "trending-queries-module",
@@ -7145,13 +7150,6 @@
     "expiry_milestone": 113
   },
   {
-    "name": "webauthn-new-desktop-ui",
-    "owners": [
-      "chrome-webauthn@google.com"
-    ],
-    "expiry_milestone": 110
-  },
-  {
     "name": "webnotes-dynamic-templates",
     "owners": ["chrome-creation@google.com"],
     "expiry_milestone": 103
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index fe0648a..11fa563 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3232,10 +3232,6 @@
     "requested using the Payment Request API. This flag removes the "
     "restriction that the TWA has to be installed from the app-store.";
 
-const char kWebAuthnNewDesktopUIName[] = "Web Authentication new desktop UI";
-const char kWebAuthnNewDesktopUIDescription[] =
-    "Enable updated UI dialog for WebAuthn requests.";
-
 const char kWebrtcHideLocalIpsWithMdnsName[] =
     "Anonymize local IPs exposed by WebRTC.";
 const char kWebrtcHideLocalIpsWithMdnsDecription[] =
@@ -3465,6 +3461,12 @@
     "When enabled, app menu should show 'Mobile site' when showing desktop "
     "site, instead of showing 'Desktop Site' with checkbox";
 
+const char kBackGestureRefactorActivityAndroidName[] =
+    "Back Gesture Refactor (Secondary Activities)";
+const char kBackGestureRefactorActivityAndroidDescription[] =
+    "Enable Back Gesture Refactor for Secondary Activities to support in-app "
+    "activity-to-activity predictive back gestures";
+
 const char kBackGestureRefactorAndroidName[] = "Back Gesture Refactor";
 const char kBackGestureRefactorAndroidDescription[] =
     "Enable Back Gesture Refactor.";
@@ -5024,6 +5026,11 @@
     "Enables Google Fast Pair service which uses BLE to discover supported "
     "nearby Bluetooth devices and surfaces a notification for quick pairing.";
 
+const char kFastPairHandshakeRefactorName[] =
+    "Enable Fast Pair Handshake Refactor";
+const char kFastPairHandshakeRefactorDescription[] =
+    "Enables refactored handshake logic for Google Fast Pair service.";
+
 const char kFastPairLowPowerName[] = "Enable Fast Pair Low Power mode";
 const char kFastPairLowPowerDescription[] =
     "Enables Fast Pair Low Power mode, which doesn't scan for devices "
@@ -5067,11 +5074,6 @@
     "permissions in the quick settings menu. Website notification permissions "
     "settings will be migrated to the lacros - chrome browser.";
 
-const char kDriveFsBidirectionalNativeMessagingName[] =
-    "Enable bidirectional native messaging for DriveFS";
-const char kDriveFsBidirectionalNativeMessagingDescription[] =
-    "Enable enhanced native messaging host to communicate with DriveFS.";
-
 const char kDriveFsChromeNetworkingName[] =
     "Enable the DriveFS / Chrome Network Service bridge";
 const char kDriveFsChromeNetworkingDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index cadae42..7dc87b99 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1840,9 +1840,6 @@
 extern const char kAppStoreBillingDebugName[];
 extern const char kAppStoreBillingDebugDescription[];
 
-extern const char kWebAuthnNewDesktopUIName[];
-extern const char kWebAuthnNewDesktopUIDescription[];
-
 extern const char kWebrtcHideLocalIpsWithMdnsName[];
 extern const char kWebrtcHideLocalIpsWithMdnsDecription[];
 
@@ -1981,6 +1978,9 @@
 extern const char kAppMenuMobileSiteOptionName[];
 extern const char kAppMenuMobileSiteOptionDescription[];
 
+extern const char kBackGestureRefactorActivityAndroidName[];
+extern const char kBackGestureRefactorActivityAndroidDescription[];
+
 extern const char kBackGestureRefactorAndroidName[];
 extern const char kBackGestureRefactorAndroidDescription[];
 
@@ -2885,6 +2885,9 @@
 extern const char kFastPairName[];
 extern const char kFastPairDescription[];
 
+extern const char kFastPairHandshakeRefactorName[];
+extern const char kFastPairHandshakeRefactorDescription[];
+
 extern const char kFastPairLowPowerName[];
 extern const char kFastPairLowPowerDescription[];
 
@@ -2905,9 +2908,6 @@
 extern const char kQuickSettingsPWANotificationsName[];
 extern const char kQuickSettingsPWANotificationsDescription[];
 
-extern const char kDriveFsBidirectionalNativeMessagingName[];
-extern const char kDriveFsBidirectionalNativeMessagingDescription[];
-
 extern const char kDriveFsChromeNetworkingName[];
 extern const char kDriveFsChromeNetworkingDescription[];
 
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index d70d8a56..b75d4e32 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -239,6 +239,7 @@
     &kPageAnnotationsService,
     &kBookmarksImprovedSaveFlow,
     &kBookmarksRefresh,
+    &kBackGestureRefactorActivityAndroid,
     &kBackGestureRefactorAndroid,
     &kOmahaMinSdkVersionAndroid,
     &kOmniboxModernizeVisualUpdate,
@@ -746,6 +747,10 @@
              "BookmarksRefresh",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+BASE_FEATURE(kBackGestureRefactorActivityAndroid,
+             "BackGestureRefactorActivityAndroid",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 BASE_FEATURE(kBackGestureRefactorAndroid,
              "BackGestureRefactorAndroid",
              base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h
index a0ee0c9..b78dab2 100644
--- a/chrome/browser/flags/android/chrome_feature_list.h
+++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -108,6 +108,7 @@
 BASE_DECLARE_FEATURE(kPageAnnotationsService);
 BASE_DECLARE_FEATURE(kBookmarksImprovedSaveFlow);
 BASE_DECLARE_FEATURE(kBookmarksRefresh);
+BASE_DECLARE_FEATURE(kBackGestureRefactorActivityAndroid);
 BASE_DECLARE_FEATURE(kBackGestureRefactorAndroid);
 BASE_DECLARE_FEATURE(kOpaqueOriginForIncomingIntents);
 BASE_DECLARE_FEATURE(kPostTaskFocusTab);
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index a9aec27f..48399565 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -209,6 +209,8 @@
     public static final String BACKGROUND_THREAD_POOL = "BackgroundThreadPool";
     public static final String BACK_FORWARD_CACHE = "BackForwardCache";
     public static final String BACK_GESTURE_REFACTOR = "BackGestureRefactorAndroid";
+    public static final String BACK_GESTURE_REFACTOR_ACTIVITY =
+            "BackGestureRefactorActivityAndroid";
     public static final String BASELINE_GM3_SURFACE_COLORS = "BaselineGM3SurfaceColors";
     public static final String BIOMETRIC_TOUCH_TO_FILL = "BiometricTouchToFill";
     public static final String BOOKMARKS_IMPROVED_SAVE_FLOW = "BookmarksImprovedSaveFlow";
@@ -549,6 +551,8 @@
     /* Alphabetical: */
     public static final CachedFlag sAppMenuMobileSiteOption =
             new CachedFlag(APP_MENU_MOBILE_SITE_OPTION, false);
+    public static final CachedFlag sBackGestureRefactorActivityAndroid =
+            new CachedFlag(BACK_GESTURE_REFACTOR_ACTIVITY, false);
     public static final CachedFlag sBackGestureRefactorAndroid =
             new CachedFlag(BACK_GESTURE_REFACTOR, false);
     public static final CachedFlag sBaselineGm3SurfaceColors =
diff --git a/chrome/browser/headless/BUILD.gn b/chrome/browser/headless/BUILD.gn
index 3fc559e..b21cc11 100644
--- a/chrome/browser/headless/BUILD.gn
+++ b/chrome/browser/headless/BUILD.gn
@@ -25,6 +25,20 @@
   }
 }
 
+source_set("command_processor") {
+  sources = [
+    "headless_command_processor.cc",
+    "headless_command_processor.h",
+  ]
+
+  deps = [
+    ":headless",
+    "//base",
+    "//components/headless/command_handler",
+    "//content/public/browser",
+  ]
+}
+
 if (!is_android) {
   source_set("browser_tests") {
     testonly = true
diff --git a/chrome/browser/headless/DEPS b/chrome/browser/headless/DEPS
new file mode 100644
index 0000000..7e2ff4c79
--- /dev/null
+++ b/chrome/browser/headless/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+components/headless",
+]
diff --git a/chrome/browser/headless/headless_command_processor.cc b/chrome/browser/headless/headless_command_processor.cc
new file mode 100644
index 0000000..f635dfaa
--- /dev/null
+++ b/chrome/browser/headless/headless_command_processor.cc
@@ -0,0 +1,55 @@
+// 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 "chrome/browser/headless/headless_command_processor.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "chrome/browser/headless/headless_mode_util.h"
+#include "components/headless/command_handler/headless_command_handler.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/web_contents.h"
+#include "ui/base/page_transition_types.h"
+
+namespace headless {
+
+bool ShouldProcessHeadlessCommands() {
+  return IsHeadlessMode() && HeadlessCommandHandler::HasHeadlessCommandSwitches(
+                                 *base::CommandLine::ForCurrentProcess());
+}
+
+void ProcessHeadlessCommands(content::BrowserContext* browser_context,
+                             GURL target_url,
+                             base::OnceClosure done_callback) {
+  DCHECK(browser_context);
+
+  // Create web contents to run the command processing in.
+  content::WebContents::CreateParams create_params(browser_context);
+  create_params.is_never_visible = true;
+  std::unique_ptr<content::WebContents> web_contents(
+      content::WebContents::Create(create_params));
+  if (!web_contents) {
+    return;
+  }
+
+  // Navigate web contents to the command processor page.
+  GURL handler_url = HeadlessCommandHandler::GetHandlerUrl();
+  content::NavigationController::LoadURLParams load_url_params(handler_url);
+  web_contents->GetController().LoadURLWithParams(load_url_params);
+
+  HeadlessCommandHandler::ProcessCommands(
+      web_contents.get(), std::move(target_url),
+      base::BindOnce(
+          [](std::unique_ptr<content::WebContents> web_contents,
+             base::OnceClosure done_callback) {
+            web_contents.reset();
+            std::move(done_callback).Run();
+          },
+          std::move(web_contents), std::move(done_callback)));
+}
+
+}  // namespace headless
diff --git a/chrome/browser/headless/headless_command_processor.h b/chrome/browser/headless/headless_command_processor.h
new file mode 100644
index 0000000..dee7a967
--- /dev/null
+++ b/chrome/browser/headless/headless_command_processor.h
@@ -0,0 +1,28 @@
+// 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 CHROME_BROWSER_HEADLESS_HEADLESS_COMMAND_PROCESSOR_H_
+#define CHROME_BROWSER_HEADLESS_HEADLESS_COMMAND_PROCESSOR_H_
+
+#include "base/functional/callback.h"
+#include "url/gurl.h"
+
+namespace content {
+class BrowserContext;
+}
+
+namespace headless {
+
+// Checks if headless command switches --dump-dom, --screenshot or
+// --print-to-pdf are present while in headless mode.
+bool ShouldProcessHeadlessCommands();
+
+// Runs headless commands against the specified target url.
+void ProcessHeadlessCommands(content::BrowserContext* browser_context,
+                             GURL target_url,
+                             base::OnceClosure done_callback);
+
+}  // namespace headless
+
+#endif  // CHROME_BROWSER_HEADLESS_HEADLESS_COMMAND_PROCESSOR_H_
diff --git a/chrome/browser/metrics/ukm_browsertest.cc b/chrome/browser/metrics/ukm_browsertest.cc
index 97b8f0f..d78c8dd 100644
--- a/chrome/browser/metrics/ukm_browsertest.cc
+++ b/chrome/browser/metrics/ukm_browsertest.cc
@@ -1727,14 +1727,6 @@
     const auto id = report->sources(i).id();
     EXPECT_EQ(ukm::GetSourceIdType(id), ukm::SourceIdType::APP_ID);
   }
-
-  // Verify that if an entry exists it is either DEFAULT or APP_ID.
-  // NOTE(crbug/1395144): There were some entries with SourceId of 0, which are
-  // not purged because they do not have a source in the recordings.
-  for (int i = 0; i < report->entries_size(); ++i) {
-    const auto id_type = ukm::GetSourceIdType(report->entries(i).id());
-    EXPECT_EQ(id_type, ukm::SourceIdType::DEFAULT);
-  }
 }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
diff --git a/chrome/browser/metrics/variations/variations_http_headers_browsertest.cc b/chrome/browser/metrics/variations/variations_http_headers_browsertest.cc
index 632426cf..2938fd1 100644
--- a/chrome/browser/metrics/variations/variations_http_headers_browsertest.cc
+++ b/chrome/browser/metrics/variations/variations_http_headers_browsertest.cc
@@ -329,30 +329,6 @@
   std::map<GURL, base::OnceClosure> done_callbacks_;
 };
 
-// Used for testing the kRestrictGoogleWebVisibility feature.
-class VariationsHttpHeadersBrowserTestWithRestrictedVisibility
-    : public VariationsHttpHeadersBrowserTest,
-      public testing::WithParamInterface<bool> {
- public:
-  VariationsHttpHeadersBrowserTestWithRestrictedVisibility() {
-    if (GetParam()) {
-      scoped_feature_list_.InitAndEnableFeature(
-          variations::internal::kRestrictGoogleWebVisibility);
-    } else {
-      scoped_feature_list_.InitAndDisableFeature(
-          variations::internal::kRestrictGoogleWebVisibility);
-    }
-  }
-
-  VariationsHttpHeadersBrowserTestWithRestrictedVisibility(
-      const VariationsHttpHeadersBrowserTestWithRestrictedVisibility&) = delete;
-  VariationsHttpHeadersBrowserTestWithRestrictedVisibility& operator=(
-      const VariationsHttpHeadersBrowserTestWithRestrictedVisibility&) = delete;
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
 std::unique_ptr<net::test_server::HttpResponse>
 VariationsHttpHeadersBrowserTest::RequestHandler(
     const net::test_server::HttpRequest& request) {
@@ -426,54 +402,6 @@
                 variations::mojom::GoogleWebVisibility::FIRST_PARTY));
 }
 
-// Creates FieldTrials associated with the FIRST_PARTY IDCollectionKeys and
-// their corresponding ANY_CONTEXT keys.
-void CreateFieldTrialsWithDifferentVisibilities() {
-  scoped_refptr<base::FieldTrial> trial_1(variations::CreateTrialAndAssociateId(
-      "t1", "g1", variations::GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, 11));
-  scoped_refptr<base::FieldTrial> trial_2(variations::CreateTrialAndAssociateId(
-      "t2", "g2", variations::GOOGLE_WEB_PROPERTIES_FIRST_PARTY, 22));
-  scoped_refptr<base::FieldTrial> trial_3(variations::CreateTrialAndAssociateId(
-      "t3", "g3", variations::GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, 33));
-  scoped_refptr<base::FieldTrial> trial_4(variations::CreateTrialAndAssociateId(
-      "t4", "g4", variations::GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY, 44));
-
-  auto* provider = variations::VariationsIdsProvider::GetInstance();
-  variations::mojom::VariationsHeadersPtr signed_in_headers =
-      provider->GetClientDataHeaders(/*is_signed_in=*/true);
-  variations::mojom::VariationsHeadersPtr signed_out_headers =
-      provider->GetClientDataHeaders(/*is_signed_in=*/false);
-
-  if (base::FeatureList::IsEnabled(
-          variations::internal::kRestrictGoogleWebVisibility)) {
-    EXPECT_NE(signed_in_headers->headers_map.at(
-                  variations::mojom::GoogleWebVisibility::ANY),
-              signed_in_headers->headers_map.at(
-                  variations::mojom::GoogleWebVisibility::FIRST_PARTY));
-    EXPECT_NE(signed_out_headers->headers_map.at(
-                  variations::mojom::GoogleWebVisibility::ANY),
-              signed_out_headers->headers_map.at(
-                  variations::mojom::GoogleWebVisibility::FIRST_PARTY));
-  } else {
-    // When kRestrictGoogleWebVisibility is disabled, the transmission of
-    // VariationIDs is not restricted. This is the status quo implementation.
-    //
-    // This means that IDs associated with the FIRST_PARTY IDCollectionKeys are
-    // treated as if they were associated with their corresponding ANY_CONTEXT
-    // IDCollectionKeys. For example, when the feature is disabled, IDs
-    // associated with GOOGLE_WEB_PROPERTIES_FIRST_PARTY are transmitted when
-    // IDs associated with GOOGLE_WEB_PROPERTIES_ANY_CONTEXT are.
-    EXPECT_EQ(signed_in_headers->headers_map.at(
-                  variations::mojom::GoogleWebVisibility::ANY),
-              signed_in_headers->headers_map.at(
-                  variations::mojom::GoogleWebVisibility::FIRST_PARTY));
-    EXPECT_EQ(signed_out_headers->headers_map.at(
-                  variations::mojom::GoogleWebVisibility::ANY),
-              signed_out_headers->headers_map.at(
-                  variations::mojom::GoogleWebVisibility::FIRST_PARTY));
-  }
-}
-
 }  // namespace
 
 // Verify in an integration test that the variations header (X-Client-Data) is
@@ -664,33 +592,44 @@
   EXPECT_TRUE(base::Contains(variation_ids, 33));
 }
 
-INSTANTIATE_TEST_SUITE_P(
-    VariationsHttpHeadersBrowserTest,
-    VariationsHttpHeadersBrowserTestWithRestrictedVisibility,
-    testing::Bool());
-
-IN_PROC_BROWSER_TEST_P(VariationsHttpHeadersBrowserTestWithRestrictedVisibility,
+IN_PROC_BROWSER_TEST_F(VariationsHttpHeadersBrowserTest,
                        TestRestrictGoogleWebVisibilityInThirdPartyContexts) {
-  // Ensure GetClientDataHeader() returns different values when
-  // kRestrictGoogleWebVisibility is enabled and the same values otherwise.
-  CreateFieldTrialsWithDifferentVisibilities();
+  scoped_refptr<base::FieldTrial> trial_1(variations::CreateTrialAndAssociateId(
+      "t1", "g1", variations::GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, 11));
+  scoped_refptr<base::FieldTrial> trial_2(variations::CreateTrialAndAssociateId(
+      "t2", "g2", variations::GOOGLE_WEB_PROPERTIES_FIRST_PARTY, 22));
+  scoped_refptr<base::FieldTrial> trial_3(variations::CreateTrialAndAssociateId(
+      "t3", "g3", variations::GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, 33));
+  scoped_refptr<base::FieldTrial> trial_4(variations::CreateTrialAndAssociateId(
+      "t4", "g4", variations::GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY, 44));
+
+  auto* provider = variations::VariationsIdsProvider::GetInstance();
+  variations::mojom::VariationsHeadersPtr signed_in_headers =
+      provider->GetClientDataHeaders(/*is_signed_in=*/true);
+  variations::mojom::VariationsHeadersPtr signed_out_headers =
+      provider->GetClientDataHeaders(/*is_signed_in=*/false);
+
+  EXPECT_NE(signed_in_headers->headers_map.at(
+                variations::mojom::GoogleWebVisibility::ANY),
+            signed_in_headers->headers_map.at(
+                variations::mojom::GoogleWebVisibility::FIRST_PARTY));
+
+  EXPECT_NE(signed_out_headers->headers_map.at(
+                variations::mojom::GoogleWebVisibility::ANY),
+            signed_out_headers->headers_map.at(
+                variations::mojom::GoogleWebVisibility::FIRST_PARTY));
 
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetGoogleUrl()));
   absl::optional<std::string> header =
       GetReceivedHeader(GetGoogleUrl(), "X-Client-Data");
   ASSERT_TRUE(header);
 
-  variations::mojom::GoogleWebVisibility web_visibility =
-      base::FeatureList::IsEnabled(
-          variations::internal::kRestrictGoogleWebVisibility)
-          ? variations::mojom::GoogleWebVisibility::FIRST_PARTY
-          : variations::mojom::GoogleWebVisibility::ANY;
-
-  variations::mojom::VariationsHeadersPtr headers =
+  variations::mojom::VariationsHeadersPtr signed_out_headers_2 =
       variations::VariationsIdsProvider::GetInstance()->GetClientDataHeaders(
           /*is_signed_in=*/false);
 
-  EXPECT_EQ(*header, headers->headers_map.at(web_visibility));
+  EXPECT_EQ(*header, signed_out_headers_2->headers_map.at(
+                         variations::mojom::GoogleWebVisibility::FIRST_PARTY));
 }
 
 IN_PROC_BROWSER_TEST_F(
diff --git a/chrome/browser/payments/secure_payment_confirmation_authenticator_browsertest.cc b/chrome/browser/payments/secure_payment_confirmation_authenticator_browsertest.cc
index 49d4e44..764832f1 100644
--- a/chrome/browser/payments/secure_payment_confirmation_authenticator_browsertest.cc
+++ b/chrome/browser/payments/secure_payment_confirmation_authenticator_browsertest.cc
@@ -14,7 +14,6 @@
 #include "content/public/browser/authenticator_environment.h"
 #include "content/public/common/content_features.h"
 #include "content/public/test/browser_test.h"
-#include "device/fido/features.h"
 #include "device/fido/virtual_fido_device_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -24,6 +23,10 @@
 #error "These tests are unsupported on Android"
 #endif
 
+// TODO(crbug.com/1372198): Temporarily disable the tests on macOS since they do
+// not yet work with current WebAuthn UI.
+#if !BUILDFLAG(IS_MAC)
+
 namespace payments {
 namespace {
 
@@ -46,13 +49,6 @@
     WEB_CONTENTS_DESTROYED,
   };
 
-  SecurePaymentConfirmationAuthenticatorTestBase() {
-    // TODO(crbug.com/1372198): Temporarily disable the new passkey UI, as it
-    // causes these tests to hang.
-    scoped_feature_list_.InitAndDisableFeature(
-        device::kWebAuthnNewDiscoverableCredentialsUi);
-  }
-
   // Installs a virtual FIDO authenticator device for the tests.
   void ReplaceFidoDiscoveryFactory(bool should_succeed,
                                    bool should_hang = false) {
@@ -114,8 +110,9 @@
     std::string* id = value->FindStringKey("id");
     ASSERT_NE(nullptr, id) << response;
 
-    if (out_info)
+    if (out_info) {
       *out_info = {*webidl_type, *type, *id};
+    }
   }
 
   void ExpectEnrollSystemPromptResult(
@@ -160,7 +157,6 @@
   }
 
   std::unique_ptr<autofill::EventWaiter<Event>> event_waiter_;
-  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 using SecurePaymentConfirmationAuthenticatorCreateTest =
@@ -629,3 +625,5 @@
 
 }  // namespace
 }  // namespace payments
+
+#endif  // !BUILDFLAG(IS_MAC)
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
index 9c6f7ea..fa8868a 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -113,6 +113,7 @@
 #include "third_party/blink/public/common/switches.h"
 #include "third_party/blink/public/mojom/context_menu/context_menu.mojom.h"
 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom.h"
+#include "third_party/libwebp/src/src/webp/decode.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/accessibility/accessibility_features.h"
 #include "ui/base/emoji/emoji_panel_helper.h"
@@ -351,6 +352,13 @@
                             .get();
       ASSERT_EQ(expected_size.width(), decoded_bitmap.width());
       ASSERT_EQ(expected_size.height(), decoded_bitmap.height());
+    } else if (response_file_extension == ".webp") {
+      int width;
+      int height;
+      EXPECT_TRUE(WebPGetInfo(&response_image_data.front(),
+                              response_image_data.size(), &width, &height));
+      ASSERT_EQ(expected_size.width(), width);
+      ASSERT_EQ(expected_size.height(), height);
     }
   }
 
@@ -2462,6 +2470,36 @@
       gfx::Size(480, 320), gfx::Size(100, /* 100 / 480 * 320 =  */ 66), ".jpg");
 }
 
+IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, JpgImageDownscaleToWebp) {
+  OpenImagePageAndContextMenu("/android/watch.jpg");
+  RequestImageAndVerifyResponse(
+      gfx::Size(100, 100), chrome::mojom::ImageFormat::WEBP,
+      gfx::Size(480, 320), gfx::Size(100, /* 100 / 480 * 320 =  */ 66),
+      ".webp");
+}
+
+IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, PngImageDownscaleToWebp) {
+  OpenImagePageAndContextMenu("/image_search/valid.png");
+  RequestImageAndVerifyResponse(
+      gfx::Size(100, 100), chrome::mojom::ImageFormat::WEBP,
+      gfx::Size(200, 100), gfx::Size(100, 50), ".webp");
+}
+
+IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, GifImageDownscaleToWebp) {
+  OpenImagePageAndContextMenu("/google/logo.gif");
+  RequestImageAndVerifyResponse(
+      gfx::Size(100, 100), chrome::mojom::ImageFormat::WEBP,
+      gfx::Size(276, 110), gfx::Size(100, /* 100 / 275 * 110 =  */ 39),
+      ".webp");
+}
+
+IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, WebpImageDownscaleToWebp) {
+  OpenImagePageAndContextMenu("/banners/webp-icon.webp");
+  RequestImageAndVerifyResponse(
+      gfx::Size(100, 100), chrome::mojom::ImageFormat::WEBP,
+      gfx::Size(192, 192), gfx::Size(100, 100), ".webp");
+}
+
 IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest,
                        CopyLinkToTextDisabledWithScrollToTextPolicyDisabled) {
   browser()->profile()->GetPrefs()->SetBoolean(
diff --git a/chrome/browser/resources/accessibility/accessibility.ts b/chrome/browser/resources/accessibility/accessibility.ts
index d66f69e..4bfb8907 100644
--- a/chrome/browser/resources/accessibility/accessibility.ts
+++ b/chrome/browser/resources/accessibility/accessibility.ts
@@ -37,7 +37,7 @@
   pid: number,
   processId: number,
   routingId: number,
-  url: string,
+  url?: string,
 
   // Used for GlobalStateName.
   // Note: Does 'metadata' actually exist? Does not appear anywhere in
diff --git a/chrome/browser/resources/ntp4/nav_dot.js b/chrome/browser/resources/ntp4/nav_dot.js
index ff760703..2d2cff7 100644
--- a/chrome/browser/resources/ntp4/nav_dot.js
+++ b/chrome/browser/resources/ntp4/nav_dot.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {DragWrapper, DragWrapperDelegate} from 'chrome://resources/js/drag_wrapper.js';
+import {DragWrapper} from 'chrome://resources/js/drag_wrapper.js';
 
 import {getCardSlider, saveAppPageName} from './new_tab.js';
 import {getCurrentlyDraggingTile, setCurrentDropEffect, TilePage} from './tile_page.js';
diff --git a/chrome/browser/resources/ntp4/tile_page.js b/chrome/browser/resources/ntp4/tile_page.js
index dc66422..925cae2 100644
--- a/chrome/browser/resources/ntp4/tile_page.js
+++ b/chrome/browser/resources/ntp4/tile_page.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {assert, assertNotReached} from 'chrome://resources/js/assert_ts.js';
-import {DragWrapper, DragWrapperDelegate} from 'chrome://resources/js/drag_wrapper.js';
+import {DragWrapper} from 'chrome://resources/js/drag_wrapper.js';
 import {EventTracker} from 'chrome://resources/js/event_tracker.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {$, isRTL} from 'chrome://resources/js/util_ts.js';
diff --git a/chrome/browser/resources/ntp4/trash.js b/chrome/browser/resources/ntp4/trash.js
index 0d0fd4d..9aaf7e52 100644
--- a/chrome/browser/resources/ntp4/trash.js
+++ b/chrome/browser/resources/ntp4/trash.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {DragWrapper, DragWrapperDelegate} from 'chrome://resources/js/drag_wrapper.js';
+import {DragWrapper} from 'chrome://resources/js/drag_wrapper.js';
 import {getCurrentlyDraggingTile, setCurrentDropEffect} from './tile_page.js';
 
 /**
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn
index 3b8ffea..cf3d2ec9 100644
--- a/chrome/browser/resources/settings/chromeos/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -295,7 +295,6 @@
 group("generate_web_components") {
   public_deps = [
     # Sub-folder targets
-    "multidevice_page:web_components",
     "nearby_share_page:web_components",
     "os_a11y_page:web_components",
     "os_privacy_page:web_components",
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn
index 84a3f1a0..5b12ea3 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn
@@ -3,7 +3,6 @@
 # found in the LICENSE file.
 
 import("//third_party/closure_compiler/compile_js.gni")
-import("//tools/polymer/html_to_js.gni")
 import("../os_settings.gni")
 
 js_type_check("closure_compile_module") {
@@ -237,23 +236,3 @@
 js_library("multidevice_metrics_logger") {
   deps = [ "//ash/webui/common/resources:assert" ]
 }
-
-html_to_js("web_components") {
-  js_files = [
-    "multidevice_combined_setup_item.js",
-    "multidevice_feature_item.js",
-    "multidevice_feature_toggle.js",
-    "multidevice_notification_access_setup_dialog.js",
-    "multidevice_page.js",
-    "multidevice_permissions_setup_dialog.js",
-    "multidevice_radio_button.js",
-    "multidevice_screen_lock_subpage.js",
-    "multidevice_smartlock_item.js",
-    "multidevice_subpage.js",
-    "multidevice_task_continuation_disabled_link.js",
-    "multidevice_task_continuation_item.js",
-    "multidevice_tether_item.js",
-    "multidevice_wifi_sync_disabled_link.js",
-    "multidevice_wifi_sync_item.js",
-  ]
-}
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_combined_setup_item.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_combined_setup_item.js
index c0b6c04..769ee1a1 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_combined_setup_item.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_combined_setup_item.js
@@ -12,9 +12,10 @@
 import './multidevice_feature_item.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_browser_proxy.js';
+import {getTemplate} from './multidevice_combined_setup_item.html.js';
 import {PhoneHubPermissionsSetupFeatureCombination} from './multidevice_constants.js';
 import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js';
 
@@ -35,7 +36,7 @@
   }
 
   static get template() {
-    return html`{__html_template__}`;
+    return getTemplate();
   }
 
   static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_item.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_item.js
index 3e2e75a..b96f51c 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_item.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_item.js
@@ -19,18 +19,18 @@
 import './multidevice_feature_toggle.js';
 
 import {assert} from 'chrome://resources/ash/common/assert.js';
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {Route, Router} from '../router.js';
 import {routes} from '../os_route.js';
 import {RouteOriginBehavior, RouteOriginBehaviorInterface} from '../route_origin_behavior.js';
+import {Route, Router} from '../router.js';
 
 import {MultiDeviceFeature} from './multidevice_constants.js';
 import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js';
+import {getTemplate} from './multidevice_feature_item.html.js';
 import {SettingsMultideviceFeatureToggleElement} from './multidevice_feature_toggle.js';
 import {recordSmartLockToggleMetric, SmartLockToggleLocation} from './multidevice_metrics_logger.js';
 
-
 /**
  * @constructor
  * @extends {PolymerElement}
@@ -48,7 +48,7 @@
   }
 
   static get template() {
-    return html`{__html_template__}`;
+    return getTemplate();
   }
 
   static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_toggle.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_toggle.js
index 941551f4..eaf1e6e 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_toggle.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_toggle.js
@@ -13,11 +13,11 @@
 
 import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js';
 
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {MultiDeviceFeature, MultiDeviceFeatureState} from './multidevice_constants.js';
 import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js';
-
+import {getTemplate} from './multidevice_feature_toggle.html.js';
 
 /**
  * @constructor
@@ -35,7 +35,7 @@
   }
 
   static get template() {
-    return html`{__html_template__}`;
+    return getTemplate();
   }
 
   static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_notification_access_setup_dialog.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_notification_access_setup_dialog.js
index d072f06..716e115 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_notification_access_setup_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_notification_access_setup_dialog.js
@@ -19,16 +19,17 @@
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js';
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_browser_proxy.js';
 import {MultiDeviceFeature} from './multidevice_constants.js';
+import {getTemplate} from './multidevice_notification_access_setup_dialog.html.js';
 
 /**
  * Numerical values should not be changed because they must stay in sync with
  * notification_access_setup_operation.h, with the exception of
  * CONNECTION_REQUESTED.
- * @enum{number}
+ * @enum {number}
  */
 export const NotificationAccessSetupOperationStatus = {
   CONNECTION_REQUESTED: 0,
@@ -57,7 +58,7 @@
   }
 
   static get template() {
-    return html`{__html_template__}`;
+    return getTemplate();
   }
 
   static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js
index 5768f68..5a5f329f 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js
@@ -21,7 +21,7 @@
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
-import {beforeNextRender, html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {beforeNextRender, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
 import {NearbyShareSettingsBehavior, NearbyShareSettingsBehaviorInterface} from '../../shared/nearby_share_settings_behavior.js';
@@ -35,6 +35,7 @@
 import {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_browser_proxy.js';
 import {MultiDeviceFeature, MultiDeviceFeatureState, MultiDevicePageContentData, MultiDeviceSettingsMode, PhoneHubFeatureAccessStatus, PhoneHubPermissionsSetupAction, PhoneHubPermissionsSetupFlowScreens} from './multidevice_constants.js';
 import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js';
+import {getTemplate} from './multidevice_page.html.js';
 
 /**
  * @constructor
@@ -67,7 +68,7 @@
   }
 
   static get template() {
-    return html`{__html_template__}`;
+    return getTemplate();
   }
 
   static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_permissions_setup_dialog.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_permissions_setup_dialog.js
index e7607c5..7d00f40 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_permissions_setup_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_permissions_setup_dialog.js
@@ -19,16 +19,17 @@
 import '../os_settings_icons.html.js';
 import '../../settings_shared.css.js';
 
-import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
-import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js';
 import {assert} from 'chrome://resources/ash/common/assert.js';
+import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
 import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js';
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js';
+import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {LockStateBehavior, LockStateBehaviorInterface} from '../os_people_page/lock_state_behavior.js';
 
 import {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_browser_proxy.js';
 import {MultiDeviceFeature, PhoneHubPermissionsSetupAction, PhoneHubPermissionsSetupFeatureCombination, PhoneHubPermissionsSetupFlowScreens} from './multidevice_constants.js';
+import {getTemplate} from './multidevice_permissions_setup_dialog.html.js';
 
 /**
  * Numerical values should not be changed because they must stay in sync with
@@ -106,7 +107,7 @@
   }
 
   static get template() {
-    return html`{__html_template__}`;
+    return getTemplate();
   }
 
   static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_radio_button.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_radio_button.js
index d94ddea..7b2ad28 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_radio_button.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_radio_button.js
@@ -8,7 +8,9 @@
 
 import {CrRadioButtonMixin} from 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button_mixin.js';
 import {PaperRippleBehavior} from 'chrome://resources/polymer/v3_0/paper-behaviors/paper-ripple-behavior.js';
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {getTemplate} from './multidevice_radio_button.html.js';
 
 class PaperRippleBehaviorInterface {
   constructor() {
@@ -39,7 +41,7 @@
   }
 
   static get template() {
-    return html`{__html_template__}`;
+    return getTemplate();
   }
 
   static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_screen_lock_subpage.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_screen_lock_subpage.js
index 9ccdf1a..33f444de 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_screen_lock_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_screen_lock_subpage.js
@@ -15,10 +15,12 @@
 import {assert} from 'chrome://resources/ash/common/assert.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
 import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js';
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {LockScreenUnlockType, LockStateBehavior, LockStateBehaviorInterface} from '../os_people_page/lock_state_behavior.js';
 
+import {getTemplate} from './multidevice_screen_lock_subpage.html.js';
+
 /**
  * @constructor
  * @extends {PolymerElement}
@@ -36,7 +38,7 @@
   }
 
   static get template() {
-    return html`{__html_template__}`;
+    return getTemplate();
   }
 
   static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_item.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_item.js
index 4733eaff..9ae5529 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_item.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_item.js
@@ -13,7 +13,7 @@
 import './multidevice_feature_item.js';
 
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js';
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {recordSettingChange} from '../metrics_recorder.js';
 import {routes} from '../os_route.js';
@@ -22,6 +22,7 @@
 import {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_browser_proxy.js';
 import {MultiDeviceFeature, MultiDevicePageContentData, MultiDeviceSettingsMode} from './multidevice_constants.js';
 import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js';
+import {getTemplate} from './multidevice_smartlock_item.html.js';
 
 /**
  * @constructor
@@ -40,7 +41,7 @@
   }
 
   static get template() {
-    return html`{__html_template__}`;
+    return getTemplate();
   }
 
   static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js
index f0d8caf8..c0dc6c7 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js
@@ -21,18 +21,19 @@
 import './multidevice_wifi_sync_item.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
-import {Route} from '../router.js';
 import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js';
 import {routes} from '../os_route.js';
 import {OsSettingsRoutes} from '../os_settings_routes.js';
 import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js';
+import {Route} from '../router.js';
 
 import {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_browser_proxy.js';
 import {MultiDeviceFeature, MultiDeviceFeatureState, MultiDeviceSettingsMode, PhoneHubFeatureAccessProhibitedReason, PhoneHubPermissionsSetupFeatureCombination} from './multidevice_constants.js';
 import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js';
+import {getTemplate} from './multidevice_subpage.html.js';
 
 /**
  * @constructor
@@ -59,7 +60,7 @@
   }
 
   static get template() {
-    return html`{__html_template__}`;
+    return getTemplate();
   }
 
   static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_disabled_link.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_disabled_link.js
index 4f333f7..62f30d83 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_disabled_link.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_disabled_link.js
@@ -17,10 +17,12 @@
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
 import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js';
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {Router} from '../router.js';
 import {routes} from '../os_route.js';
+import {Router} from '../router.js';
+
+import {getTemplate} from './multidevice_task_continuation_disabled_link.html.js';
 
 /**
  * @constructor
@@ -38,7 +40,7 @@
   }
 
   static get template() {
-    return html`{__html_template__}`;
+    return getTemplate();
   }
 
   /** @override */
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.js
index 64b6d11c..73b959eb 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.js
@@ -23,11 +23,12 @@
 import '../../settings_shared.css.js';
 
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js';
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {SyncBrowserProxyImpl} from '../../people_page/sync_browser_proxy.js';
 
 import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js';
+import {getTemplate} from './multidevice_task_continuation_item.html.js';
 
 /**
  * @constructor
@@ -50,7 +51,7 @@
   }
 
   static get template() {
-    return html`{__html_template__}`;
+    return getTemplate();
   }
 
   static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_tether_item.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_tether_item.js
index 164d614..b837f13 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_tether_item.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_tether_item.js
@@ -22,12 +22,13 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {CrosNetworkConfigRemote, FilterType, InhibitReason, NetworkStateProperties} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js';
 import {DeviceStateType, NetworkType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js';
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {routes} from '../os_route.js';
 import {OsSettingsRoutes} from '../os_settings_routes.js';
 
 import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js';
+import {getTemplate} from './multidevice_tether_item.html.js';
 
 /**
  * @constructor
@@ -50,7 +51,7 @@
   }
 
   static get template() {
-    return html`{__html_template__}`;
+    return getTemplate();
   }
 
   static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_disabled_link.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_disabled_link.js
index a0792fb..d98285d 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_disabled_link.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_disabled_link.js
@@ -16,12 +16,13 @@
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
 import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js';
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {Router} from '../router.js';
 import {routes} from '../os_route.js';
+import {Router} from '../router.js';
 
 import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js';
+import {getTemplate} from './multidevice_wifi_sync_disabled_link.html.js';
 
 /**
  * @constructor
@@ -40,7 +41,7 @@
   }
 
   static get template() {
-    return html`{__html_template__}`;
+    return getTemplate();
   }
 
   getAriaLabelledContent_() {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_item.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_item.js
index c4df43f..34e6662 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_item.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_item.js
@@ -22,12 +22,13 @@
 
 import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js';
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js';
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {SyncBrowserProxyImpl} from '../../people_page/sync_browser_proxy.js';
 import {OsSyncBrowserProxy, OsSyncBrowserProxyImpl, OsSyncPrefs} from '../os_people_page/os_sync_browser_proxy.js';
 
 import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js';
+import {getTemplate} from './multidevice_wifi_sync_item.html.js';
 
 /**
  * @constructor
@@ -46,7 +47,7 @@
   }
 
   static get template() {
-    return html`{__html_template__}`;
+    return getTemplate();
   }
 
   static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js b/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js
index 4457440e..e4b9d428 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js
@@ -27,7 +27,7 @@
 import {getImage} from '../icon.js';
 import {recordSettingChange} from '../metrics_recorder.js';
 import {routes} from '../os_route.js';
-import {ParentalControlsBrowserProxy, ParentalControlsBrowserProxyImpl} from '../parental_controls_page/parental_controls_browser_proxy.js';
+import {ParentalControlsBrowserProxyImpl} from '../parental_controls_page/parental_controls_browser_proxy.js';
 import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js';
 import {Route} from '../router.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry_list_behavior.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry_list_behavior.js
index 86727eb0..2845bd5 100644
--- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry_list_behavior.js
+++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry_list_behavior.js
@@ -11,7 +11,6 @@
 import {assert} from 'chrome://resources/ash/common/assert.js';
 
 import {findDifference} from './cups_printer_dialog_util.js';
-import {PrinterListEntry} from './cups_printer_types.js';
 import {CupsPrintersEntryManager} from './cups_printers_entry_manager.js';
 
 /** @polymerBehavior */
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni
index 72c16889..6f631d5 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.gni
+++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -85,6 +85,21 @@
   "chromeos/kerberos_page/kerberos_add_account_dialog.ts",
   "chromeos/kerberos_page/kerberos_page.ts",
   "chromeos/keyboard_shortcut_banner/keyboard_shortcut_banner.ts",
+  "chromeos/multidevice_page/multidevice_combined_setup_item.js",
+  "chromeos/multidevice_page/multidevice_feature_item.js",
+  "chromeos/multidevice_page/multidevice_feature_toggle.js",
+  "chromeos/multidevice_page/multidevice_notification_access_setup_dialog.js",
+  "chromeos/multidevice_page/multidevice_page.js",
+  "chromeos/multidevice_page/multidevice_permissions_setup_dialog.js",
+  "chromeos/multidevice_page/multidevice_radio_button.js",
+  "chromeos/multidevice_page/multidevice_screen_lock_subpage.js",
+  "chromeos/multidevice_page/multidevice_smartlock_item.js",
+  "chromeos/multidevice_page/multidevice_subpage.js",
+  "chromeos/multidevice_page/multidevice_task_continuation_disabled_link.js",
+  "chromeos/multidevice_page/multidevice_task_continuation_item.js",
+  "chromeos/multidevice_page/multidevice_tether_item.js",
+  "chromeos/multidevice_page/multidevice_wifi_sync_disabled_link.js",
+  "chromeos/multidevice_page/multidevice_wifi_sync_item.js",
   "chromeos/os_a11y_page/audio_and_captions_page.ts",
   "chromeos/os_a11y_page/change_dictation_locale_dialog.ts",
   "chromeos/os_a11y_page/cursor_and_touchpad_page.ts",
@@ -396,21 +411,6 @@
 
 # Files that are generated by html_to_js() or other build rule.
 generated_web_component_files = [
-  "chromeos/multidevice_page/multidevice_combined_setup_item.js",
-  "chromeos/multidevice_page/multidevice_feature_item.js",
-  "chromeos/multidevice_page/multidevice_feature_toggle.js",
-  "chromeos/multidevice_page/multidevice_notification_access_setup_dialog.js",
-  "chromeos/multidevice_page/multidevice_page.js",
-  "chromeos/multidevice_page/multidevice_permissions_setup_dialog.js",
-  "chromeos/multidevice_page/multidevice_radio_button.js",
-  "chromeos/multidevice_page/multidevice_screen_lock_subpage.js",
-  "chromeos/multidevice_page/multidevice_smartlock_item.js",
-  "chromeos/multidevice_page/multidevice_subpage.js",
-  "chromeos/multidevice_page/multidevice_task_continuation_disabled_link.js",
-  "chromeos/multidevice_page/multidevice_task_continuation_item.js",
-  "chromeos/multidevice_page/multidevice_tether_item.js",
-  "chromeos/multidevice_page/multidevice_wifi_sync_disabled_link.js",
-  "chromeos/multidevice_page/multidevice_wifi_sync_item.js",
   "chromeos/nearby_share_page/nearby_share_confirm_page.js",
   "chromeos/nearby_share_page/nearby_share_contact_visibility_dialog.js",
   "chromeos/nearby_share_page/nearby_share_data_usage_dialog.js",
diff --git a/chrome/browser/resources/side_panel/customize_chrome/categories.html b/chrome/browser/resources/side_panel/customize_chrome/categories.html
index 6db0e19..469d3f7 100644
--- a/chrome/browser/resources/side_panel/customize_chrome/categories.html
+++ b/chrome/browser/resources/side_panel/customize_chrome/categories.html
@@ -21,7 +21,7 @@
 
   cr-grid {
     --cr-column-width: 1fr;
-    --cr-grid-gap: 16px 11px;
+    --cr-grid-gap: 16px 12px;
     display: block;
     margin: 0 16px 32px;
   }
diff --git a/chrome/browser/resources/side_panel/customize_chrome/themes.html b/chrome/browser/resources/side_panel/customize_chrome/themes.html
index e0f87db2..73f4ab2 100644
--- a/chrome/browser/resources/side_panel/customize_chrome/themes.html
+++ b/chrome/browser/resources/side_panel/customize_chrome/themes.html
@@ -21,7 +21,8 @@
 
   cr-grid {
     --cr-column-width: 1fr;
-    --cr-grid-gap: 16px 11px;
+    --cr-grid-gap: 16px 12px;
+    --cr-grid-width: 100%;
     display: block;
     margin: 16px 16px 32px;
   }
@@ -50,8 +51,7 @@
     }
   }
 
-  .image-container img,
-  .image-container div {
+  .image-container img {
     position: absolute;
   }
 
@@ -62,14 +62,6 @@
     transform: translateX(-50%);
   }
 
-  .label {
-    color: var(--cr-primary-text-color);
-    font-size: 11px;
-    line-height: 16px;
-    padding-top: 7px;
-    text-align: center;
-  }
-
   .image-container {
     border-radius: 12px;
   }
@@ -101,14 +93,13 @@
 <cr-grid columns="3">
   <template is="dom-repeat" id="themesRepeat" items="[[themes_]]">
     <div class="tile theme" tabindex="0" role="button"
-        on-click="onSelectTheme_">
+        on-click="onSelectTheme_" title="[[item.attribution1]]">
       <div class="image-container">
         <img is="cr-auto-img"
             auto-src="[[item.previewImageUrl.url]]"
             draggable="false">
         </img>
       </div>
-      <div class="label">[[item.attribution1]]</div>
     </div>
   </template>
 </cr-grid>
diff --git a/chrome/browser/settings/BUILD.gn b/chrome/browser/settings/BUILD.gn
index e37c3fc..84e460b 100644
--- a/chrome/browser/settings/BUILD.gn
+++ b/chrome/browser/settings/BUILD.gn
@@ -21,6 +21,7 @@
     "//components/prefs/android:java",
     "//components/user_prefs/android:java",
     "//third_party/androidx:androidx_annotation_annotation_java",
+    "//third_party/androidx:androidx_constraintlayout_constraintlayout_java",
     "//third_party/androidx:androidx_fragment_fragment_java",
     "//url:gurl_java",
   ]
diff --git a/chrome/browser/subresource_filter/BUILD.gn b/chrome/browser/subresource_filter/BUILD.gn
index 457d10fe..60457b0 100644
--- a/chrome/browser/subresource_filter/BUILD.gn
+++ b/chrome/browser/subresource_filter/BUILD.gn
@@ -13,6 +13,7 @@
 
   android_library("subresource_filter_java_test_support") {
     testonly = true
+    annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
     sources = [ "../../android/javatests/src/org/chromium/chrome/browser/subresource_filter/TestRulesetPublisher.java" ]
     deps = [ "//base:jni_java" ]
   }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index b17fbedd..4d1c5cbdf 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1764,6 +1764,7 @@
       "//chrome/browser/ash/system_web_apps/types:types",
       "//chrome/browser/browsing_data:constants",
       "//chrome/browser/cart:mojo_bindings",
+      "//chrome/browser/headless:command_processor",
       "//chrome/browser/image_editor",
       "//chrome/browser/image_editor:image_editor_component_util",
       "//chrome/browser/media/router",
@@ -5318,8 +5319,6 @@
       "webauthn/authenticator_request_sheet_model.cc",
       "webauthn/authenticator_request_sheet_model.h",
       "webauthn/hover_list_model.h",
-      "webauthn/other_mechanisms_menu_model.cc",
-      "webauthn/other_mechanisms_menu_model.h",
       "webauthn/sheet_models.cc",
       "webauthn/sheet_models.h",
       "webauthn/transport_hover_list_model.cc",
diff --git a/chrome/browser/ui/android/toolbar/java/res/layout/toolbar_tablet.xml b/chrome/browser/ui/android/toolbar/java/res/layout/toolbar_tablet.xml
index a85bec2..690712e 100644
--- a/chrome/browser/ui/android/toolbar/java/res/layout/toolbar_tablet.xml
+++ b/chrome/browser/ui/android/toolbar/java/res/layout/toolbar_tablet.xml
@@ -24,17 +24,6 @@
         android:layout_height="match_parent"
         android:orientation="horizontal" >
 
-        <org.chromium.chrome.browser.toolbar.HomeButton
-            android:id="@+id/home_button"
-            style="@style/ToolbarButton"
-            android:src="@drawable/btn_toolbar_home"
-            android:contentDescription="@string/accessibility_toolbar_btn_home"
-            android:visibility="gone"
-            app:menuMaxWidth="@dimen/home_button_list_menu_width"
-            app:menuPositionedAtEnd="false"
-            app:menuVerticalOverlapAnchor="false"
-            app:tint="@color/default_icon_color_tint_list" />
-
         <org.chromium.ui.widget.ChromeImageButton
             android:id="@+id/back_button"
             style="@style/ToolbarButton"
@@ -57,6 +46,17 @@
             app:tint="@color/default_icon_color_tint_list"
             style="@style/ToolbarButton" />
 
+        <org.chromium.chrome.browser.toolbar.HomeButton
+            android:id="@+id/home_button"
+            style="@style/ToolbarButton"
+            android:src="@drawable/btn_toolbar_home"
+            android:contentDescription="@string/accessibility_toolbar_btn_home"
+            android:visibility="gone"
+            app:menuMaxWidth="@dimen/home_button_list_menu_width"
+            app:menuPositionedAtEnd="false"
+            app:menuVerticalOverlapAnchor="false"
+            app:tint="@color/default_icon_color_tint_list" />
+
         <org.chromium.chrome.browser.omnibox.LocationBarTablet
             android:id="@+id/location_bar"
             android:layout_width="0dp"
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
index ee012d2..b7af629 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
@@ -806,6 +806,10 @@
 
     protected GURL getUrlOfVisibleNavigationEntry() {
         if (mNativeLocationBarModelAndroid == 0) return GURL.emptyGURL();
+        if (mNtpDelegate.isCurrentlyVisible()) {
+            return getTab().getUrl();
+        }
+
         return LocationBarModelJni.get().getUrlOfVisibleNavigationEntry(
                 mNativeLocationBarModelAndroid, LocationBarModel.this);
     }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java
index 440aba2..fd1b7be 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java
@@ -136,6 +136,13 @@
         mBackButton = findViewById(R.id.back_button);
         mForwardButton = findViewById(R.id.forward_button);
         mReloadButton = findViewById(R.id.refresh_button);
+
+        // Disable home button reposition that aligns with desktop ordering when TSR disabled.
+        if (!ChromeFeatureList.sTabStripRedesign.isEnabled()) {
+            // Bring home button to the top when TSR is disabled.
+            mHomeButton.bringToFront();
+        }
+
         // ImageView tinting doesn't work with LevelListDrawable, use Drawable tinting instead.
         // See https://crbug.com/891593 for details.
         // Also, using Drawable tinting doesn't work correctly with LevelListDrawable on Android L
@@ -188,18 +195,26 @@
         mHomeButton.setOnKeyListener(new KeyboardNavigationListener() {
             @Override
             public View getNextFocusForward() {
-                if (mBackButton.isFocusable()) {
-                    return findViewById(R.id.back_button);
-                } else if (mForwardButton.isFocusable()) {
-                    return findViewById(R.id.forward_button);
+                if (ChromeFeatureList.sTabStripRedesign.isEnabled()) {
+                    return findViewById(R.id.url_bar);
                 } else {
-                    return findViewById(R.id.refresh_button);
+                    if (mBackButton.isFocusable()) {
+                        return findViewById(R.id.back_button);
+                    } else if (mForwardButton.isFocusable()) {
+                        return findViewById(R.id.forward_button);
+                    } else {
+                        return findViewById(R.id.refresh_button);
+                    }
                 }
             }
 
             @Override
             public View getNextFocusBackward() {
-                return findViewById(R.id.menu_button);
+                if (ChromeFeatureList.sTabStripRedesign.isEnabled()) {
+                    return findViewById(R.id.refresh_button);
+                } else {
+                    return findViewById(R.id.menu_button);
+                }
             }
         });
 
@@ -217,10 +232,14 @@
 
             @Override
             public View getNextFocusBackward() {
-                if (mHomeButton.getVisibility() == VISIBLE) {
-                    return findViewById(R.id.home_button);
-                } else {
+                if (ChromeFeatureList.sTabStripRedesign.isEnabled()) {
                     return findViewById(R.id.menu_button);
+                } else {
+                    if (mHomeButton.getVisibility() == VISIBLE) {
+                        return findViewById(R.id.home_button);
+                    } else {
+                        return findViewById(R.id.menu_button);
+                    }
                 }
             }
         });
@@ -237,7 +256,8 @@
             public View getNextFocusBackward() {
                 if (mBackButton.isFocusable()) {
                     return mBackButton;
-                } else if (mHomeButton.getVisibility() == VISIBLE) {
+                } else if (!ChromeFeatureList.sTabStripRedesign.isEnabled()
+                        && mHomeButton.getVisibility() == VISIBLE) {
                     return findViewById(R.id.home_button);
                 } else {
                     return findViewById(R.id.menu_button);
@@ -250,7 +270,12 @@
         mReloadButton.setOnKeyListener(new KeyboardNavigationListener() {
             @Override
             public View getNextFocusForward() {
-                return findViewById(R.id.url_bar);
+                if (ChromeFeatureList.sTabStripRedesign.isEnabled()
+                        && mHomeButton.getVisibility() == VISIBLE) {
+                    return findViewById(R.id.home_button);
+                } else {
+                    return findViewById(R.id.url_bar);
+                }
             }
 
             @Override
@@ -259,7 +284,8 @@
                     return mForwardButton;
                 } else if (mBackButton.isFocusable()) {
                     return mBackButton;
-                } else if (mHomeButton.getVisibility() == VISIBLE) {
+                } else if (!ChromeFeatureList.sTabStripRedesign.isEnabled()
+                        && mHomeButton.getVisibility() == VISIBLE) {
                     return findViewById(R.id.home_button);
                 } else {
                     return findViewById(R.id.menu_button);
diff --git a/chrome/browser/ui/ash/test_wallpaper_controller.cc b/chrome/browser/ui/ash/test_wallpaper_controller.cc
index 5f000d58..2f194d35 100644
--- a/chrome/browser/ui/ash/test_wallpaper_controller.cc
+++ b/chrome/browser/ui/ash/test_wallpaper_controller.cc
@@ -225,11 +225,6 @@
   NOTIMPLEMENTED();
 }
 
-void TestWallpaperController::GetOfflineWallpaperList(
-    GetOfflineWallpaperListCallback callback) {
-  NOTIMPLEMENTED();
-}
-
 void TestWallpaperController::SetAnimationDuration(
     base::TimeDelta animation_duration) {
   NOTIMPLEMENTED();
diff --git a/chrome/browser/ui/ash/test_wallpaper_controller.h b/chrome/browser/ui/ash/test_wallpaper_controller.h
index b372f23..0d4ee397 100644
--- a/chrome/browser/ui/ash/test_wallpaper_controller.h
+++ b/chrome/browser/ui/ash/test_wallpaper_controller.h
@@ -140,8 +140,6 @@
   void RemoveAlwaysOnTopWallpaper() override;
   void RemoveUserWallpaper(const AccountId& account_id) override;
   void RemovePolicyWallpaper(const AccountId& account_id) override;
-  void GetOfflineWallpaperList(
-      GetOfflineWallpaperListCallback callback) override;
   void SetAnimationDuration(base::TimeDelta animation_duration) override;
   void OpenWallpaperPickerIfAllowed() override;
   void MinimizeInactiveWindows(const std::string& user_id_hash) override;
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc b/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc
index a319996..4ce81360c 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc
+++ b/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc
@@ -378,11 +378,6 @@
   wallpaper_controller_->RemovePolicyWallpaper(account_id);
 }
 
-void WallpaperControllerClientImpl::GetOfflineWallpaperList(
-    ash::WallpaperController::GetOfflineWallpaperListCallback callback) {
-  wallpaper_controller_->GetOfflineWallpaperList(std::move(callback));
-}
-
 void WallpaperControllerClientImpl::SetAnimationDuration(
     const base::TimeDelta& animation_duration) {
   wallpaper_controller_->SetAnimationDuration(animation_duration);
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client_impl.h b/chrome/browser/ui/ash/wallpaper_controller_client_impl.h
index 18fc083..bd8a050 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client_impl.h
+++ b/chrome/browser/ui/ash/wallpaper_controller_client_impl.h
@@ -125,8 +125,6 @@
   void RemoveAlwaysOnTopWallpaper();
   void RemoveUserWallpaper(const AccountId& account_id);
   void RemovePolicyWallpaper(const AccountId& account_id);
-  void GetOfflineWallpaperList(
-      ash::WallpaperController::GetOfflineWallpaperListCallback callback);
   void SetAnimationDuration(const base::TimeDelta& animation_duration);
   void OpenWallpaperPickerIfAllowed();
   void MinimizeInactiveWindows(const std::string& user_id_hash);
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
index 3448d6c0..d9222b5 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
 #include "chrome/browser/defaults.h"
+#include "chrome/browser/headless/headless_command_processor.h"
 #include "chrome/browser/infobars/simple_alert_infobar_creator.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_service.h"
@@ -342,6 +343,23 @@
       browser->tab_strip_model()->ActivateTabAt(0);
   }
 
+  if (headless::ShouldProcessHeadlessCommands()) {
+    // Headless mode is restricted to only one url in the command line, so
+    // just grab the actave tab assuming it's the target.
+    content::WebContents* web_contents =
+        browser->tab_strip_model()->GetActiveWebContents();
+    if (web_contents) {
+      headless::ProcessHeadlessCommands(profile_, web_contents->GetVisibleURL(),
+                                        base::BindOnce(
+                                            [](base::WeakPtr<Browser> browser) {
+                                              if (browser->window()) {
+                                                browser->window()->Close();
+                                              }
+                                            },
+                                            browser->AsWeakPtr()));
+    }
+  }
+
 #if BUILDFLAG(IS_MAC)
   // On Mac, LaunchServices will send activation events if necessary.
   // Prefer not activating non-minimized browser window when opening new tabs,
diff --git a/chrome/browser/ui/tabs/tab_strip_model_stats_recorder.cc b/chrome/browser/ui/tabs/tab_strip_model_stats_recorder.cc
index 60de26b..635747d 100644
--- a/chrome/browser/ui/tabs/tab_strip_model_stats_recorder.cc
+++ b/chrome/browser/ui/tabs/tab_strip_model_stats_recorder.cc
@@ -66,16 +66,8 @@
 
   switch (current_state_) {
     case TabState::INITIAL:
-      break;
     case TabState::ACTIVE:
-      UMA_HISTOGRAM_ENUMERATION("Tabs.StateTransfer.Target_Active",
-                                static_cast<int>(new_state),
-                                static_cast<int>(TabState::MAX));
-      break;
     case TabState::INACTIVE:
-      UMA_HISTOGRAM_ENUMERATION("Tabs.StateTransfer.Target_Inactive",
-                                static_cast<int>(new_state),
-                                static_cast<int>(TabState::MAX));
       break;
     case TabState::CLOSED:
     case TabState::MAX:
diff --git a/chrome/browser/ui/tabs/tab_strip_model_stats_recorder_unittest.cc b/chrome/browser/ui/tabs/tab_strip_model_stats_recorder_unittest.cc
index 88f280a..f6fba6c 100644
--- a/chrome/browser/ui/tabs/tab_strip_model_stats_recorder_unittest.cc
+++ b/chrome/browser/ui/tabs/tab_strip_model_stats_recorder_unittest.cc
@@ -24,140 +24,6 @@
 class TabStripModelStatsRecorderTest : public ChromeRenderViewHostTestHarness {
 };
 
-TEST_F(TabStripModelStatsRecorderTest, BasicTabLifecycle) {
-  TestTabStripModelDelegate delegate;
-  TabStripModel tabstrip(&delegate, profile());
-
-  TabStripModelStatsRecorder recorder;
-  tabstrip.AddObserver(&recorder);
-
-  HistogramTester tester;
-
-  // Insert the first tab.
-  std::unique_ptr<WebContents> contents1 = CreateTestWebContents();
-  WebContents* raw_contents1 = contents1.get();
-  tabstrip.InsertWebContentsAt(0, std::move(contents1),
-                               AddTabTypes::ADD_ACTIVE);
-
-  // Deactivate the first tab by inserting new tab.
-  std::unique_ptr<WebContents> contents2 = CreateTestWebContents();
-  WebContents* raw_contents2 = contents2.get();
-  tabstrip.InsertWebContentsAt(1, std::move(contents2),
-                               AddTabTypes::ADD_ACTIVE);
-
-  tester.ExpectUniqueSample(
-      "Tabs.StateTransfer.Target_Active",
-      static_cast<int>(TabStripModelStatsRecorder::TabState::INACTIVE), 1);
-
-  // Reactivate the first tab.
-  tabstrip.ActivateTabAt(tabstrip.GetIndexOfWebContents(raw_contents1),
-                         TabStripUserGestureDetails(
-                             TabStripUserGestureDetails::GestureType::kOther));
-
-  tester.ExpectUniqueSample(
-      "Tabs.StateTransfer.Target_Active",
-      static_cast<int>(TabStripModelStatsRecorder::TabState::INACTIVE), 2);
-  tester.ExpectUniqueSample(
-      "Tabs.StateTransfer.Target_Inactive",
-      static_cast<int>(TabStripModelStatsRecorder::TabState::ACTIVE), 1);
-  tester.ExpectUniqueSample(
-      "Tabs.StateTransfer.NumberOfOtherTabsActivatedBeforeMadeActive", 1, 1);
-
-  // Replace the contents of the first tab.
-  // TabStripModeStatsRecorder should follow WebContents change.
-  std::unique_ptr<WebContents> contents3 = CreateTestWebContents();
-  tabstrip.ReplaceWebContentsAt(0, std::move(contents3));
-
-  // Close the inactive second tab.
-  tabstrip.CloseWebContentsAt(tabstrip.GetIndexOfWebContents(raw_contents2),
-                              TabCloseTypes::CLOSE_USER_GESTURE |
-                                  TabCloseTypes::CLOSE_CREATE_HISTORICAL_TAB);
-
-  tester.ExpectBucketCount(
-      "Tabs.StateTransfer.Target_Inactive",
-      static_cast<int>(TabStripModelStatsRecorder::TabState::CLOSED), 1);
-
-  // Close the active first tab.
-  tabstrip.CloseSelectedTabs();
-  tester.ExpectBucketCount(
-      "Tabs.StateTransfer.Target_Active",
-      static_cast<int>(TabStripModelStatsRecorder::TabState::CLOSED), 1);
-
-  tabstrip.RemoveObserver(&recorder);
-
-  tabstrip.CloseAllTabs();
-}
-
-TEST_F(TabStripModelStatsRecorderTest, ObserveMultipleTabStrips) {
-  TestTabStripModelDelegate delegate;
-  TabStripModel tabstrip1(&delegate, profile());
-  TabStripModel tabstrip2(&delegate, profile());
-
-  TabStripModelStatsRecorder recorder;
-  tabstrip1.AddObserver(&recorder);
-  tabstrip2.AddObserver(&recorder);
-
-  HistogramTester tester;
-
-  // Create a tab in strip 1.
-  tabstrip1.InsertWebContentsAt(0, CreateTestWebContents(),
-                                AddTabTypes::ADD_ACTIVE);
-
-  // Create a tab in strip 2.
-  tabstrip2.InsertWebContentsAt(0, CreateTestWebContents(),
-                                AddTabTypes::ADD_ACTIVE);
-
-  // Create another tab in strip 1.
-  tabstrip1.InsertWebContentsAt(1, CreateTestWebContents(),
-                                AddTabTypes::ADD_ACTIVE);
-
-  tester.ExpectUniqueSample(
-      "Tabs.StateTransfer.Target_Active",
-      static_cast<int>(TabStripModelStatsRecorder::TabState::INACTIVE), 1);
-
-  // Create another tab in strip 2.
-  tabstrip2.InsertWebContentsAt(1, CreateTestWebContents(),
-                                AddTabTypes::ADD_ACTIVE);
-
-  tester.ExpectUniqueSample(
-      "Tabs.StateTransfer.Target_Active",
-      static_cast<int>(TabStripModelStatsRecorder::TabState::INACTIVE), 2);
-
-  // Move the first tab in strip 1 to strip 2
-  tabstrip2.InsertWebContentsAt(2, tabstrip1.DetachWebContentsAtForInsertion(0),
-                                AddTabTypes::ADD_ACTIVE);
-
-  tester.ExpectUniqueSample(
-      "Tabs.StateTransfer.Target_Active",
-      static_cast<int>(TabStripModelStatsRecorder::TabState::INACTIVE), 3);
-  tester.ExpectUniqueSample(
-      "Tabs.StateTransfer.Target_Inactive",
-      static_cast<int>(TabStripModelStatsRecorder::TabState::ACTIVE), 1);
-
-  // Switch to the first tab in strip 2.
-  tabstrip2.ActivateTabAt(0,
-                          TabStripUserGestureDetails(
-                              TabStripUserGestureDetails::GestureType::kOther));
-  tester.ExpectUniqueSample(
-      "Tabs.StateTransfer.Target_Active",
-      static_cast<int>(TabStripModelStatsRecorder::TabState::INACTIVE), 4);
-  tester.ExpectUniqueSample(
-      "Tabs.StateTransfer.Target_Inactive",
-      static_cast<int>(TabStripModelStatsRecorder::TabState::ACTIVE), 2);
-
-  // Close the first tab in strip 2.
-  tabstrip2.CloseSelectedTabs();
-  tester.ExpectBucketCount(
-      "Tabs.StateTransfer.Target_Active",
-      static_cast<int>(TabStripModelStatsRecorder::TabState::CLOSED), 1);
-
-  tabstrip1.RemoveObserver(&recorder);
-  tabstrip2.RemoveObserver(&recorder);
-
-  tabstrip1.CloseAllTabs();
-  tabstrip2.CloseAllTabs();
-}
-
 TEST_F(TabStripModelStatsRecorderTest,
        NumberOfOtherTabsActivatedBeforeMadeActive) {
   TestTabStripModelDelegate delegate;
diff --git a/chrome/browser/ui/views/accessibility/accessibility_focus_highlight.cc b/chrome/browser/ui/views/accessibility/accessibility_focus_highlight.cc
index 755fd87..8257776 100644
--- a/chrome/browser/ui/views/accessibility/accessibility_focus_highlight.cc
+++ b/chrome/browser/ui/views/accessibility/accessibility_focus_highlight.cc
@@ -293,7 +293,7 @@
     // Decrease alpha as distance remaining decreases.
     int alpha = (original_alpha * remaining * remaining) /
                 (kGradientWidth * kGradientWidth);
-    gradient_flags.setAlpha(alpha);
+    gradient_flags.setAlphaf(alpha / 255.0f);
 
     recorder.canvas()->DrawRoundRect(gradient_bounds, gradient_border_radius,
                                      gradient_flags);
diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc
index 0764829..726e05f 100644
--- a/chrome/browser/ui/views/download/download_item_view.cc
+++ b/chrome/browser/ui/views/download/download_item_view.cc
@@ -655,7 +655,7 @@
     cc::PaintFlags flags;
     // Use an alpha to make the image look disabled.
     if (!GetEnabled())
-      flags.setAlpha(120);
+      flags.setAlphaf(120.0f / 255.0f);
     canvas->DrawImageInt(*file_icon, progress_x + offset, progress_y + offset,
                          flags);
   }
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.cc b/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.cc
index f9ed267..489fdea 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.cc
+++ b/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.cc
@@ -227,16 +227,20 @@
   UpdateSiteSettingToggleText(site_settings_toggle_);
 }
 
-void ExtensionsMenuMainPageView::Update() {
-  content::WebContents* web_contents = GetActiveWebContents();
-  if (web_contents) {
-    subheader_subtitle_->SetText(GetCurrentSite(web_contents));
+void ExtensionsMenuMainPageView::Update(content::WebContents* web_contents) {
+  DCHECK(web_contents);
 
-    site_settings_toggle_->SetVisible(
-        IsSiteSettingsToggleVisible(toolbar_model_, web_contents));
-    site_settings_toggle_->SetIsOn(
-        IsSiteSettingsToggleOn(browser_, web_contents));
-    UpdateSiteSettingToggleText(site_settings_toggle_);
+  subheader_subtitle_->SetText(GetCurrentSite(web_contents));
+
+  site_settings_toggle_->SetVisible(
+      IsSiteSettingsToggleVisible(toolbar_model_, web_contents));
+  site_settings_toggle_->SetIsOn(
+      IsSiteSettingsToggleOn(browser_, web_contents));
+  UpdateSiteSettingToggleText(site_settings_toggle_);
+
+  // Update menu items.
+  for (auto* view : menu_items_->children()) {
+    GetAsMenuItem(view)->Update();
   }
 }
 
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.h b/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.h
index 9cfcc77..7dbbdcf 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.h
+++ b/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.h
@@ -44,7 +44,7 @@
   void OnToggleButtonPressed();
 
   // ExtensionsMenuPageView:
-  void Update() override;
+  void Update(content::WebContents* web_contents) override;
 
   // Accessors used by tests:
   // Returns the currently-showing menu items.
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_page_view.h b/chrome/browser/ui/views/extensions/extensions_menu_page_view.h
index f5595b7..c0f6432 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_page_view.h
+++ b/chrome/browser/ui/views/extensions/extensions_menu_page_view.h
@@ -7,12 +7,18 @@
 
 #include "ui/views/view.h"
 
+namespace content {
+class WebContents;
+}  // namespace content
+
 // An interface for pages in the extensions menu.
 class ExtensionsMenuPageView : public views::View {
  public:
   // TODO(crbug.com/1390952): Move shared page view construction from "main
   // page" and "site permissions page".
-  virtual void Update() = 0;
+
+  // Updates the menu page for `web_contents`.
+  virtual void Update(content::WebContents* web_contents) = 0;
 };
 
 BEGIN_VIEW_BUILDER(/* no export */, ExtensionsMenuPageView, views::View)
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_site_permissions_page_view.cc b/chrome/browser/ui/views/extensions/extensions_menu_site_permissions_page_view.cc
index cb4b0e3..fddfa54 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_site_permissions_page_view.cc
+++ b/chrome/browser/ui/views/extensions/extensions_menu_site_permissions_page_view.cc
@@ -63,4 +63,5 @@
 }
 
 // TODO(crbug.com/1390952): Update content once content is added to this page.
-void ExtensionsMenuSitePermissionsPage::Update() {}
+void ExtensionsMenuSitePermissionsPage::Update(
+    content::WebContents* web_contents) {}
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_site_permissions_page_view.h b/chrome/browser/ui/views/extensions/extensions_menu_site_permissions_page_view.h
index f9927f6..8729655 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_site_permissions_page_view.h
+++ b/chrome/browser/ui/views/extensions/extensions_menu_site_permissions_page_view.h
@@ -20,7 +20,7 @@
   ~ExtensionsMenuSitePermissionsPage() override = default;
 
   // ExtensionsMenuPageView:
-  void Update() override;
+  void Update(content::WebContents* web_contents) override;
 };
 
 BEGIN_VIEW_BUILDER(/* no export */,
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_view_controller.cc b/chrome/browser/ui/views/extensions/extensions_menu_view_controller.cc
index c9386b1..f978fc8 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_view_controller.cc
+++ b/chrome/browser/ui/views/extensions/extensions_menu_view_controller.cc
@@ -8,9 +8,11 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/extensions/extension_action_view_controller.h"
 #include "chrome/browser/ui/extensions/extensions_container.h"
+#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "chrome/browser/ui/views/extensions/extensions_menu_main_page_view.h"
 #include "chrome/browser/ui/views/extensions/extensions_menu_page_view.h"
 #include "chrome/browser/ui/views/extensions/extensions_menu_site_permissions_page_view.h"
+#include "content/public/browser/web_contents.h"
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
 #include "ui/views/view_utils.h"
 #include "ui/views/widget/widget.h"
@@ -81,15 +83,19 @@
                                                 int index,
                                                 TabChangeType change_type) {
   DCHECK(current_page_);
-  current_page_->Update();
+  current_page_->Update(contents);
 }
 
 void ExtensionsMenuViewController::OnTabStripModelChanged(
     TabStripModel* tab_strip_model,
     const TabStripModelChange& change,
     const TabStripSelectionChange& selection) {
-  DCHECK(current_page_);
-  current_page_->Update();
+  content::WebContents* web_contents = tab_strip_model->GetActiveWebContents();
+  if (!selection.active_tab_changed() || !web_contents) {
+    return;
+  }
+
+  current_page_->Update(browser_->tab_strip_model()->GetActiveWebContents());
 }
 
 // TODO(crbug.com/1390952): Listen for "toolbar pinned actions changed" to
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
index e3df9b0..6628f075 100644
--- a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
+++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
@@ -87,10 +87,14 @@
   if (!base::FeatureList::IsEnabled(media::kMediaRemotingWithoutFullscreen) ||
       !item ||
       item->SourceType() !=
-          media_message_center::SourceType::kLocalMediaSession ||
-      !static_cast<global_media_controls::MediaSessionNotificationItem*>(
-           item.get())
-           ->GetRemotePlaybackMetadata()
+          media_message_center::SourceType::kLocalMediaSession) {
+    return "";
+  }
+  const auto* media_session_item =
+      static_cast<global_media_controls::MediaSessionNotificationItem*>(
+          item.get());
+  if (!media_session_item->GetRemotePlaybackMetadata() ||
+      !media_session_item->GetRemotePlaybackMetadata()
            ->remote_playback_started) {
     return "";
   }
@@ -535,7 +539,7 @@
     return footer_view;
   }
 
-  // Show a footerview for a Cast item.
+  // Show a footer view for a Cast item.
   if (item->SourceType() == media_message_center::SourceType::kCast &&
       media_router::GlobalMediaControlsCastStartStopEnabled(profile_)) {
     return std::make_unique<MediaItemUILegacyCastFooterView>(
diff --git a/chrome/browser/ui/views/webauthn/authenticator_dialog_view_browsertest.cc b/chrome/browser/ui/views/webauthn/authenticator_dialog_view_browsertest.cc
index 818a535..e28b7a23 100644
--- a/chrome/browser/ui/views/webauthn/authenticator_dialog_view_browsertest.cc
+++ b/chrome/browser/ui/views/webauthn/authenticator_dialog_view_browsertest.cc
@@ -73,8 +73,6 @@
     return u"You must construct additional pylons.";
   }
 
-  ui::MenuModel* GetOtherMechanismsMenuModel() override { return nullptr; }
-
   void OnBack() override {}
   void OnAccept() override {}
   void OnCancel() override {}
diff --git a/chrome/browser/ui/views/webauthn/authenticator_paask_sheet_view.cc b/chrome/browser/ui/views/webauthn/authenticator_paask_sheet_view.cc
index c50886d..acbeb295 100644
--- a/chrome/browser/ui/views/webauthn/authenticator_paask_sheet_view.cc
+++ b/chrome/browser/ui/views/webauthn/authenticator_paask_sheet_view.cc
@@ -5,11 +5,9 @@
 #include <memory>
 #include <utility>
 
-#include "base/feature_list.h"
 #include "chrome/browser/ui/views/webauthn/authenticator_paask_sheet_view.h"
 #include "chrome/browser/ui/webauthn/sheet_models.h"
 #include "chrome/grit/generated_resources.h"
-#include "device/fido/features.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/views/border.h"
@@ -50,37 +48,11 @@
     return std::make_pair(nullptr, AutoFocus::kNo);
   }
 
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return std::make_pair(
-        std::make_unique<LinkLabelButton>(
-            base::BindRepeating(&AuthenticatorPaaskSheetView::OnLinkClicked,
-                                base::Unretained(this)),
-            l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLEV2_SERVERLINK_TROUBLE)),
-        AutoFocus::kNo);
-  }
-
-  std::u16string link_text;
-  switch (dialog_model->experiment_server_link_sheet_) {
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::CONTROL:
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_2:
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_3:
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_5:
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_6:
-      link_text =
-          l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLEV2_SERVERLINK_TROUBLE);
-      break;
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_4:
-      link_text = l10n_util::GetStringUTF16(
-          IDS_WEBAUTHN_CABLEV2_SERVERLINK_TROUBLE_ALT);
-      break;
-  }
-
   return std::make_pair(
       std::make_unique<LinkLabelButton>(
           base::BindRepeating(&AuthenticatorPaaskSheetView::OnLinkClicked,
                               base::Unretained(this)),
-          link_text),
+          l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLEV2_SERVERLINK_TROUBLE)),
       AutoFocus::kNo);
 }
 
diff --git a/chrome/browser/ui/views/webauthn/authenticator_qr_sheet_view.cc b/chrome/browser/ui/views/webauthn/authenticator_qr_sheet_view.cc
index caa12d17..63b15d6 100644
--- a/chrome/browser/ui/views/webauthn/authenticator_qr_sheet_view.cc
+++ b/chrome/browser/ui/views/webauthn/authenticator_qr_sheet_view.cc
@@ -4,14 +4,12 @@
 
 #include "chrome/browser/ui/views/webauthn/authenticator_qr_sheet_view.h"
 
-#include "base/feature_list.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
 #include "chrome/browser/ui/color/chrome_color_id.h"
 #include "chrome/services/qrcode_generator/public/cpp/qrcode_generator_service.h"
 #include "chrome/services/qrcode_generator/public/mojom/qrcode_generator.mojom.h"
-#include "device/fido/features.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/color/color_provider.h"
@@ -52,20 +50,12 @@
         qrcode_generator::mojom::GenerateQRCodeRequest::New();
     request->data = qr_string;
     request->should_render = true;
-    request->center_image =
-        base::FeatureList::IsEnabled(
-            device::kWebAuthnNewDiscoverableCredentialsUi) ||
-                base::FeatureList::IsEnabled(device::kWebAuthPasskeysUI)
-            ? qrcode_generator::mojom::CenterImage::PASSKEY_ICON
-            : qrcode_generator::mojom::CenterImage::CHROME_DINO;
+    request->center_image = qrcode_generator::mojom::CenterImage::PASSKEY_ICON;
 
     request->render_module_style =
         qrcode_generator::mojom::ModuleStyle::CIRCLES;
     request->render_locator_style =
-        base::FeatureList::IsEnabled(
-            device::kWebAuthnNewDiscoverableCredentialsUi)
-            ? qrcode_generator::mojom::LocatorStyle::ROUNDED
-            : qrcode_generator::mojom::LocatorStyle::DEFAULT_SQUARE;
+        qrcode_generator::mojom::LocatorStyle::ROUNDED;
 
     // Deleting the view will close the channel so base::Unretained is safe
     // here.
@@ -87,15 +77,9 @@
     const int border_radius =
         views::LayoutProvider::Get()->GetCornerRadiusMetric(
             views::Emphasis::kHigh);
-    const auto* color_provider = GetColorProvider();
-    if (!base::FeatureList::IsEnabled(
-            device::kWebAuthnNewDiscoverableCredentialsUi)) {
-      qr_code_image_->SetBorder(views::CreateRoundedRectBorder(
-          /*thickness=*/2, border_radius,
-          color_provider->GetColor(kColorQrCodeBorder)));
-    }
     qr_code_image_->SetBackground(views::CreateRoundedRectBackground(
-        color_provider->GetColor(kColorQrCodeBackground), border_radius, 2));
+        GetColorProvider()->GetColor(kColorQrCodeBackground), border_radius,
+        2));
   }
 
  private:
diff --git a/chrome/browser/ui/views/webauthn/authenticator_request_dialog_view.cc b/chrome/browser/ui/views/webauthn/authenticator_request_dialog_view.cc
index a2b60c7..40bebe9 100644
--- a/chrome/browser/ui/views/webauthn/authenticator_request_dialog_view.cc
+++ b/chrome/browser/ui/views/webauthn/authenticator_request_dialog_view.cc
@@ -9,7 +9,6 @@
 #include "base/logging.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/chrome_typography.h"
-#include "chrome/browser/ui/views/controls/md_text_button_with_down_arrow.h"
 #include "chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.h"
 #include "chrome/browser/ui/views/webauthn/sheet_view_factory.h"
 #include "chrome/browser/ui/webauthn/authenticator_request_sheet_model.h"
@@ -18,16 +17,13 @@
 #include "components/strings/grit/components_strings.h"
 #include "components/web_modal/web_contents_modal_dialog_manager.h"
 #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h"
-#include "device/fido/features.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
-#include "ui/gfx/color_utils.h"
 #include "ui/gfx/geometry/insets.h"
-#include "ui/gfx/paint_vector_icon.h"
-#include "ui/views/border.h"
+#include "ui/views/controls/button/label_button.h"
+#include "ui/views/controls/button/md_text_button.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/fill_layout.h"
-#include "ui/views/vector_icons.h"
 
 // static
 void ShowAuthenticatorRequestDialog(content::WebContents* web_contents,
@@ -44,8 +40,9 @@
   // should audit this.
   auto* manager = web_modal::WebContentsModalDialogManager::FromWebContents(
       constrained_window::GetTopLevelWebContents(web_contents));
-  if (!manager)
+  if (!manager) {
     return;
+  }
 
   new AuthenticatorRequestDialogView(web_contents, model);
 }
@@ -90,10 +87,12 @@
   sheet_->ReInitChildViews();
 
   int buttons = ui::DIALOG_BUTTON_NONE;
-  if (sheet()->model()->IsAcceptButtonVisible())
+  if (sheet()->model()->IsAcceptButtonVisible()) {
     buttons |= ui::DIALOG_BUTTON_OK;
-  if (sheet()->model()->IsCancelButtonVisible())
+  }
+  if (sheet()->model()->IsCancelButtonVisible()) {
     buttons |= ui::DIALOG_BUTTON_CANCEL;
+  }
   SetButtons(buttons);
   SetDefaultButton((buttons & ui::DIALOG_BUTTON_OK) ? ui::DIALOG_BUTTON_OK
                                                     : ui::DIALOG_BUTTON_NONE);
@@ -111,8 +110,9 @@
 
   // If the widget is not yet shown or already being torn down, we are done. In
   // the former case, sizing/layout will happen once the dialog is visible.
-  if (!GetWidget())
+  if (!GetWidget()) {
     return;
+  }
 
   // Force re-layout of the entire dialog client view, which includes the sheet
   // content as well as the button row on the bottom.
@@ -125,16 +125,18 @@
   // TODO(https://crbug.com/849323): Investigate how a web-modal dialog's
   // lifetime compares to that of the parent WebContents. Take a conservative
   // approach for now.
-  if (!web_contents())
+  if (!web_contents()) {
     return;
+  }
 
   // The |dialog_manager| might temporarily be unavailable while the tab is
   // being dragged from one browser window to the other.
   auto* dialog_manager =
       web_modal::WebContentsModalDialogManager::FromWebContents(
           constrained_window::GetTopLevelWebContents(web_contents()));
-  if (!dialog_manager)
+  if (!dialog_manager) {
     return;
+  }
 
   // Update the dialog size and position, as the preferred size of the sheet
   // might have changed.
@@ -142,18 +144,14 @@
       GetWidget(), dialog_manager->delegate()->GetWebContentsModalDialogHost());
 
   // Reset focus to the highest priority control on the new/updated sheet.
-  if (GetInitiallyFocusedView())
+  if (GetInitiallyFocusedView()) {
     GetInitiallyFocusedView()->RequestFocus();
+  }
 }
 
 bool AuthenticatorRequestDialogView::ShouldOtherMechanismsButtonBeVisible()
     const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return sheet_->model()->IsOtherMechanismButtonVisible();
-  }
-  return sheet_->model()->GetOtherMechanismsMenuModel() &&
-         sheet_->model()->GetOtherMechanismsMenuModel()->GetItemCount();
+  return sheet_->model()->IsOtherMechanismButtonVisible();
 }
 
 bool AuthenticatorRequestDialogView::Accept() {
@@ -190,19 +188,22 @@
 
   views::View* intially_focused_sheet_control =
       sheet()->GetInitiallyFocusedView();
-  if (intially_focused_sheet_control)
+  if (intially_focused_sheet_control) {
     return intially_focused_sheet_control;
+  }
 
   if (sheet()->model()->IsAcceptButtonVisible() &&
       sheet()->model()->IsAcceptButtonEnabled()) {
     return GetOkButton();
   }
 
-  if (ShouldOtherMechanismsButtonBeVisible())
+  if (ShouldOtherMechanismsButtonBeVisible()) {
     return other_mechanisms_button_;
+  }
 
-  if (sheet()->model()->IsCancelButtonVisible())
+  if (sheet()->model()->IsCancelButtonVisible()) {
     return GetCancelButton();
+  }
 
   return nullptr;
 }
@@ -270,20 +271,11 @@
   hbox->SetLayoutManager(std::make_unique<views::BoxLayout>(
       views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), 0));
 
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    other_mechanisms_button_ = new views::MdTextButton(
-        base::BindRepeating(
-            &AuthenticatorRequestDialogView::OtherMechanismsButtonPressed,
-            base::Unretained(this)),
-        l10n_util::GetStringUTF16(IDS_WEBAUTHN_TRY_ANOTHER_WAY));
-  } else {
-    other_mechanisms_button_ = new views::MdTextButtonWithDownArrow(
-        base::BindRepeating(
-            &AuthenticatorRequestDialogView::OtherMechanismsButtonPressed,
-            base::Unretained(this)),
-        l10n_util::GetStringUTF16(IDS_WEBAUTHN_TRANSPORT_POPUP_LABEL));
-  }
+  other_mechanisms_button_ = new views::MdTextButton(
+      base::BindRepeating(
+          &AuthenticatorRequestDialogView::OtherMechanismsButtonPressed,
+          base::Unretained(this)),
+      l10n_util::GetStringUTF16(IDS_WEBAUTHN_TRY_ANOTHER_WAY));
   hbox->AddChildView(other_mechanisms_button_.get());
 
   manage_devices_button_ = new views::MdTextButton(
@@ -331,25 +323,7 @@
 }
 
 void AuthenticatorRequestDialogView::OtherMechanismsButtonPressed() {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    sheet_->model()->OnBack();
-    return;
-  }
-
-  auto* other_mechanisms_menu_model =
-      sheet_->model()->GetOtherMechanismsMenuModel();
-  DCHECK(other_mechanisms_menu_model);
-  DCHECK_GE(other_mechanisms_menu_model->GetItemCount(), 1u);
-
-  other_mechanisms_menu_runner_ = std::make_unique<views::MenuRunner>(
-      other_mechanisms_menu_model, views::MenuRunner::COMBOBOX);
-
-  gfx::Rect anchor_bounds = other_mechanisms_button_->GetBoundsInScreen();
-  other_mechanisms_menu_runner_->RunMenuAt(
-      other_mechanisms_button_->GetWidget(), nullptr /* MenuButtonController */,
-      anchor_bounds, views::MenuAnchorPosition::kTopLeft,
-      ui::MENU_SOURCE_MOUSE);
+  sheet_->model()->OnBack();
 }
 
 void AuthenticatorRequestDialogView::ManageDevicesButtonPressed() {
@@ -382,8 +356,9 @@
   // This should not be a problem as the native widget will never synchronously
   // close and hence not synchronously destroy the model while it's iterating
   // over observers in SetCurrentStep().
-  if (model_ && !model_->should_dialog_be_closed())
+  if (model_ && !model_->should_dialog_be_closed()) {
     Cancel();
+  }
 }
 
 BEGIN_METADATA(AuthenticatorRequestDialogView, views::DialogDelegateView)
diff --git a/chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.cc b/chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.cc
index c2b17ed..983f907 100644
--- a/chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.cc
+++ b/chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.cc
@@ -7,7 +7,6 @@
 #include <memory>
 #include <utility>
 
-#include "base/feature_list.h"
 #include "chrome/browser/ui/color/chrome_color_id.h"
 #include "chrome/browser/ui/views/accessibility/non_accessible_image_view.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
@@ -17,7 +16,6 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/vector_icons/vector_icons.h"
-#include "device/fido/features.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/color/color_provider.h"
@@ -86,25 +84,18 @@
 
 std::unique_ptr<views::View>
 AuthenticatorRequestSheetView::CreateIllustrationWithOverlays() {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    // Some sheets do not have an illustration.
-    const gfx::VectorIcon& illustration =
-        model()->GetStepIllustration(ImageColorScheme::kLight);
-    if (&illustration == &gfx::kNoneIcon) {
-      return std::make_unique<views::View>();
-    }
+  // Some sheets do not have an illustration.
+  const gfx::VectorIcon& illustration =
+      model()->GetStepIllustration(ImageColorScheme::kLight);
+  if (&illustration == &gfx::kNoneIcon) {
+    return std::make_unique<views::View>();
   }
 
   const int dialog_width = ChromeLayoutProvider::Get()->GetDistanceMetric(
       views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH);
   constexpr int kImageHeight = 112, kImageMarginTop = 22,
                 kImageMarginBottom = 2;
-  const int header_height =
-      base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)
-          ? (kImageHeight + kImageMarginTop + kImageMarginBottom)
-          : 148;
+  const int header_height = kImageHeight + kImageMarginTop + kImageMarginBottom;
   const gfx::Size image_view_size(dialog_width, header_height);
 
   // The container view has no layout, so its preferred size is hardcoded to
@@ -114,11 +105,8 @@
 
   auto image_view = std::make_unique<NonAccessibleImageView>();
   step_illustration_ = image_view.get();
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    image_view->SetBorder(views::CreateEmptyBorder(
-        gfx::Insets::TLBR(kImageMarginTop, 0, kImageMarginTop, 0)));
-  }
+  image_view->SetBorder(views::CreateEmptyBorder(
+      gfx::Insets::TLBR(kImageMarginTop, 0, kImageMarginTop, 0)));
   image_view->SetSize(image_view_size);
   image_view->SetVerticalAlignment(views::ImageView::Alignment::kLeading);
   header_view->AddChildView(image_view.release());
@@ -134,44 +122,6 @@
     header_view->AddChildView(activity_indicator.release());
   }
 
-  if (!base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi) &&
-      model()->IsBackButtonVisible()) {
-    auto back_arrow = views::CreateVectorImageButton(base::BindRepeating(
-        &AuthenticatorRequestSheetModel::OnBack, base::Unretained(model())));
-    back_arrow->SetAccessibleName(l10n_util::GetStringUTF16(
-        IDS_BACK_BUTTON_AUTHENTICATOR_REQUEST_DIALOG));
-
-    // Position the back button so that there is the standard amount of padding
-    // between the top/left side of the back button and the dialog borders.
-    const gfx::Insets dialog_insets =
-        views::LayoutProvider::Get()->GetDialogInsetsForContentType(
-            views::DialogContentType::kControl,
-            views::DialogContentType::kControl);
-    auto color_reference = std::make_unique<views::Label>(
-        std::u16string(), views::style::CONTEXT_DIALOG_TITLE,
-        views::style::STYLE_PRIMARY);
-    back_arrow->SizeToPreferredSize();
-    back_arrow->SetX(dialog_insets.left());
-    back_arrow->SetY(dialog_insets.top());
-    back_arrow_ = back_arrow.get();
-    back_arrow_button_ = header_view->AddChildView(std::move(back_arrow));
-  }
-  if (!base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi) &&
-      model()->IsCloseButtonVisible()) {
-    auto close = views::CreateVectorImageButton(base::BindRepeating(
-        &AuthenticatorRequestSheetModel::OnCancel, base::Unretained(model())));
-    close->SetAccessibleName(
-        l10n_util::GetStringUTF16(IDS_NEW_TAB_VOICE_CLOSE_TOOLTIP));
-    close->SizeToPreferredSize();
-    close->SetX(dialog_width - close->GetPreferredSize().width() -
-                kActivityIndicatorHeight);
-    close->SetY(kActivityIndicatorHeight);
-    close_button_ = close.get();
-    header_view->AddChildView(std::move(close));
-  }
-
   if (GetWidget()) {
     UpdateIconImageFromModel();
     UpdateIconColors();
@@ -263,8 +213,9 @@
 }
 
 void AuthenticatorRequestSheetView::UpdateIconImageFromModel() {
-  if (!step_illustration_)
+  if (!step_illustration_) {
     return;
+  }
 
   gfx::IconDescription icon_description(model()->GetStepIllustration(
       GetNativeTheme()->ShouldUseDarkColors() ? ImageColorScheme::kDark
diff --git a/chrome/browser/ui/views/webauthn/hover_list_view.cc b/chrome/browser/ui/views/webauthn/hover_list_view.cc
index c953acb1..d8e92fc2 100644
--- a/chrome/browser/ui/views/webauthn/hover_list_view.cc
+++ b/chrome/browser/ui/views/webauthn/hover_list_view.cc
@@ -36,8 +36,7 @@
     const ui::ImageModel& icon,
     std::u16string item_title,
     std::u16string item_description,
-    views::Button::PressedCallback callback,
-    bool is_two_line_item) {
+    views::Button::PressedCallback callback) {
   constexpr int kChevronSize = 8;
   auto secondary_view =
       std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
@@ -49,7 +48,7 @@
 
   return std::make_unique<WebAuthnHoverButton>(
       std::move(callback), std::move(item_image), item_title, item_description,
-      std::move(secondary_view), is_two_line_item);
+      std::move(secondary_view), false /*XXX*/);
 }
 
 }  // namespace
@@ -57,7 +56,7 @@
 // HoverListView ---------------------------------------------------------
 
 HoverListView::HoverListView(std::unique_ptr<HoverListModel> model)
-    : model_(std::move(model)), is_two_line_list_(model_->StyleForTwoLines()) {
+    : model_(std::move(model)) {
   DCHECK(model_);
   SetLayoutManager(std::make_unique<views::FillLayout>());
 
@@ -91,8 +90,7 @@
   auto hover_button = CreateHoverButtonForListItem(
       icon, item_text, description_text,
       base::BindRepeating(&HoverListModel::OnListItemSelected,
-                          base::Unretained(model_.get()), item_tag),
-      is_two_line_list_);
+                          base::Unretained(model_.get()), item_tag));
 
   auto* list_item_view_ptr = hover_button.release();
   item_container_->AddChildView(list_item_view_ptr);
@@ -108,8 +106,9 @@
 }
 
 void HoverListView::RequestFocus() {
-  if (tags_to_list_item_views_.empty())
+  if (tags_to_list_item_views_.empty()) {
     return;
+  }
 
   GetTopListItemView().RequestFocus();
 }
@@ -130,7 +129,7 @@
   if (reserved_items > 0) {
     auto dummy_hover_button = CreateHoverButtonForListItem(
         ui::ImageModel(), std::u16string(), std::u16string(),
-        views::Button::PressedCallback(), is_two_line_list_);
+        views::Button::PressedCallback());
     const auto list_item_height =
         separator_height + dummy_hover_button->GetPreferredSize().height();
     size += list_item_height * reserved_items;
diff --git a/chrome/browser/ui/views/webauthn/hover_list_view.h b/chrome/browser/ui/views/webauthn/hover_list_view.h
index 281f1bf7..74a4c79 100644
--- a/chrome/browser/ui/views/webauthn/hover_list_view.h
+++ b/chrome/browser/ui/views/webauthn/hover_list_view.h
@@ -66,10 +66,6 @@
   std::map<int, ListItemViews> tags_to_list_item_views_;
   raw_ptr<views::ScrollView> scroll_view_;
   raw_ptr<views::View> item_container_;
-  // is_two_line_list_, if true, indicates that list items should be sized so
-  // that entries with only a single line of text are as tall as entries with
-  // two lines.
-  const bool is_two_line_list_;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_WEBAUTHN_HOVER_LIST_VIEW_H_
diff --git a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
index 2e31c04..121ab9f7 100644
--- a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
+++ b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/check.h"
-#include "base/feature_list.h"
 #include "build/build_config.h"
 #include "chrome/browser/ui/autofill/payments/webauthn_dialog_model.h"
 #include "chrome/browser/ui/views/webauthn/authenticator_bio_enrollment_sheet_view.h"
@@ -22,7 +21,6 @@
 #include "chrome/browser/ui/webauthn/sheet_models.h"
 #include "chrome/browser/ui/webauthn/transport_hover_list_model.h"
 #include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
-#include "device/fido/features.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/gfx/text_constants.h"
 #include "ui/views/controls/label.h"
@@ -265,8 +263,6 @@
               AuthenticatorSelectAccountSheetModel::kMultipleAccounts));
       break;
     case Step::kSelectSingleAccount:
-      DCHECK(base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi));
       sheet_view = std::make_unique<AuthenticatorSelectAccountSheetView>(
           std::make_unique<AuthenticatorSelectAccountSheetModel>(
               dialog_model,
@@ -274,8 +270,6 @@
               AuthenticatorSelectAccountSheetModel::kSingleAccount));
       break;
     case Step::kPreSelectAccount:
-      DCHECK(base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi));
       sheet_view = std::make_unique<AuthenticatorSelectAccountSheetView>(
           std::make_unique<AuthenticatorSelectAccountSheetModel>(
               dialog_model,
@@ -283,8 +277,6 @@
               AuthenticatorSelectAccountSheetModel::kMultipleAccounts));
       break;
     case Step::kPreSelectSingleAccount:
-      DCHECK(base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi));
       sheet_view = std::make_unique<AuthenticatorSelectAccountSheetView>(
           std::make_unique<AuthenticatorSelectAccountSheetModel>(
               dialog_model,
diff --git a/chrome/browser/ui/webauthn/account_hover_list_model.cc b/chrome/browser/ui/webauthn/account_hover_list_model.cc
index f7a4f28e..082193bb 100644
--- a/chrome/browser/ui/webauthn/account_hover_list_model.cc
+++ b/chrome/browser/ui/webauthn/account_hover_list_model.cc
@@ -6,7 +6,6 @@
 
 #include <string>
 
-#include "base/feature_list.h"
 #include "base/functional/bind.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/app/vector_icons/vector_icons.h"
@@ -14,7 +13,6 @@
 #include "components/vector_icons/vector_icons.h"
 #include "device/fido/authenticator_get_assertion_response.h"
 #include "device/fido/discoverable_credential_metadata.h"
-#include "device/fido/features.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/image_model.h"
 #include "ui/color/color_id.h"
@@ -24,8 +22,9 @@
 
 namespace {
 std::u16string NameTokenForDisplay(base::StringPiece name_token) {
-  if (name_token.empty())
+  if (name_token.empty()) {
     return l10n_util::GetStringUTF16(IDS_WEBAUTHN_UNKNOWN_ACCOUNT);
+  }
   return base::UTF8ToUTF16(name_token);
 }
 }  // namespace
@@ -34,21 +33,11 @@
     base::span<const device::DiscoverableCredentialMetadata> creds,
     Delegate* delegate)
     : delegate_(delegate) {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    for (const device::DiscoverableCredentialMetadata& cred : creds) {
-      items_.emplace_back(
-          NameTokenForDisplay(cred.user.name.value_or("")), u"",
-          ui::ImageModel::FromVectorIcon(vector_icons::kPasskeyIcon,
-                                         ui::kColorAccent, kIconSize));
-    }
-    return;
-  }
-
   for (const device::DiscoverableCredentialMetadata& cred : creds) {
     items_.emplace_back(
-        NameTokenForDisplay(cred.user.display_name.value_or("")),
-        NameTokenForDisplay(cred.user.name.value_or("")), ui::ImageModel());
+        NameTokenForDisplay(cred.user.name.value_or("")), u"",
+        ui::ImageModel::FromVectorIcon(vector_icons::kPasskeyIcon,
+                                       ui::kColorAccent, kIconSize));
   }
 }
 
@@ -82,12 +71,6 @@
   return items_.size();
 }
 
-bool AccountHoverListModel::StyleForTwoLines() const {
-  // With `kWebAuthnNewDiscoverableCredentialsUi`, we don't show a display name.
-  return !base::FeatureList::IsEnabled(
-      device::kWebAuthnNewDiscoverableCredentialsUi);
-}
-
 AccountHoverListModel::Item::Item(std::u16string text,
                                   std::u16string description,
                                   ui::ImageModel icon)
diff --git a/chrome/browser/ui/webauthn/account_hover_list_model.h b/chrome/browser/ui/webauthn/account_hover_list_model.h
index 97a1ce7..b344f97 100644
--- a/chrome/browser/ui/webauthn/account_hover_list_model.h
+++ b/chrome/browser/ui/webauthn/account_hover_list_model.h
@@ -44,7 +44,6 @@
   ui::ImageModel GetItemIcon(int item_tag) const override;
   void OnListItemSelected(int item_tag) override;
   size_t GetPreferredItemCount() const override;
-  bool StyleForTwoLines() const override;
 
  private:
   struct Item {
diff --git a/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc b/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc
index 2facbab..bd79360 100644
--- a/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc
+++ b/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc
@@ -7,8 +7,6 @@
 
 #include "base/functional/callback_helpers.h"
 #include "base/test/bind.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/test/with_feature_override.h"
 #include "build/build_config.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -19,12 +17,10 @@
 #include "chrome/browser/webauthn/authenticator_reference.h"
 #include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
 #include "components/cbor/values.h"
-#include "content/public/common/content_features.h"
 #include "content/public/test/browser_test.h"
 #include "device/fido/authenticator_data.h"
 #include "device/fido/authenticator_get_assertion_response.h"
 #include "device/fido/cable/cable_discovery_data.h"
-#include "device/fido/features.h"
 #include "device/fido/fido_request_handler_base.h"
 #include "device/fido/pin.h"
 #include "device/fido/public_key_credential_user_entity.h"
@@ -32,28 +28,18 @@
 // Run with:
 //
 //   --gtest_filter=BrowserUiTest.Invoke --test-launcher-interactive \
-//   --ui=All/AuthenticatorDialogTest.InvokeUi_${test_name}/${param_state}
+//   --ui=All/AuthenticatorDialogTest.InvokeUi_${test_name}
 //
-// where test_name is the second arg to IN_PROC_BROWSER_TEST_P(), and
-// param_state is 0 or 1 and indicates the `base::test::WithFeatureOverride`
-// state.
+// where test_name is the second arg to IN_PROC_BROWSER_TEST_F().
 
-class AuthenticatorDialogTest : public DialogBrowserTest,
-                                public base::test::WithFeatureOverride {
+class AuthenticatorDialogTest : public DialogBrowserTest {
  public:
-  AuthenticatorDialogTest()
-      : DialogBrowserTest(),
-        base::test::WithFeatureOverride(
-            device::kWebAuthnNewDiscoverableCredentialsUi) {}
-
+  AuthenticatorDialogTest() = default;
   AuthenticatorDialogTest(const AuthenticatorDialogTest&) = delete;
   AuthenticatorDialogTest& operator=(const AuthenticatorDialogTest&) = delete;
 
   // DialogBrowserTest:
-  void ShowUi(const std::string& test_name) override {
-    // Strip trailing feature param state.
-    std::string name = test_name.substr(0, test_name.find('/'));
-
+  void ShowUi(const std::string& name) override {
     // Web modal dialogs' bounds may exceed the display's work area.
     // https://crbug.com/893292.
     set_should_verify_dialog_bounds(false);
@@ -175,8 +161,9 @@
               return;
             }
             weak_model->OnSampleCollected(--bio_samples_remaining_);
-            if (bio_samples_remaining_ <= 0)
+            if (bio_samples_remaining_ <= 0) {
               timer_.Stop();
+            }
           }));
     } else if (name == "retry_uv") {
       model_->OnRetryUserVerification(5);
@@ -355,184 +342,182 @@
   int bio_samples_remaining_ = 5;
 };
 
-INSTANTIATE_FEATURE_OVERRIDE_TEST_SUITE(AuthenticatorDialogTest);
-
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_default) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_default) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_force_pin_change) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_force_pin_change) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest,
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
                        InvokeUi_force_pin_change_same_as_current) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_mechanisms) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_mechanisms) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_activate_usb) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_activate_usb) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_timeout) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_timeout) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest,
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
                        InvokeUi_no_available_transports) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_key_not_registered) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_key_not_registered) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest,
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
                        InvokeUi_key_already_registered) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest,
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
                        InvokeUi_internal_unrecognized_error) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_ble_power_on_manual) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_ble_power_on_manual) {
   ShowAndVerifyUi();
 }
 
 #if BUILDFLAG(IS_MAC)
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_touchid) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_touchid) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_touchid_incognito) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_touchid_incognito) {
   ShowAndVerifyUi();
 }
 #endif  // BUILDFLAG(IS_MAC)
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_cable_activate) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_cable_activate) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest,
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
                        InvokeUi_cable_server_link_activate) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_cable_v2_activate) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_cable_v2_activate) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_cable_v2_pair) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_cable_v2_pair) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_phone_aoa) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_phone_aoa) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_set_pin) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_set_pin) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_get_pin) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_get_pin) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest,
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
                        InvokeUi_get_pin_two_tries_remaining) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest,
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
                        InvokeUi_get_pin_one_try_remaining) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_get_pin_fallback) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_get_pin_fallback) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest,
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
                        InvokeUi_inline_bio_enrollment) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_retry_uv) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_retry_uv) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest,
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
                        InvokeUi_retry_uv_two_tries_remaining) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest,
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
                        InvokeUi_retry_uv_one_try_remaining) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_second_tap) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_second_tap) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_soft_block) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_soft_block) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_hard_block) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_hard_block) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest,
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
                        InvokeUi_authenticator_removed) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_missing_capability) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_missing_capability) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_storage_full) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_storage_full) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest,
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
                        InvokeUi_resident_credential_confirm) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest,
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
                        InvokeUi_single_account_select) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_account_select) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_account_select) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest,
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
                        InvokeUi_request_attestation_permission) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest,
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
                        InvokeUi_request_enterprise_attestation_permission) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest,
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
                        InvokeUi_server_link_title_UNLOCK_YOUR_PHONE) {
   ShowAndVerifyUi();
 }
 
 #define EXP_SHEET(x)                                       \
-  IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest,          \
+  IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,          \
                          InvokeUi_server_link_sheet_##x) { \
     ShowAndVerifyUi();                                     \
   }
@@ -546,11 +531,11 @@
 #undef EXP_SHEET
 
 #if BUILDFLAG(IS_MAC)
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_ble_permission_mac) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_ble_permission_mac) {
   ShowAndVerifyUi();
 }
 #endif
 
-IN_PROC_BROWSER_TEST_P(AuthenticatorDialogTest, InvokeUi_create_passkey) {
+IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_create_passkey) {
   ShowAndVerifyUi();
 }
diff --git a/chrome/browser/ui/webauthn/authenticator_request_sheet_model.cc b/chrome/browser/ui/webauthn/authenticator_request_sheet_model.cc
index 6a54fe83..4a29d88 100644
--- a/chrome/browser/ui/webauthn/authenticator_request_sheet_model.cc
+++ b/chrome/browser/ui/webauthn/authenticator_request_sheet_model.cc
@@ -21,10 +21,6 @@
   return std::u16string();
 }
 
-ui::MenuModel* AuthenticatorRequestSheetModel::GetOtherMechanismsMenuModel() {
-  return nullptr;
-}
-
 bool AuthenticatorRequestSheetModel::IsManageDevicesButtonVisible() const {
   return false;
 }
diff --git a/chrome/browser/ui/webauthn/authenticator_request_sheet_model.h b/chrome/browser/ui/webauthn/authenticator_request_sheet_model.h
index 7be5c26..e8cf4d0 100644
--- a/chrome/browser/ui/webauthn/authenticator_request_sheet_model.h
+++ b/chrome/browser/ui/webauthn/authenticator_request_sheet_model.h
@@ -13,10 +13,6 @@
 struct VectorIcon;
 }
 
-namespace ui {
-class MenuModel;
-}
-
 // The basic interface of models backing a given UI sheet shown in the WebAuthn
 // request dialog; where each sheet, in turn, corresponds to one of `steps`
 // defined by AuthenticatorRequestDialogModel.
@@ -65,8 +61,6 @@
   virtual std::u16string GetAdditionalDescription() const;
   virtual std::u16string GetError() const;
 
-  virtual ui::MenuModel* GetOtherMechanismsMenuModel();
-
   virtual void OnBack() = 0;
   virtual void OnAccept() = 0;
   virtual void OnCancel() = 0;
diff --git a/chrome/browser/ui/webauthn/hover_list_model.h b/chrome/browser/ui/webauthn/hover_list_model.h
index 8915671..75add4a 100644
--- a/chrome/browser/ui/webauthn/hover_list_model.h
+++ b/chrome/browser/ui/webauthn/hover_list_model.h
@@ -33,12 +33,6 @@
   virtual ui::ImageModel GetItemIcon(int item_tag) const = 0;
   virtual void OnListItemSelected(int item_tag) = 0;
   virtual size_t GetPreferredItemCount() const = 0;
-  // StyleForTwoLines returns true if the items in the list should lay out
-  // with the assumption that there will be both item and description text.
-  // This causes items with no description text to be larger than strictly
-  // necessary so that all items, including those with descriptions, are the
-  // same height.
-  virtual bool StyleForTwoLines() const = 0;
 };
 
 #endif  // CHROME_BROWSER_UI_WEBAUTHN_HOVER_LIST_MODEL_H_
diff --git a/chrome/browser/ui/webauthn/other_mechanisms_menu_model.cc b/chrome/browser/ui/webauthn/other_mechanisms_menu_model.cc
deleted file mode 100644
index c29d8ed..0000000
--- a/chrome/browser/ui/webauthn/other_mechanisms_menu_model.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2018 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/webauthn/other_mechanisms_menu_model.h"
-
-#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
-#include "ui/base/models/image_model.h"
-#include "ui/color/color_id.h"
-
-OtherMechanismsMenuModel::OtherMechanismsMenuModel(
-    AuthenticatorRequestDialogModel* dialog_model)
-    : ui::SimpleMenuModel(this), dialog_model_(dialog_model) {
-  base::span<const AuthenticatorRequestDialogModel::Mechanism> mechanisms =
-      dialog_model->mechanisms();
-  const absl::optional<size_t> current_mechanism =
-      dialog_model->current_mechanism();
-
-  constexpr int kTransportIconSize = 16;
-  for (size_t i = 0; i < mechanisms.size(); i++) {
-    if (current_mechanism && i == *current_mechanism) {
-      continue;
-    }
-
-    const auto& m = mechanisms[i];
-    AddItemWithIcon(static_cast<int>(i), m.short_name,
-                    ui::ImageModel::FromVectorIcon(*m.icon, ui::kColorMenuIcon,
-                                                   kTransportIconSize));
-  }
-}
-
-OtherMechanismsMenuModel::~OtherMechanismsMenuModel() = default;
-
-bool OtherMechanismsMenuModel::IsCommandIdChecked(int command_id) const {
-  return false;
-}
-
-bool OtherMechanismsMenuModel::IsCommandIdEnabled(int command_id) const {
-  return true;
-}
-
-void OtherMechanismsMenuModel::ExecuteCommand(int command_id, int event_flags) {
-  dialog_model_->mechanisms()[command_id].callback.Run();
-}
diff --git a/chrome/browser/ui/webauthn/other_mechanisms_menu_model.h b/chrome/browser/ui/webauthn/other_mechanisms_menu_model.h
deleted file mode 100644
index b31c03a..0000000
--- a/chrome/browser/ui/webauthn/other_mechanisms_menu_model.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2018 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_WEBAUTHN_OTHER_MECHANISMS_MENU_MODEL_H_
-#define CHROME_BROWSER_UI_WEBAUTHN_OTHER_MECHANISMS_MENU_MODEL_H_
-
-#include "base/memory/raw_ptr.h"
-#include "ui/base/models/simple_menu_model.h"
-
-class AuthenticatorRequestDialogModel;
-
-// The model of the pop-up menu shown when `Choose another option` is clicked.
-//
-// This pop-up menu is available on several sheets instructing the user to
-// activate their security key over a given transport, and allows the user to
-// instead use a different transport protocol.
-class OtherMechanismsMenuModel : public ui::SimpleMenuModel,
-                                 public ui::SimpleMenuModel::Delegate {
- public:
-  explicit OtherMechanismsMenuModel(
-      AuthenticatorRequestDialogModel* dialog_model);
-
-  OtherMechanismsMenuModel(const OtherMechanismsMenuModel&) = delete;
-  OtherMechanismsMenuModel& operator=(const OtherMechanismsMenuModel&) = delete;
-
-  ~OtherMechanismsMenuModel() override;
-
- protected:
-  // ui::SimpleMenuModel::Delegate:
-  bool IsCommandIdChecked(int command_id) const override;
-  bool IsCommandIdEnabled(int command_id) const override;
-  void ExecuteCommand(int command_id, int event_flags) override;
-
-  const raw_ptr<AuthenticatorRequestDialogModel, DanglingUntriaged>
-      dialog_model_;
-};
-
-#endif  // CHROME_BROWSER_UI_WEBAUTHN_OTHER_MECHANISMS_MENU_MODEL_H_
diff --git a/chrome/browser/ui/webauthn/sheet_models.cc b/chrome/browser/ui/webauthn/sheet_models.cc
index d8e51c5..0fb1814 100644
--- a/chrome/browser/ui/webauthn/sheet_models.cc
+++ b/chrome/browser/ui/webauthn/sheet_models.cc
@@ -9,7 +9,6 @@
 #include <utility>
 
 #include "base/check_op.h"
-#include "base/feature_list.h"
 #include "base/i18n/number_formatting.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
@@ -18,14 +17,12 @@
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "chrome/app/vector_icons/vector_icons.h"
-#include "chrome/browser/ui/webauthn/other_mechanisms_menu_model.h"
 #include "chrome/browser/ui/webauthn/webauthn_ui_helpers.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/url_formatter/elide_url.h"
 #include "device/fido/authenticator_get_assertion_response.h"
 #include "device/fido/discoverable_credential_metadata.h"
-#include "device/fido/features.h"
 #include "device/fido/fido_types.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/font_list.h"
@@ -104,8 +101,6 @@
 }
 
 bool AuthenticatorSheetModelBase::IsOtherMechanismButtonVisible() const {
-  DCHECK(base::FeatureList::IsEnabled(
-      device::kWebAuthnNewDiscoverableCredentialsUi));
   return other_mechanism_button_visibility_ ==
              OtherMechanismButtonVisibility::kVisible &&
          dialog_model_->mechanisms().size() > 1;
@@ -128,8 +123,9 @@
 }
 
 void AuthenticatorSheetModelBase::OnBack() {
-  if (dialog_model())
+  if (dialog_model()) {
     dialog_model()->StartOver();
+  }
 }
 
 void AuthenticatorSheetModelBase::OnAccept() {
@@ -137,8 +133,9 @@
 }
 
 void AuthenticatorSheetModelBase::OnCancel() {
-  if (dialog_model())
+  if (dialog_model()) {
     dialog_model()->Cancel();
+  }
 }
 
 void AuthenticatorSheetModelBase::OnModelDestroyed(
@@ -149,11 +146,6 @@
 
 // AuthenticatorMechanismSelectorSheetModel -----------------------------------
 
-AuthenticatorMechanismSelectorSheetModel::
-    AuthenticatorMechanismSelectorSheetModel(
-        AuthenticatorRequestDialogModel* dialog_model)
-    : AuthenticatorSheetModelBase(dialog_model) {}
-
 bool AuthenticatorMechanismSelectorSheetModel::IsBackButtonVisible() const {
   return false;
 }
@@ -161,48 +153,33 @@
 const gfx::VectorIcon&
 AuthenticatorMechanismSelectorSheetModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyHeaderDarkIcon
-                                                   : kPasskeyHeaderIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnWelcomeDarkIcon
-                                                 : kWebauthnWelcomeIcon;
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyHeaderDarkIcon
+                                                 : kPasskeyHeaderIcon;
 }
 
 std::u16string AuthenticatorMechanismSelectorSheetModel::GetStepTitle() const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    switch (dialog_model()->transport_availability()->request_type) {
-      case device::FidoRequestType::kMakeCredential:
-        return l10n_util::GetStringUTF16(
-            IDS_WEBAUTHN_CREATE_PASSKEY_CHOOSE_DEVICE_TITLE);
-      case device::FidoRequestType::kGetAssertion:
-        return l10n_util::GetStringUTF16(
-            IDS_WEBAUTHN_USE_PASSKEY_CHOOSE_DEVICE_TITLE);
-    }
+  switch (dialog_model()->transport_availability()->request_type) {
+    case device::FidoRequestType::kMakeCredential:
+      return l10n_util::GetStringUTF16(
+          IDS_WEBAUTHN_CREATE_PASSKEY_CHOOSE_DEVICE_TITLE);
+    case device::FidoRequestType::kGetAssertion:
+      return l10n_util::GetStringUTF16(
+          IDS_WEBAUTHN_USE_PASSKEY_CHOOSE_DEVICE_TITLE);
   }
-  return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_TRANSPORT_SELECTION_TITLE,
-                                    GetRelyingPartyIdString(dialog_model()));
 }
 
 std::u16string AuthenticatorMechanismSelectorSheetModel::GetStepDescription()
     const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    switch (dialog_model()->transport_availability()->request_type) {
-      case device::FidoRequestType::kMakeCredential:
-        return l10n_util::GetStringFUTF16(
-            IDS_WEBAUTHN_CREATE_PASSKEY_CHOOSE_DEVICE_BODY,
-            GetRelyingPartyIdString(dialog_model()));
-      case device::FidoRequestType::kGetAssertion:
-        return l10n_util::GetStringFUTF16(
-            IDS_WEBAUTHN_USE_PASSKEY_CHOOSE_DEVICE_BODY,
-            GetRelyingPartyIdString(dialog_model()));
-    }
+  switch (dialog_model()->transport_availability()->request_type) {
+    case device::FidoRequestType::kMakeCredential:
+      return l10n_util::GetStringFUTF16(
+          IDS_WEBAUTHN_CREATE_PASSKEY_CHOOSE_DEVICE_BODY,
+          GetRelyingPartyIdString(dialog_model()));
+    case device::FidoRequestType::kGetAssertion:
+      return l10n_util::GetStringFUTF16(
+          IDS_WEBAUTHN_USE_PASSKEY_CHOOSE_DEVICE_BODY,
+          GetRelyingPartyIdString(dialog_model()));
   }
-  return l10n_util::GetStringUTF16(
-      IDS_WEBAUTHN_TRANSPORT_SELECTION_DESCRIPTION);
 }
 
 bool AuthenticatorMechanismSelectorSheetModel::IsManageDevicesButtonVisible()
@@ -229,12 +206,7 @@
     AuthenticatorInsertAndActivateUsbSheetModel(
         AuthenticatorRequestDialogModel* dialog_model)
     : AuthenticatorSheetModelBase(dialog_model,
-                                  OtherMechanismButtonVisibility::kVisible),
-      other_mechanisms_menu_model_(
-          std::make_unique<OtherMechanismsMenuModel>(dialog_model)) {}
-
-AuthenticatorInsertAndActivateUsbSheetModel::
-    ~AuthenticatorInsertAndActivateUsbSheetModel() = default;
+                                  OtherMechanismButtonVisibility::kVisible) {}
 
 bool AuthenticatorInsertAndActivateUsbSheetModel::IsActivityIndicatorVisible()
     const {
@@ -244,13 +216,8 @@
 const gfx::VectorIcon&
 AuthenticatorInsertAndActivateUsbSheetModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyUsbDarkIcon
-                                                   : kPasskeyUsbIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnUsbDarkIcon
-                                                 : kWebauthnUsbIcon;
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyUsbDarkIcon
+                                                 : kPasskeyUsbIcon;
 }
 
 std::u16string AuthenticatorInsertAndActivateUsbSheetModel::GetStepTitle()
@@ -269,11 +236,6 @@
   return PossibleResidentKeyWarning(dialog_model());
 }
 
-ui::MenuModel*
-AuthenticatorInsertAndActivateUsbSheetModel::GetOtherMechanismsMenuModel() {
-  return other_mechanisms_menu_model_.get();
-}
-
 // AuthenticatorTimeoutErrorModel ---------------------------------------------
 
 bool AuthenticatorTimeoutErrorModel::IsBackButtonVisible() const {
@@ -286,13 +248,8 @@
 
 const gfx::VectorIcon& AuthenticatorTimeoutErrorModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon
-                                                   : kPasskeyErrorIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnErrorDarkIcon
-                                                 : kWebauthnErrorIcon;
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon
+                                                 : kPasskeyErrorIcon;
 }
 
 std::u16string AuthenticatorTimeoutErrorModel::GetStepTitle() const {
@@ -317,13 +274,8 @@
 const gfx::VectorIcon&
 AuthenticatorNoAvailableTransportsErrorModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon
-                                                   : kPasskeyErrorIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnErrorDarkIcon
-                                                 : kWebauthnErrorIcon;
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon
+                                                 : kPasskeyErrorIcon;
 }
 
 std::u16string AuthenticatorNoAvailableTransportsErrorModel::GetStepTitle()
@@ -349,13 +301,8 @@
 
 const gfx::VectorIcon& AuthenticatorNoPasskeysErrorModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon
-                                                   : kPasskeyErrorIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnErrorDarkIcon
-                                                 : kWebauthnErrorIcon;
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon
+                                                 : kPasskeyErrorIcon;
 }
 
 std::u16string AuthenticatorNoPasskeysErrorModel::GetStepTitle() const {
@@ -394,13 +341,8 @@
 const gfx::VectorIcon&
 AuthenticatorNotRegisteredErrorModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon
-                                                   : kPasskeyErrorIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnErrorDarkIcon
-                                                 : kWebauthnErrorIcon;
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon
+                                                 : kPasskeyErrorIcon;
 }
 
 std::u16string AuthenticatorNotRegisteredErrorModel::GetStepTitle() const {
@@ -444,32 +386,18 @@
 const gfx::VectorIcon&
 AuthenticatorAlreadyRegisteredErrorModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon
-                                                   : kPasskeyErrorIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnErrorDarkIcon
-                                                 : kWebauthnErrorIcon;
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon
+                                                 : kPasskeyErrorIcon;
 }
 
 std::u16string AuthenticatorAlreadyRegisteredErrorModel::GetStepTitle() const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_WRONG_DEVICE_TITLE);
-  }
-  return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_WRONG_KEY_TITLE);
+  return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_WRONG_DEVICE_TITLE);
 }
 
 std::u16string AuthenticatorAlreadyRegisteredErrorModel::GetStepDescription()
     const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return l10n_util::GetStringUTF16(
-        IDS_WEBAUTHN_ERROR_WRONG_DEVICE_REGISTER_DESCRIPTION);
-  }
   return l10n_util::GetStringUTF16(
-      IDS_WEBAUTHN_ERROR_WRONG_KEY_REGISTER_DESCRIPTION);
+      IDS_WEBAUTHN_ERROR_WRONG_DEVICE_REGISTER_DESCRIPTION);
 }
 
 void AuthenticatorAlreadyRegisteredErrorModel::OnAccept() {
@@ -501,13 +429,8 @@
 const gfx::VectorIcon&
 AuthenticatorInternalUnrecognizedErrorSheetModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon
-                                                   : kPasskeyErrorIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnErrorDarkIcon
-                                                 : kWebauthnErrorIcon;
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon
+                                                 : kPasskeyErrorIcon;
 }
 
 std::u16string AuthenticatorInternalUnrecognizedErrorSheetModel::GetStepTitle()
@@ -537,15 +460,9 @@
 const gfx::VectorIcon&
 AuthenticatorBlePowerOnManualSheetModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark
-               ? kPasskeyErrorBluetoothDarkIcon
-               : kPasskeyErrorBluetoothIcon;
-  }
   return color_scheme == ImageColorScheme::kDark
-             ? kWebauthnErrorBluetoothDarkIcon
-             : kWebauthnErrorBluetoothIcon;
+             ? kPasskeyErrorBluetoothDarkIcon
+             : kPasskeyErrorBluetoothIcon;
 }
 
 std::u16string AuthenticatorBlePowerOnManualSheetModel::GetStepTitle() const {
@@ -597,15 +514,9 @@
 const gfx::VectorIcon&
 AuthenticatorBlePowerOnAutomaticSheetModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark
-               ? kPasskeyErrorBluetoothDarkIcon
-               : kPasskeyErrorBluetoothIcon;
-  }
   return color_scheme == ImageColorScheme::kDark
-             ? kWebauthnErrorBluetoothDarkIcon
-             : kWebauthnErrorBluetoothIcon;
+             ? kPasskeyErrorBluetoothDarkIcon
+             : kPasskeyErrorBluetoothIcon;
 }
 
 std::u16string AuthenticatorBlePowerOnAutomaticSheetModel::GetStepTitle()
@@ -656,15 +567,9 @@
 const gfx::VectorIcon&
 AuthenticatorBlePermissionMacSheetModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark
-               ? kPasskeyErrorBluetoothDarkIcon
-               : kPasskeyErrorBluetoothIcon;
-  }
   return color_scheme == ImageColorScheme::kDark
-             ? kWebauthnErrorBluetoothDarkIcon
-             : kWebauthnErrorBluetoothIcon;
+             ? kPasskeyErrorBluetoothDarkIcon
+             : kPasskeyErrorBluetoothIcon;
 }
 
 std::u16string AuthenticatorBlePermissionMacSheetModel::GetStepTitle() const {
@@ -703,28 +608,13 @@
 // AuthenticatorOffTheRecordInterstitialSheetModel
 // -----------------------------------------
 
-AuthenticatorOffTheRecordInterstitialSheetModel::
-    AuthenticatorOffTheRecordInterstitialSheetModel(
-        AuthenticatorRequestDialogModel* dialog_model)
-    : AuthenticatorSheetModelBase(dialog_model),
-      other_mechanisms_menu_model_(
-          std::make_unique<OtherMechanismsMenuModel>(dialog_model)) {}
-
-AuthenticatorOffTheRecordInterstitialSheetModel::
-    ~AuthenticatorOffTheRecordInterstitialSheetModel() = default;
-
 const gfx::VectorIcon&
 AuthenticatorOffTheRecordInterstitialSheetModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    // TODO(1358719): Add more specific illustration once available. The "error"
-    // graphic is a large question mark, so it looks visually very similar.
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon
-                                                   : kPasskeyErrorIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnPermissionDarkIcon
-                                                 : kWebauthnPermissionIcon;
+  // TODO(1358719): Add more specific illustration once available. The "error"
+  // graphic is a large question mark, so it looks visually very similar.
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon
+                                                 : kPasskeyErrorIcon;
 }
 
 std::u16string AuthenticatorOffTheRecordInterstitialSheetModel::GetStepTitle()
@@ -740,11 +630,6 @@
       IDS_WEBAUTHN_PLATFORM_AUTHENTICATOR_OFF_THE_RECORD_INTERSTITIAL_DESCRIPTION);
 }
 
-ui::MenuModel*
-AuthenticatorOffTheRecordInterstitialSheetModel::GetOtherMechanismsMenuModel() {
-  return other_mechanisms_menu_model_.get();
-}
-
 bool AuthenticatorOffTheRecordInterstitialSheetModel::IsAcceptButtonVisible()
     const {
   return true;
@@ -775,9 +660,7 @@
 AuthenticatorPaaskSheetModel::AuthenticatorPaaskSheetModel(
     AuthenticatorRequestDialogModel* dialog_model)
     : AuthenticatorSheetModelBase(dialog_model,
-                                  OtherMechanismButtonVisibility::kVisible),
-      other_mechanisms_menu_model_(
-          std::make_unique<OtherMechanismsMenuModel>(dialog_model)) {}
+                                  OtherMechanismButtonVisibility::kVisible) {}
 
 AuthenticatorPaaskSheetModel::~AuthenticatorPaaskSheetModel() = default;
 
@@ -808,23 +691,9 @@
 }
 
 bool AuthenticatorPaaskSheetModel::IsCancelButtonVisible() const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    // Don't hide the Cancel button in the new UI. Back and close do not exist
-    // there.
-    return true;
-  }
-
-  switch (dialog_model()->experiment_server_link_sheet_) {
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::CONTROL:
-      return true;
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_2:
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_3:
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_4:
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_5:
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_6:
-      return false;
-  }
+  // Don't hide the Cancel button in the new UI. Back and close do not exist
+  // there.
+  return true;
 }
 
 bool AuthenticatorPaaskSheetModel::IsActivityIndicatorVisible() const {
@@ -833,97 +702,38 @@
 
 const gfx::VectorIcon& AuthenticatorPaaskSheetModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyPhoneDarkIcon
-                                                   : kPasskeyPhoneIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnPhoneDarkIcon
-                                                 : kWebauthnPhoneIcon;
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyPhoneDarkIcon
+                                                 : kPasskeyPhoneIcon;
 }
 
 std::u16string AuthenticatorPaaskSheetModel::GetStepTitle() const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    switch (dialog_model()->cable_ui_type()) {
-      case AuthenticatorRequestDialogModel::CableUIType::CABLE_V1:
-      case AuthenticatorRequestDialogModel::CableUIType::CABLE_V2_SERVER_LINK:
-        // caBLEv1 and v2 server-link don't include device names.
-        return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLE_ACTIVATE_TITLE);
-      case AuthenticatorRequestDialogModel::CableUIType::CABLE_V2_2ND_FACTOR:
-        return l10n_util::GetStringUTF16(
-            IDS_WEBAUTHN_CABLE_ACTIVATE_TITLE_DEVICE);
-    }
-  }
-  switch (dialog_model()->experiment_server_link_title_) {
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkTitle::CONTROL:
+  switch (dialog_model()->cable_ui_type()) {
+    case AuthenticatorRequestDialogModel::CableUIType::CABLE_V1:
+    case AuthenticatorRequestDialogModel::CableUIType::CABLE_V2_SERVER_LINK:
+      // caBLEv1 and v2 server-link don't include device names.
       return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLE_ACTIVATE_TITLE);
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkTitle::
-        UNLOCK_YOUR_PHONE:
-      return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLE_ACTIVATE_TITLE_ALT);
+    case AuthenticatorRequestDialogModel::CableUIType::CABLE_V2_2ND_FACTOR:
+      return l10n_util::GetStringUTF16(
+          IDS_WEBAUTHN_CABLE_ACTIVATE_TITLE_DEVICE);
   }
 }
 
 std::u16string AuthenticatorPaaskSheetModel::GetStepDescription() const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    switch (dialog_model()->cable_ui_type()) {
-      case AuthenticatorRequestDialogModel::CableUIType::CABLE_V1:
-      case AuthenticatorRequestDialogModel::CableUIType::CABLE_V2_SERVER_LINK:
-        // caBLEv1 and v2 server-link don't include device names.
-        return l10n_util::GetStringUTF16(
-            IDS_WEBAUTHN_CABLE_ACTIVATE_DESCRIPTION);
-      case AuthenticatorRequestDialogModel::CableUIType::CABLE_V2_2ND_FACTOR: {
-        DCHECK(dialog_model()->selected_phone_name());
-        return l10n_util::GetStringFUTF16(
-            IDS_WEBAUTHN_CABLE_ACTIVATE_DEVICE_NAME_DESCRIPTION,
-            base::UTF8ToUTF16(
-                dialog_model()->selected_phone_name().value_or("")));
-      }
-    }
-  }
   switch (dialog_model()->cable_ui_type()) {
     case AuthenticatorRequestDialogModel::CableUIType::CABLE_V1:
-      return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLE_ACTIVATE_DESCRIPTION);
-
     case AuthenticatorRequestDialogModel::CableUIType::CABLE_V2_SERVER_LINK:
-      return l10n_util::GetStringFUTF16(
-          IDS_WEBAUTHN_CABLEV2_SERVERLINK_DESCRIPTION,
-          GetRelyingPartyIdString(dialog_model()));
-
+      // caBLEv1 and v2 server-link don't include device names.
+      return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLE_ACTIVATE_DESCRIPTION);
     case AuthenticatorRequestDialogModel::CableUIType::CABLE_V2_2ND_FACTOR: {
-      std::u16string notification_title;
-      switch (dialog_model()->transport_availability()->request_type) {
-        case device::FidoRequestType::kMakeCredential:
-          notification_title = l10n_util::GetStringUTF16(
-              IDS_CABLEV2_MAKE_CREDENTIAL_NOTIFICATION_TITLE);
-          break;
-        case device::FidoRequestType::kGetAssertion:
-          notification_title = l10n_util::GetStringUTF16(
-              IDS_CABLEV2_GET_ASSERTION_NOTIFICATION_TITLE);
-          break;
-      }
-
+      DCHECK(dialog_model()->selected_phone_name());
       return l10n_util::GetStringFUTF16(
-          IDS_WEBAUTHN_CABLEV2_2ND_FACTOR_DESCRIPTION,
-          GetRelyingPartyIdString(dialog_model()), notification_title);
+          IDS_WEBAUTHN_CABLE_ACTIVATE_DEVICE_NAME_DESCRIPTION,
+          base::UTF8ToUTF16(
+              dialog_model()->selected_phone_name().value_or("")));
     }
   }
 }
 
-ui::MenuModel* AuthenticatorPaaskSheetModel::GetOtherMechanismsMenuModel() {
-  switch (dialog_model()->experiment_server_link_sheet_) {
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::CONTROL:
-      return other_mechanisms_menu_model_.get();
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_2:
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_3:
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_4:
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_5:
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_6:
-      return nullptr;
-  }
-}
-
 void AuthenticatorPaaskSheetModel::OnBack() {
   switch (dialog_model()->experiment_server_link_sheet_) {
     case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::CONTROL:
@@ -945,9 +755,7 @@
     AuthenticatorAndroidAccessorySheetModel(
         AuthenticatorRequestDialogModel* dialog_model)
     : AuthenticatorSheetModelBase(dialog_model,
-                                  OtherMechanismButtonVisibility::kVisible),
-      other_mechanisms_menu_model_(
-          std::make_unique<OtherMechanismsMenuModel>(dialog_model)) {}
+                                  OtherMechanismButtonVisibility::kVisible) {}
 
 AuthenticatorAndroidAccessorySheetModel::
     ~AuthenticatorAndroidAccessorySheetModel() = default;
@@ -964,12 +772,8 @@
 const gfx::VectorIcon&
 AuthenticatorAndroidAccessorySheetModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyAoaDarkIcon
-                                                   : kPasskeyAoaIcon;
-  }
-  return kWebauthnAoaIcon;
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyAoaDarkIcon
+                                                 : kPasskeyAoaIcon;
 }
 
 std::u16string AuthenticatorAndroidAccessorySheetModel::GetStepTitle() const {
@@ -981,11 +785,6 @@
   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLEV2_AOA_DESCRIPTION);
 }
 
-ui::MenuModel*
-AuthenticatorAndroidAccessorySheetModel::GetOtherMechanismsMenuModel() {
-  return other_mechanisms_menu_model_.get();
-}
-
 // AuthenticatorClientPinEntrySheetModel
 // -----------------------------------------
 
@@ -1043,13 +842,8 @@
 const gfx::VectorIcon&
 AuthenticatorClientPinEntrySheetModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyUsbDarkIcon
-                                                   : kPasskeyUsbIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnUsbDarkIcon
-                                                 : kWebauthnUsbIcon;
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyUsbDarkIcon
+                                                 : kPasskeyUsbIcon;
 }
 
 std::u16string AuthenticatorClientPinEntrySheetModel::GetStepTitle() const {
@@ -1116,13 +910,8 @@
 const gfx::VectorIcon&
 AuthenticatorClientPinTapAgainSheetModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyUsbDarkIcon
-                                                   : kPasskeyUsbIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnUsbDarkIcon
-                                                 : kWebauthnUsbIcon;
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyUsbDarkIcon
+                                                 : kPasskeyUsbIcon;
 }
 
 std::u16string AuthenticatorClientPinTapAgainSheetModel::GetStepTitle() const {
@@ -1156,14 +945,9 @@
 const gfx::VectorIcon&
 AuthenticatorBioEnrollmentSheetModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    // No illustration since the content already has a large animated
-    // fingerprint icon.
-    return gfx::kNoneIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnFingerprintDarkIcon
-                                                 : kWebauthnFingerprintIcon;
+  // No illustration since the content already has a large animated
+  // fingerprint icon.
+  return gfx::kNoneIcon;
 }
 
 std::u16string AuthenticatorBioEnrollmentSheetModel::GetStepTitle() const {
@@ -1226,13 +1010,8 @@
 
 const gfx::VectorIcon& AuthenticatorRetryUvSheetModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyFingerprintDarkIcon
-                                                   : kPasskeyFingerprintIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnFingerprintDarkIcon
-                                                 : kWebauthnFingerprintIcon;
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyFingerprintDarkIcon
+                                                 : kPasskeyFingerprintIcon;
 }
 
 std::u16string AuthenticatorRetryUvSheetModel::GetStepTitle() const {
@@ -1337,13 +1116,8 @@
 
 const gfx::VectorIcon& AuthenticatorGenericErrorSheetModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon
-                                                   : kPasskeyErrorIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnErrorDarkIcon
-                                                 : kWebauthnErrorIcon;
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon
+                                                 : kPasskeyErrorIcon;
 }
 
 std::u16string AuthenticatorGenericErrorSheetModel::GetStepTitle() const {
@@ -1371,15 +1145,10 @@
 const gfx::VectorIcon&
 AuthenticatorResidentCredentialConfirmationSheetView::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    // TODO(1358719): Add more specific illustration once available. The "error"
-    // graphic is a large question mark, so it looks visually very similar.
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon
-                                                   : kPasskeyErrorIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnPermissionDarkIcon
-                                                 : kWebauthnPermissionIcon;
+  // TODO(1358719): Add more specific illustration once available. The "error"
+  // graphic is a large question mark, so it looks visually very similar.
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyErrorDarkIcon
+                                                 : kPasskeyErrorIcon;
 }
 
 bool AuthenticatorResidentCredentialConfirmationSheetView::IsBackButtonVisible()
@@ -1470,60 +1239,39 @@
 const gfx::VectorIcon&
 AuthenticatorSelectAccountSheetModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyHeaderDarkIcon
-                                                   : kPasskeyHeaderIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnWelcomeDarkIcon
-                                                 : kWebauthnWelcomeIcon;
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyHeaderDarkIcon
+                                                 : kPasskeyHeaderIcon;
 }
 
 std::u16string AuthenticatorSelectAccountSheetModel::GetStepTitle() const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    switch (selection_type_) {
-      case kSingleAccount:
-        return l10n_util::GetStringFUTF16(
-            IDS_WEBAUTHN_USE_PASSKEY_TITLE,
-            GetRelyingPartyIdString(dialog_model()));
-      case kMultipleAccounts:
-        return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CHOOSE_PASSKEY_TITLE);
-    }
+  switch (selection_type_) {
+    case kSingleAccount:
+      return l10n_util::GetStringFUTF16(
+          IDS_WEBAUTHN_USE_PASSKEY_TITLE,
+          GetRelyingPartyIdString(dialog_model()));
+    case kMultipleAccounts:
+      return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CHOOSE_PASSKEY_TITLE);
   }
-  return l10n_util::GetStringUTF16(IDS_WEBAUTHN_SELECT_ACCOUNT);
 }
 
 std::u16string AuthenticatorSelectAccountSheetModel::GetStepDescription()
     const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    switch (selection_type_) {
-      case kSingleAccount:
-        return u"";
-      case kMultipleAccounts:
-        return l10n_util::GetStringFUTF16(
-            IDS_WEBAUTHN_CHOOSE_PASSKEY_BODY,
-            GetRelyingPartyIdString(dialog_model()));
-    }
+  switch (selection_type_) {
+    case kSingleAccount:
+      return u"";
+    case kMultipleAccounts:
+      return l10n_util::GetStringFUTF16(
+          IDS_WEBAUTHN_CHOOSE_PASSKEY_BODY,
+          GetRelyingPartyIdString(dialog_model()));
   }
-  return std::u16string();
 }
 
 bool AuthenticatorSelectAccountSheetModel::IsAcceptButtonVisible() const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return selection_type_ == kSingleAccount;
-  }
-  return false;
+  return selection_type_ == kSingleAccount;
 }
 
 bool AuthenticatorSelectAccountSheetModel::IsAcceptButtonEnabled() const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return selection_type_ == kSingleAccount;
-  }
-  return false;
+  return selection_type_ == kSingleAccount;
 }
 
 std::u16string AuthenticatorSelectAccountSheetModel::GetAcceptButtonLabel()
@@ -1551,14 +1299,9 @@
 const gfx::VectorIcon&
 AttestationPermissionRequestSheetModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    // TODO(1358719): Add more specific illustration once available.
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyUsbDarkIcon
-                                                   : kPasskeyUsbIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnPermissionDarkIcon
-                                                 : kWebauthnPermissionIcon;
+  // TODO(1358719): Add more specific illustration once available.
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyUsbDarkIcon
+                                                 : kPasskeyUsbIcon;
 }
 
 std::u16string AttestationPermissionRequestSheetModel::GetStepTitle() const {
@@ -1630,43 +1373,30 @@
 
 const gfx::VectorIcon& AuthenticatorQRSheetModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    // No illustration since there already is the QR code.
-    return gfx::kNoneIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnPhoneDarkIcon
-                                                 : kWebauthnPhoneIcon;
+  // No illustration since there already is the QR code.
+  return gfx::kNoneIcon;
 }
 
 std::u16string AuthenticatorQRSheetModel::GetStepTitle() const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    switch (dialog_model()->transport_availability()->request_type) {
-      case device::FidoRequestType::kMakeCredential:
-        return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CREATE_PASSKEY_QR_TITLE);
-      case device::FidoRequestType::kGetAssertion:
-        return l10n_util::GetStringUTF16(IDS_WEBAUTHN_USE_PASSKEY_QR_TITLE);
-    }
+  switch (dialog_model()->transport_availability()->request_type) {
+    case device::FidoRequestType::kMakeCredential:
+      return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CREATE_PASSKEY_QR_TITLE);
+    case device::FidoRequestType::kGetAssertion:
+      return l10n_util::GetStringUTF16(IDS_WEBAUTHN_USE_PASSKEY_QR_TITLE);
   }
-  return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLEV2_ADD_PHONE);
 }
 
 std::u16string AuthenticatorQRSheetModel::GetStepDescription() const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    switch (dialog_model()->transport_availability()->request_type) {
-      case device::FidoRequestType::kMakeCredential:
-        return l10n_util::GetStringFUTF16(
-            IDS_WEBAUTHN_CREATE_PASSKEY_QR_BODY,
-            GetRelyingPartyIdString(dialog_model()));
-      case device::FidoRequestType::kGetAssertion:
-        return l10n_util::GetStringFUTF16(
-            IDS_WEBAUTHN_USE_PASSKEY_QR_BODY,
-            GetRelyingPartyIdString(dialog_model()));
-    }
+  switch (dialog_model()->transport_availability()->request_type) {
+    case device::FidoRequestType::kMakeCredential:
+      return l10n_util::GetStringFUTF16(
+          IDS_WEBAUTHN_CREATE_PASSKEY_QR_BODY,
+          GetRelyingPartyIdString(dialog_model()));
+    case device::FidoRequestType::kGetAssertion:
+      return l10n_util::GetStringFUTF16(
+          IDS_WEBAUTHN_USE_PASSKEY_QR_BODY,
+          GetRelyingPartyIdString(dialog_model()));
   }
-  return l10n_util::GetStringUTF16(IDS_BROWSER_SHARING_QR_CODE_DIALOG_TOOLTIP);
 }
 
 // AuthenticatorCreatePasskeySheetModel
@@ -1683,13 +1413,8 @@
 const gfx::VectorIcon&
 AuthenticatorCreatePasskeySheetModel::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    return color_scheme == ImageColorScheme::kDark ? kPasskeyHeaderDarkIcon
-                                                   : kPasskeyHeaderIcon;
-  }
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnWelcomeDarkIcon
-                                                 : kWebauthnWelcomeIcon;
+  return color_scheme == ImageColorScheme::kDark ? kPasskeyHeaderDarkIcon
+                                                 : kPasskeyHeaderIcon;
 }
 
 std::u16string AuthenticatorCreatePasskeySheetModel::GetStepTitle() const {
diff --git a/chrome/browser/ui/webauthn/sheet_models.h b/chrome/browser/ui/webauthn/sheet_models.h
index 8373c89..9791859 100644
--- a/chrome/browser/ui/webauthn/sheet_models.h
+++ b/chrome/browser/ui/webauthn/sheet_models.h
@@ -11,7 +11,6 @@
 #include "base/memory/raw_ptr.h"
 #include "build/build_config.h"
 #include "chrome/browser/ui/webauthn/authenticator_request_sheet_model.h"
-#include "chrome/browser/ui/webauthn/transport_hover_list_model.h"
 #include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
 #include "device/fido/pin.h"
 
@@ -19,12 +18,6 @@
 struct VectorIcon;
 }
 
-namespace ui {
-class MenuModel;
-}
-
-class OtherMechanismsMenuModel;
-
 // Base class for sheets, implementing the shared behavior used on most sheets,
 // as well as maintaining a weak pointer to the dialog model.
 class AuthenticatorSheetModelBase
@@ -89,10 +82,8 @@
 class AuthenticatorMechanismSelectorSheetModel
     : public AuthenticatorSheetModelBase {
  public:
-  explicit AuthenticatorMechanismSelectorSheetModel(
-      AuthenticatorRequestDialogModel* dialog_model);
+  using AuthenticatorSheetModelBase::AuthenticatorSheetModelBase;
 
- private:
   // AuthenticatorSheetModelBase:
   bool IsBackButtonVisible() const override;
   bool IsManageDevicesButtonVisible() const override;
@@ -108,9 +99,7 @@
  public:
   explicit AuthenticatorInsertAndActivateUsbSheetModel(
       AuthenticatorRequestDialogModel* dialog_model);
-  ~AuthenticatorInsertAndActivateUsbSheetModel() override;
 
- private:
   // AuthenticatorSheetModelBase:
   bool IsActivityIndicatorVisible() const override;
   const gfx::VectorIcon& GetStepIllustration(
@@ -118,9 +107,6 @@
   std::u16string GetStepTitle() const override;
   std::u16string GetStepDescription() const override;
   std::u16string GetAdditionalDescription() const override;
-  ui::MenuModel* GetOtherMechanismsMenuModel() override;
-
-  std::unique_ptr<OtherMechanismsMenuModel> other_mechanisms_menu_model_;
 };
 
 class AuthenticatorTimeoutErrorModel : public AuthenticatorSheetModelBase {
@@ -291,24 +277,18 @@
 class AuthenticatorOffTheRecordInterstitialSheetModel
     : public AuthenticatorSheetModelBase {
  public:
-  explicit AuthenticatorOffTheRecordInterstitialSheetModel(
-      AuthenticatorRequestDialogModel* dialog_model);
-  ~AuthenticatorOffTheRecordInterstitialSheetModel() override;
+  using AuthenticatorSheetModelBase::AuthenticatorSheetModelBase;
 
- private:
   // AuthenticatorSheetModelBase:
   const gfx::VectorIcon& GetStepIllustration(
       ImageColorScheme color_scheme) const override;
   std::u16string GetStepTitle() const override;
   std::u16string GetStepDescription() const override;
-  ui::MenuModel* GetOtherMechanismsMenuModel() override;
   bool IsAcceptButtonVisible() const override;
   bool IsAcceptButtonEnabled() const override;
   std::u16string GetAcceptButtonLabel() const override;
   std::u16string GetCancelButtonLabel() const override;
   void OnAccept() override;
-
-  std::unique_ptr<OtherMechanismsMenuModel> other_mechanisms_menu_model_;
 };
 
 class AuthenticatorPaaskSheetModel : public AuthenticatorSheetModelBase {
@@ -327,10 +307,7 @@
       ImageColorScheme color_scheme) const override;
   std::u16string GetStepTitle() const override;
   std::u16string GetStepDescription() const override;
-  ui::MenuModel* GetOtherMechanismsMenuModel() override;
   void OnBack() override;
-
-  std::unique_ptr<OtherMechanismsMenuModel> other_mechanisms_menu_model_;
 };
 
 class AuthenticatorAndroidAccessorySheetModel
@@ -348,9 +325,6 @@
       ImageColorScheme color_scheme) const override;
   std::u16string GetStepTitle() const override;
   std::u16string GetStepDescription() const override;
-  ui::MenuModel* GetOtherMechanismsMenuModel() override;
-
-  std::unique_ptr<OtherMechanismsMenuModel> other_mechanisms_menu_model_;
 };
 
 class AuthenticatorClientPinEntrySheetModel
diff --git a/chrome/browser/ui/webauthn/transport_hover_list_model.cc b/chrome/browser/ui/webauthn/transport_hover_list_model.cc
index 7d4733d..017483e 100644
--- a/chrome/browser/ui/webauthn/transport_hover_list_model.cc
+++ b/chrome/browser/ui/webauthn/transport_hover_list_model.cc
@@ -43,7 +43,3 @@
 size_t TransportHoverListModel::GetPreferredItemCount() const {
   return mechanisms_.size();
 }
-
-bool TransportHoverListModel::StyleForTwoLines() const {
-  return false;
-}
diff --git a/chrome/browser/ui/webauthn/transport_hover_list_model.h b/chrome/browser/ui/webauthn/transport_hover_list_model.h
index 91a0b33..7a54b0f0 100644
--- a/chrome/browser/ui/webauthn/transport_hover_list_model.h
+++ b/chrome/browser/ui/webauthn/transport_hover_list_model.h
@@ -30,7 +30,6 @@
   ui::ImageModel GetItemIcon(int item_tag) const override;
   void OnListItemSelected(int item_tag) override;
   size_t GetPreferredItemCount() const override;
-  bool StyleForTwoLines() const override;
 
  private:
   const base::span<const AuthenticatorRequestDialogModel::Mechanism>
diff --git a/chrome/browser/ui/webui/ash/drive_internals_ui.cc b/chrome/browser/ui/webui/ash/drive_internals_ui.cc
index 12eaded..2e8f2598 100644
--- a/chrome/browser/ui/webui/ash/drive_internals_ui.cc
+++ b/chrome/browser/ui/webui/ash/drive_internals_ui.cc
@@ -63,11 +63,12 @@
 #include "google_apis/drive/drive_api_parser.h"
 #include "net/base/filename_util.h"
 
-using content::BrowserThread;
-
 namespace ash {
 namespace {
 
+using content::BrowserThread;
+using drivefs::pinning::DriveFsPinManager;
+
 constexpr char kKey[] = "key";
 constexpr char kValue[] = "value";
 constexpr char kClass[] = "class";
@@ -244,9 +245,8 @@
              base::WeakPtr<DriveInternalsWebUIHandler> drive_internals);
 
 // Class to handle messages from chrome://drive-internals.
-class DriveInternalsWebUIHandler
-    : public content::WebUIMessageHandler,
-      public drivefs::pinning::DriveFsBulkPinObserver {
+class DriveInternalsWebUIHandler : public content::WebUIMessageHandler,
+                                   public DriveFsPinManager::Observer {
  public:
   ~DriveInternalsWebUIHandler() override {
     if (pin_manager_) {
@@ -615,29 +615,32 @@
     drive::DriveIntegrationService* const integration_service =
         GetIntegrationService();
     DCHECK(integration_service);
-    if (!pin_manager_) {
-      pin_manager_ = integration_service->GetPinManager();
-      if (!pin_manager_) {
-        LOG(ERROR) << "No DriveFS pin manager";
-        SetSectionEnabled("bulk-pinning-section", false);
-        return;
-      }
 
-      pin_manager_->AddObserver(this);
-      VLOG(1) << "Added Pin manager observer";
-
-      OnSetupProgress(pin_manager_->GetProgress());
+    if (pin_manager_) {
+      pin_manager_->RemoveObserver(this);
+      VLOG(1) << "Removed Pin manager observer";
+      pin_manager_.reset();
     }
 
-    SetSectionEnabled("bulk-pinning-section", true);
+    DriveFsPinManager* const pin_manager = integration_service->GetPinManager();
+    if (!pin_manager) {
+      LOG(ERROR) << "No DriveFS pin manager";
+      SetSectionEnabled("bulk-pinning-section", false);
+      return;
+    }
 
+    pin_manager_ = pin_manager->GetWeakPtr();
+    pin_manager_->AddObserver(this);
+    VLOG(1) << "Added Pin manager observer";
+
+    OnProgress(pin_manager_->GetProgress());
+    SetSectionEnabled("bulk-pinning-section", true);
     const bool bulk_pinning_enabled =
         GetPrefs()->GetBoolean(drive::prefs::kDriveFsBulkPinningEnabled);
     MaybeCallJavascript("updateBulkPinning", base::Value(bulk_pinning_enabled));
   }
 
-  void OnSetupProgress(
-      const drivefs::pinning::SetupProgress& progress) override {
+  void OnProgress(const drivefs::pinning::SetupProgress& progress) override {
     using drivefs::pinning::HumanReadableSize;
 
     base::Value::Dict d;
@@ -995,7 +998,7 @@
   }
 
   // DriveFS bulk-pinning manager.
-  drivefs::pinning::DriveFsPinManager* pin_manager_ = nullptr;
+  base::WeakPtr<DriveFsPinManager> pin_manager_;
 
   // The last event sent to the JavaScript side.
   int last_sent_event_id_ = -1;
diff --git a/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc b/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc
index 8c6a821..e5e98ff4 100644
--- a/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc
@@ -175,11 +175,12 @@
       Profile::FromWebUI(web_ui()));
   for (const base::Value& type : data_type_list) {
     const std::string pref_name = type.GetString();
-    BrowsingDataType data_type =
+    absl::optional<BrowsingDataType> data_type =
         browsing_data::GetDataTypeFromDeletionPreference(pref_name);
-    data_type_vector.push_back(data_type);
+    CHECK(data_type);
+    data_type_vector.push_back(*data_type);
 
-    switch (data_type) {
+    switch (*data_type) {
       case BrowsingDataType::HISTORY:
         if (prefs->GetBoolean(prefs::kAllowDeletingBrowserHistory))
           remove_mask |= chrome_browsing_data_remover::DATA_TYPE_HISTORY;
@@ -222,7 +223,7 @@
 
     // Inform the T&S sentiment service that this datatype was cleared.
     if (sentiment_service) {
-      sentiment_service->ClearedBrowsingData(data_type);
+      sentiment_service->ClearedBrowsingData(*data_type);
     }
   }
 
diff --git a/chrome/browser/vr/test/gl_test_environment_unittest.cc b/chrome/browser/vr/test/gl_test_environment_unittest.cc
index f4afce1..c3a7e7b 100644
--- a/chrome/browser/vr/test/gl_test_environment_unittest.cc
+++ b/chrome/browser/vr/test/gl_test_environment_unittest.cc
@@ -13,8 +13,11 @@
 
 namespace vr {
 
-// TODO(crbug.com/1394319): Re-enable this test
-#if BUILDFLAG(IS_LINUX) && defined(MEMORY_SANITIZER)
+// TODO(crbug.com/1394319): Re-enable this test on MSAN if not removed.
+// TODO(crbug.com/1231934): Re-enable this test on Linux in general, or fully
+// remove if DrawVrBrowsingMode is removed (see
+// https://chromium-review.googlesource.com/c/chromium/src/+/4102520/comments/b1cb2e21_5078eef7).
+#if BUILDFLAG(IS_LINUX)
 #define MAYBE_InitializeAndCleanup DISABLED_InitializeAndCleanup
 #else
 #define MAYBE_InitializeAndCleanup InitializeAndCleanup
diff --git a/chrome/browser/vr/ui_pixeltest.cc b/chrome/browser/vr/ui_pixeltest.cc
index a25c116..c530d07 100644
--- a/chrome/browser/vr/ui_pixeltest.cc
+++ b/chrome/browser/vr/ui_pixeltest.cc
@@ -16,8 +16,11 @@
 
 namespace vr {
 
-// TODO(crbug.com/1394319): Re-enable this test
-#if BUILDFLAG(IS_LINUX) && defined(MEMORY_SANITIZER)
+// TODO(crbug.com/1394319): Re-enable this test on MSAN if not removed.
+// TODO(crbug.com/1231934): Re-enable this test on Linux in general, or fully
+// remove if DrawVrBrowsingMode is removed (see
+// https://chromium-review.googlesource.com/c/chromium/src/+/4102520/comments/b1cb2e21_5078eef7).
+#if BUILDFLAG(IS_LINUX)
 #define MAYBE_DrawVrBrowsingMode DISABLED_DrawVrBrowsingMode
 #else
 #define MAYBE_DrawVrBrowsingMode DrawVrBrowsingMode
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn
index eea3478..9ee0b5e 100644
--- a/chrome/browser/web_applications/BUILD.gn
+++ b/chrome/browser/web_applications/BUILD.gn
@@ -119,6 +119,8 @@
     "os_integration/protocol_handling_sub_manager.h",
     "os_integration/run_on_os_login_sub_manager.cc",
     "os_integration/run_on_os_login_sub_manager.h",
+    "os_integration/shortcut_menu_handling_sub_manager.cc",
+    "os_integration/shortcut_menu_handling_sub_manager.h",
     "os_integration/shortcut_sub_manager.cc",
     "os_integration/shortcut_sub_manager.h",
     "os_integration/uninstallation_via_os_settings_sub_manager.cc",
@@ -603,6 +605,7 @@
     "os_integration/os_integration_manager_unittest.cc",
     "os_integration/protocol_handling_sub_manager_unittest.cc",
     "os_integration/run_on_os_login_sub_manager_unittest.cc",
+    "os_integration/shortcut_menu_handling_sub_manager_unittest.cc",
     "os_integration/uninstallation_via_os_settings_sub_manager_unittest.cc",
     "os_integration/web_app_file_handler_manager_unittest.cc",
     "os_integration/web_app_protocol_handler_manager_unittest.cc",
diff --git a/chrome/browser/web_applications/os_integration/os_integration_manager.cc b/chrome/browser/web_applications/os_integration/os_integration_manager.cc
index 9670641e..fd1789d2 100644
--- a/chrome/browser/web_applications/os_integration/os_integration_manager.cc
+++ b/chrome/browser/web_applications/os_integration/os_integration_manager.cc
@@ -27,6 +27,7 @@
 #include "chrome/browser/web_applications/os_integration/os_integration_sub_manager.h"
 #include "chrome/browser/web_applications/os_integration/protocol_handling_sub_manager.h"
 #include "chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager.h"
+#include "chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager.h"
 #include "chrome/browser/web_applications/os_integration/shortcut_sub_manager.h"
 #include "chrome/browser/web_applications/os_integration/uninstallation_via_os_settings_sub_manager.h"
 #include "chrome/browser/web_applications/os_integration/web_app_shortcut.h"
@@ -185,12 +186,16 @@
       *profile_, *icon_manager, *registrar);
   auto protocol_handling_sub_manager =
       std::make_unique<ProtocolHandlingSubManager>(profile_, *registrar);
+  auto shortcut_menu_handling_sub_manager =
+      std::make_unique<ShortcutMenuHandlingSubManager>(*icon_manager,
+                                                       *registrar);
   auto run_on_os_login_sub_manager =
       std::make_unique<RunOnOsLoginSubManager>(*registrar);
   auto uninstallation_via_os_settings_sub_manager =
       std::make_unique<UninstallationViaOsSettingsSubManager>(*registrar);
   sub_managers_.push_back(std::move(shortcut_sub_manager));
   sub_managers_.push_back(std::move(protocol_handling_sub_manager));
+  sub_managers_.push_back(std::move(shortcut_menu_handling_sub_manager));
   sub_managers_.push_back(std::move(run_on_os_login_sub_manager));
   sub_managers_.push_back(
       std::move(uninstallation_via_os_settings_sub_manager));
diff --git a/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager.cc b/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager.cc
new file mode 100644
index 0000000..c247178
--- /dev/null
+++ b/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager.cc
@@ -0,0 +1,92 @@
+// 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 "chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager.h"
+
+#include <utility>
+
+#include "base/functional/bind.h"
+#include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h"
+#include "chrome/browser/web_applications/web_app_icon_manager.h"
+#include "chrome/browser/web_applications/web_app_registrar.h"
+#include "components/sync/base/time.h"
+
+namespace web_app {
+ShortcutMenuHandlingSubManager::ShortcutMenuHandlingSubManager(
+    WebAppIconManager& icon_manager,
+    WebAppRegistrar& registrar)
+    : icon_manager_(icon_manager), registrar_(registrar) {}
+
+ShortcutMenuHandlingSubManager::~ShortcutMenuHandlingSubManager() = default;
+
+void ShortcutMenuHandlingSubManager::Start() {}
+
+void ShortcutMenuHandlingSubManager::Shutdown() {}
+
+void ShortcutMenuHandlingSubManager::Configure(
+    const AppId& app_id,
+    proto::WebAppOsIntegrationState& desired_state,
+    base::OnceClosure configure_done) {
+  DCHECK(!desired_state.has_shortcut_menus());
+
+  if (!registrar_->IsLocallyInstalled(app_id)) {
+    std::move(configure_done).Run();
+    return;
+  }
+
+  std::string url = registrar_->GetAppLaunchUrl(app_id).spec();
+  std::string title = registrar_->GetAppShortName(app_id);
+  proto::ShortcutMenus* shortcut_menus = desired_state.mutable_shortcut_menus();
+  icon_manager_->ReadAllShortcutMenuIconsWithTimestamp(
+      app_id,
+      base::BindOnce(&ShortcutMenuHandlingSubManager::StoreShortcutMenuData,
+                     weak_ptr_factory_.GetWeakPtr(), shortcut_menus, title, url)
+          .Then(std::move(configure_done)));
+}
+
+void ShortcutMenuHandlingSubManager::Execute(
+    const AppId& app_id,
+    const absl::optional<SynchronizeOsOptions>& synchronize_options,
+    const proto::WebAppOsIntegrationState& desired_state,
+    const proto::WebAppOsIntegrationState& current_state,
+    base::OnceClosure callback) {
+  // Not implemented yet.
+  std::move(callback).Run();
+}
+
+void ShortcutMenuHandlingSubManager::StoreShortcutMenuData(
+    proto::ShortcutMenus* shortcut_menus,
+    std::string title,
+    std::string url,
+    WebAppIconManager::ShortcutIconDataVector shortcut_menu_items) {
+  for (auto& menu_item : shortcut_menu_items) {
+    proto::ShortcutMenuInfo* new_shortcut_menu_item =
+        shortcut_menus->add_shortcut_menu_info();
+    new_shortcut_menu_item->set_app_title(title);
+    new_shortcut_menu_item->set_app_launch_url(url);
+
+    for (const auto& [size, time] : menu_item[IconPurpose::ANY]) {
+      web_app::proto::ShortcutIconData* icon_data =
+          new_shortcut_menu_item->add_icon_data_any();
+      icon_data->set_icon_size(size);
+      icon_data->set_timestamp(syncer::TimeToProtoTime(time));
+    }
+
+    for (const auto& [size, time] : menu_item[IconPurpose::MASKABLE]) {
+      web_app::proto::ShortcutIconData* icon_data =
+          new_shortcut_menu_item->add_icon_data_maskable();
+      icon_data->set_icon_size(size);
+      icon_data->set_timestamp(syncer::TimeToProtoTime(time));
+    }
+
+    for (const auto& [size, time] : menu_item[IconPurpose::MONOCHROME]) {
+      web_app::proto::ShortcutIconData* icon_data =
+          new_shortcut_menu_item->add_icon_data_monochrome();
+      icon_data->set_icon_size(size);
+      icon_data->set_timestamp(syncer::TimeToProtoTime(time));
+    }
+  }
+}
+
+}  // namespace web_app
diff --git a/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager.h b/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager.h
new file mode 100644
index 0000000..c88d6be5
--- /dev/null
+++ b/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager.h
@@ -0,0 +1,52 @@
+// 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 CHROME_BROWSER_WEB_APPLICATIONS_OS_INTEGRATION_SHORTCUT_MENU_HANDLING_SUB_MANAGER_H_
+#define CHROME_BROWSER_WEB_APPLICATIONS_OS_INTEGRATION_SHORTCUT_MENU_HANDLING_SUB_MANAGER_H_
+
+#include "base/functional/callback_forward.h"
+#include "chrome/browser/web_applications/os_integration/os_integration_sub_manager.h"
+#include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h"
+#include "chrome/browser/web_applications/web_app_icon_manager.h"
+#include "chrome/browser/web_applications/web_app_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace web_app {
+
+class WebAppRegistrar;
+
+// Used to track when information, like shortcut menu icons, app title and app
+// launch url in shortcut menu were last updated at and update them once they
+// are changed.
+class ShortcutMenuHandlingSubManager : public OsIntegrationSubManager {
+ public:
+  explicit ShortcutMenuHandlingSubManager(WebAppIconManager& icon_manager,
+                                          WebAppRegistrar& registrar);
+  ~ShortcutMenuHandlingSubManager() override;
+  void Start() override;
+  void Shutdown() override;
+
+  void Configure(const AppId& app_id,
+                 proto::WebAppOsIntegrationState& desired_state,
+                 base::OnceClosure configure_done) override;
+  void Execute(const AppId& app_id,
+               const absl::optional<SynchronizeOsOptions>& synchronize_options,
+               const proto::WebAppOsIntegrationState& desired_state,
+               const proto::WebAppOsIntegrationState& current_state,
+               base::OnceClosure callback) override;
+
+ private:
+  void StoreShortcutMenuData(proto::ShortcutMenus* shortcut_menus,
+                             std::string title,
+                             std::string url,
+                             WebAppIconManager::ShortcutIconDataVector data);
+
+  const raw_ref<WebAppIconManager> icon_manager_;
+  const raw_ref<WebAppRegistrar> registrar_;
+
+  base::WeakPtrFactory<ShortcutMenuHandlingSubManager> weak_ptr_factory_{this};
+};
+}  // namespace web_app
+
+#endif  // CHROME_BROWSER_WEB_APPLICATIONS_OS_INTEGRATION_SHORTCUT_MENU_HANDLING_SUB_MANAGER_H_
diff --git a/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager_unittest.cc b/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager_unittest.cc
new file mode 100644
index 0000000..3c76c96
--- /dev/null
+++ b/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager_unittest.cc
@@ -0,0 +1,227 @@
+// 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 <memory>
+#include <utility>
+#include <vector>
+
+#include "base/files/file_util.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/test_future.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
+#include "chrome/browser/web_applications/os_integration/os_integration_test_override.h"
+#include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h"
+#include "chrome/browser/web_applications/test/fake_web_app_provider.h"
+#include "chrome/browser/web_applications/test/web_app_icon_test_utils.h"
+#include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
+#include "chrome/browser/web_applications/test/web_app_test.h"
+#include "chrome/browser/web_applications/test/web_app_test_utils.h"
+#include "chrome/browser/web_applications/web_app_command_scheduler.h"
+#include "chrome/browser/web_applications/web_app_icon_generator.h"
+#include "chrome/browser/web_applications/web_app_install_info.h"
+#include "chrome/browser/web_applications/web_app_install_params.h"
+#include "chrome/browser/web_applications/web_app_provider.h"
+#include "chrome/common/chrome_features.h"
+#include "components/webapps/browser/install_result_code.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace web_app {
+
+namespace {
+
+class ShortcutMenuHandlingSubManagerTest
+    : public WebAppTest,
+      public ::testing::WithParamInterface<OsIntegrationSubManagersState> {
+ public:
+  const GURL kWebAppUrl = GURL("https://example.com/path/index.html");
+
+  ShortcutMenuHandlingSubManagerTest() = default;
+  ~ShortcutMenuHandlingSubManagerTest() override = default;
+
+  void SetUp() override {
+    WebAppTest::SetUp();
+    {
+      base::ScopedAllowBlockingForTesting allow_blocking;
+      test_override_ =
+          OsIntegrationTestOverride::OverrideForTesting(base::GetHomeDir());
+    }
+    if (GetParam() == OsIntegrationSubManagersState::kSaveStateToDB) {
+      scoped_feature_list_.InitAndEnableFeatureWithParameters(
+          features::kOsIntegrationSubManagers, {{"stage", "write_config"}});
+    } else {
+      scoped_feature_list_.InitWithFeatures(
+          /*enabled_features=*/{},
+          /*disabled_features=*/{features::kOsIntegrationSubManagers});
+    }
+
+    provider_ = FakeWebAppProvider::Get(profile());
+
+    auto file_handler_manager =
+        std::make_unique<WebAppFileHandlerManager>(profile());
+    auto protocol_handler_manager =
+        std::make_unique<WebAppProtocolHandlerManager>(profile());
+    auto shortcut_manager = std::make_unique<WebAppShortcutManager>(
+        profile(), /*icon_manager=*/nullptr, file_handler_manager.get(),
+        protocol_handler_manager.get());
+    auto os_integration_manager = std::make_unique<OsIntegrationManager>(
+        profile(), std::move(shortcut_manager), std::move(file_handler_manager),
+        std::move(protocol_handler_manager), /*url_handler_manager=*/nullptr);
+
+    provider_->SetOsIntegrationManager(std::move(os_integration_manager));
+    test::AwaitStartWebAppProviderAndSubsystems(profile());
+  }
+
+  void TearDown() override {
+    // Blocking required due to file operations in the shortcut override
+    // destructor.
+    test::UninstallAllWebApps(profile());
+    {
+      base::ScopedAllowBlockingForTesting allow_blocking;
+      test_override_.reset();
+    }
+    WebAppTest::TearDown();
+  }
+
+  ShortcutsMenuIconBitmaps MakeIconBitmaps(
+      const std::vector<GeneratedIconsInfo>& icons_info,
+      int num_menu_items) {
+    ShortcutsMenuIconBitmaps shortcuts_menu_icons;
+
+    for (int i = 0; i < num_menu_items; ++i) {
+      IconBitmaps menu_item_icon_map;
+      for (const GeneratedIconsInfo& info : icons_info) {
+        DCHECK_EQ(info.sizes_px.size(), info.colors.size());
+        std::map<SquareSizePx, SkBitmap> generated_bitmaps;
+        for (size_t j = 0; j < info.sizes_px.size(); ++j) {
+          AddGeneratedIcon(&generated_bitmaps, info.sizes_px[j],
+                           info.colors[j]);
+        }
+        menu_item_icon_map.SetBitmapsForPurpose(info.purpose,
+                                                std::move(generated_bitmaps));
+      }
+      shortcuts_menu_icons.push_back(std::move(menu_item_icon_map));
+    }
+
+    return shortcuts_menu_icons;
+  }
+
+  web_app::AppId InstallWebAppWithShortcutMenuIcons(
+      ShortcutsMenuIconBitmaps shortcuts_menu_icons) {
+    std::unique_ptr<WebAppInstallInfo> info =
+        std::make_unique<WebAppInstallInfo>();
+    info->start_url = kWebAppUrl;
+    info->title = u"Test App";
+    info->user_display_mode = web_app::mojom::UserDisplayMode::kStandalone;
+    info->shortcuts_menu_icon_bitmaps = shortcuts_menu_icons;
+    base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+    // InstallFromInfoWithParams is used instead of InstallFromInfo, because
+    // InstallFromInfo doesn't register OS integration.
+    provider().scheduler().InstallFromInfoWithParams(
+        std::move(info), /*overwrite_existing_manifest_fields=*/true,
+        webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
+        result.GetCallback(), WebAppInstallParams());
+    bool success = result.Wait();
+    EXPECT_TRUE(success);
+    if (!success) {
+      return AppId();
+    }
+    EXPECT_EQ(result.Get<webapps::InstallResultCode>(),
+              webapps::InstallResultCode::kSuccessNewInstall);
+    return result.Get<AppId>();
+  }
+
+ protected:
+  WebAppProvider& provider() { return *provider_; }
+
+ private:
+  raw_ptr<FakeWebAppProvider> provider_;
+  base::test::ScopedFeatureList scoped_feature_list_;
+  std::unique_ptr<OsIntegrationTestOverride::BlockingRegistration>
+      test_override_;
+};
+
+TEST_P(ShortcutMenuHandlingSubManagerTest, TestConfigure) {
+  const int num_menu_items = 2;
+
+  const std::vector<int> sizes = {icon_size::k64, icon_size::k128};
+  const std::vector<SkColor> colors = {SK_ColorRED, SK_ColorRED};
+  const AppId& app_id = InstallWebAppWithShortcutMenuIcons(
+      MakeIconBitmaps({{IconPurpose::ANY, sizes, colors},
+                       {IconPurpose::MASKABLE, sizes, colors},
+                       {IconPurpose::MONOCHROME, sizes, colors}},
+                      num_menu_items));
+
+  auto state =
+      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+  ASSERT_TRUE(state.has_value());
+  const proto::WebAppOsIntegrationState& os_integration_state = state.value();
+  if (AreOsIntegrationSubManagersEnabled()) {
+    EXPECT_TRUE(
+        os_integration_state.shortcut_menus().shortcut_menu_info_size() ==
+        num_menu_items);
+
+    EXPECT_TRUE(os_integration_state.shortcut_menus()
+                    .shortcut_menu_info(0)
+                    .app_title() == "Test App");
+    EXPECT_TRUE(os_integration_state.shortcut_menus()
+                    .shortcut_menu_info(0)
+                    .app_launch_url() == "https://example.com/path/index.html");
+
+    int num_sizes = static_cast<int>(sizes.size());
+
+    for (int menu_index = 0; menu_index < num_menu_items; menu_index++) {
+      EXPECT_TRUE(os_integration_state.shortcut_menus()
+                      .shortcut_menu_info(menu_index)
+                      .icon_data_any_size() == num_sizes);
+      EXPECT_TRUE(os_integration_state.shortcut_menus()
+                      .shortcut_menu_info(menu_index)
+                      .icon_data_maskable_size() == num_sizes);
+      EXPECT_TRUE(os_integration_state.shortcut_menus()
+                      .shortcut_menu_info(menu_index)
+                      .icon_data_monochrome_size() == num_sizes);
+
+      for (int size_index = 0; size_index < num_sizes; size_index++) {
+        EXPECT_TRUE(os_integration_state.shortcut_menus()
+                        .shortcut_menu_info(menu_index)
+                        .icon_data_any(size_index)
+                        .icon_size() == sizes[size_index]);
+        EXPECT_TRUE(os_integration_state.shortcut_menus()
+                        .shortcut_menu_info(menu_index)
+                        .icon_data_any(size_index)
+                        .has_timestamp());
+        EXPECT_TRUE(os_integration_state.shortcut_menus()
+                        .shortcut_menu_info(menu_index)
+                        .icon_data_maskable(size_index)
+                        .icon_size() == sizes[size_index]);
+        EXPECT_TRUE(os_integration_state.shortcut_menus()
+                        .shortcut_menu_info(menu_index)
+                        .icon_data_maskable(size_index)
+                        .has_timestamp());
+        EXPECT_TRUE(os_integration_state.shortcut_menus()
+                        .shortcut_menu_info(menu_index)
+                        .icon_data_monochrome(size_index)
+                        .icon_size() == sizes[size_index]);
+        EXPECT_TRUE(os_integration_state.shortcut_menus()
+                        .shortcut_menu_info(menu_index)
+                        .icon_data_monochrome(size_index)
+                        .has_timestamp());
+      }
+    }
+  } else {
+    ASSERT_FALSE(os_integration_state.has_shortcut_menus());
+  }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    ShortcutMenuHandlingSubManagerTest,
+    ::testing::Values(OsIntegrationSubManagersState::kSaveStateToDB,
+                      OsIntegrationSubManagersState::kDisabled),
+    test::GetOsIntegrationSubManagersTestName);
+
+}  // namespace
+
+}  // namespace web_app
diff --git a/chrome/browser/web_applications/proto/web_app_os_integration_state.proto b/chrome/browser/web_applications/proto/web_app_os_integration_state.proto
index b3e6ac29..3841dc0 100644
--- a/chrome/browser/web_applications/proto/web_app_os_integration_state.proto
+++ b/chrome/browser/web_applications/proto/web_app_os_integration_state.proto
@@ -43,6 +43,18 @@
   optional RunOnOsLoginMode run_on_os_login_mode = 1;
 }
 
+message ShortcutMenuInfo {
+  optional string app_title = 1;
+  optional string app_launch_url = 2;
+  repeated ShortcutIconData icon_data_any = 3;
+  repeated ShortcutIconData icon_data_maskable = 4;
+  repeated ShortcutIconData icon_data_monochrome = 5;
+}
+
+message ShortcutMenus {
+  repeated ShortcutMenuInfo shortcut_menu_info = 1;
+}
+
 message OsUninstallRegistration {
   optional bool registered_with_os = 1;
 }
@@ -55,6 +67,7 @@
   optional ProtocolsHandled protocols_handled = 3;
   optional RunOnOsLogin run_on_os_login = 4;
   optional OsUninstallRegistration uninstall_registration = 5;
+  optional ShortcutMenus shortcut_menus = 6;
   // Add data states for other OS integration hooks here.
   // New fields added to this message must also be added to:
   // OsStatesDebugValue()
diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc
index 82e00e2..5505f8a2 100644
--- a/chrome/browser/web_applications/web_app.cc
+++ b/chrome/browser/web_applications/web_app.cc
@@ -114,6 +114,44 @@
         current_states.uninstall_registration().registered_with_os());
   }
 
+  if (current_states.has_shortcut_menus()) {
+    for (const auto& shortcut_menu :
+         current_states.shortcut_menus().shortcut_menu_info()) {
+      base::Value::Dict icon_data_any_dict;
+      base::Value::Dict icon_data_maskable_dict;
+      base::Value::Dict icon_data_monochrome_dict;
+      for (const auto& icon_data_any : shortcut_menu.icon_data_any()) {
+        icon_data_any_dict.Set(
+            base::NumberToString(icon_data_any.icon_size()),
+            syncer::GetTimeDebugString(
+                syncer::ProtoTimeToTime(icon_data_any.timestamp())));
+      }
+      for (const auto& icon_data_maskable : shortcut_menu.icon_data_any()) {
+        icon_data_maskable_dict.Set(
+            base::NumberToString(icon_data_maskable.icon_size()),
+            syncer::GetTimeDebugString(
+                syncer::ProtoTimeToTime(icon_data_maskable.timestamp())));
+      }
+      for (const auto& icon_data_monochrome : shortcut_menu.icon_data_any()) {
+        icon_data_monochrome_dict.Set(
+            base::NumberToString(icon_data_monochrome.icon_size()),
+            syncer::GetTimeDebugString(
+                syncer::ProtoTimeToTime(icon_data_monochrome.timestamp())));
+      }
+      base::Value::Dict shortcut_menu_dict;
+      shortcut_menu_dict.Set("app_title", shortcut_menu.app_title());
+      shortcut_menu_dict.Set("app_launch_url", shortcut_menu.app_launch_url());
+      shortcut_menu_dict.Set("icon_data_any",
+                             base::Value(std::move(icon_data_any_dict)));
+      shortcut_menu_dict.Set("icon_data_maskable",
+                             base::Value(std::move(icon_data_maskable_dict)));
+      shortcut_menu_dict.Set("icon_data_monochrome",
+                             base::Value(std::move(icon_data_monochrome_dict)));
+      debug_dict.Set("shortcut_menus",
+                     base::Value(std::move(shortcut_menu_dict)));
+    }
+  }
+
   return base::Value(std::move(debug_dict));
 }
 
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
index d1f823051..2e62c8f 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
@@ -183,8 +183,9 @@
 }
 
 AuthenticatorRequestDialogModel::~AuthenticatorRequestDialogModel() {
-  for (auto& observer : observers_)
+  for (auto& observer : observers_) {
     observer.OnModelDestroyed(this);
+  }
 }
 
 void AuthenticatorRequestDialogModel::HideDialog() {
@@ -215,8 +216,9 @@
 void AuthenticatorRequestDialogModel::StartOver() {
   ResetEphemeralState();
 
-  for (auto& observer : observers_)
+  for (auto& observer : observers_) {
     observer.OnStartOver();
+  }
 
   current_mechanism_.reset();
   current_step_ = Step::kNotStarted;
@@ -348,8 +350,9 @@
 
 void AuthenticatorRequestDialogModel::PowerOnBleAdapter() {
   DCHECK_EQ(current_step(), Step::kBlePowerOnAutomatic);
-  if (!bluetooth_adapter_power_on_callback_)
+  if (!bluetooth_adapter_power_on_callback_) {
     return;
+  }
 
   bluetooth_adapter_power_on_callback_.Run();
 }
@@ -382,9 +385,7 @@
 
     // For empty allow list requests, let the user select one of the silently
     // enumerated credentials before dispatching to the platform authenticator.
-    if (base::FeatureList::IsEnabled(
-            device::kWebAuthnNewDiscoverableCredentialsUi) &&
-        transport_availability_.has_empty_allow_list &&
+    if (transport_availability_.has_empty_allow_list &&
         !transport_availability_.recognized_platform_authenticator_credentials
              .empty()) {
       ephemeral_state_.creds_ =
@@ -398,9 +399,7 @@
 
   if (transport_availability_.request_type ==
       device::FidoRequestType::kMakeCredential) {
-    if (kShowCreatePlatformPasskeyStep &&
-        base::FeatureList::IsEnabled(
-            device::kWebAuthnNewDiscoverableCredentialsUi)) {
+    if (kShowCreatePlatformPasskeyStep) {
       SetCurrentStep(Step::kCreatePasskey);
       return;
     }
@@ -451,8 +450,9 @@
   if (use_conditional_mediation_) {
     // Conditional UI requests are never cancelled, they restart silently.
     ResetEphemeralState();
-    for (auto& observer : observers_)
+    for (auto& observer : observers_) {
       observer.OnStartOver();
+    }
     StartConditionalMediationRequest();
     return;
   }
@@ -473,8 +473,9 @@
 }
 
 void AuthenticatorRequestDialogModel::OnSheetModelDidChange() {
-  for (auto& observer : observers_)
+  for (auto& observer : observers_) {
     observer.OnSheetModelChanged();
+  }
 }
 
 void AuthenticatorRequestDialogModel::AddObserver(Observer* observer) {
@@ -599,12 +600,14 @@
     bool powered) {
   transport_availability_.is_ble_powered = powered;
 
-  for (auto& observer : observers_)
+  for (auto& observer : observers_) {
     observer.OnBluetoothPoweredStateChanged();
+  }
 
   // For the manual flow, the user has to click the "next" button explicitly.
-  if (current_step() == Step::kBlePowerOnAutomatic)
+  if (current_step() == Step::kBlePowerOnAutomatic) {
     ContinueWithFlowAfterBleAdapterPowered();
+  }
 }
 
 void AuthenticatorRequestDialogModel::SetRequestCallback(
@@ -685,14 +688,9 @@
         relying_party_id_, response.credential->id, *response.user_entity);
   }
   selection_callback_ = std::move(callback);
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    SetCurrentStep(ephemeral_state_.creds_.size() == 1
-                       ? Step::kSelectSingleAccount
-                       : Step::kSelectAccount);
-    return;
-  }
-  SetCurrentStep(Step::kSelectAccount);
+  SetCurrentStep(ephemeral_state_.creds_.size() == 1
+                     ? Step::kSelectSingleAccount
+                     : Step::kSelectAccount);
 }
 
 void AuthenticatorRequestDialogModel::OnAccountSelected(size_t index) {
@@ -773,25 +771,10 @@
 }
 
 bool AuthenticatorRequestDialogModel::cable_should_suggest_usb() const {
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi)) {
-    // Offer AoA only for linked caBLEv2 authenticators, not caBLEv1.
-    return cable_ui_type_ != CableUIType::CABLE_V1 &&
-           base::Contains(transport_availability_.available_transports,
-                          AuthenticatorTransport::kAndroidAccessory);
-  }
-  switch (experiment_server_link_sheet_) {
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::CONTROL:
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_2:
-      return base::Contains(transport_availability_.available_transports,
-                            AuthenticatorTransport::kAndroidAccessory);
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_3:
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_4:
-      return true;
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_5:
-    case AuthenticatorRequestDialogModel::ExperimentServerLinkSheet::ARM_6:
-      return false;
-  }
+  // Offer AoA only for linked caBLEv2 authenticators, not caBLEv1.
+  return cable_ui_type_ != CableUIType::CABLE_V1 &&
+         base::Contains(transport_availability_.available_transports,
+                        AuthenticatorTransport::kAndroidAccessory);
 }
 
 void AuthenticatorRequestDialogModel::CollectPIN(
@@ -925,8 +908,9 @@
     }
   }
 
-  for (auto& observer : observers_)
+  for (auto& observer : observers_) {
     observer.OnStepTransition();
+  }
 }
 
 void AuthenticatorRequestDialogModel::StartGuidedFlowForTransport(
@@ -1059,8 +1043,9 @@
 
 void AuthenticatorRequestDialogModel::DispatchRequestAsyncInternal(
     const std::string& authenticator_id) {
-  if (!request_callback_)
+  if (!request_callback_) {
     return;
+  }
 
   base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
       FROM_HERE, base::BindOnce(request_callback_, authenticator_id));
@@ -1099,9 +1084,7 @@
   absl::optional<AuthenticatorTransport> priority_transport;
 
   const bool show_create_passkey_step =
-      !is_get_assertion && kShowCreatePlatformPasskeyStep &&
-      base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi);
+      !is_get_assertion && kShowCreatePlatformPasskeyStep;
   if (base::Contains(transport_availability_.available_transports,
                      AuthenticatorTransport::kInternal) &&
       (transport_availability_.has_platform_authenticator_credential ==
@@ -1161,30 +1144,19 @@
   if (win_native_api_enabled()) {
     const std::u16string desc = l10n_util::GetStringUTF16(
         IDS_WEBAUTHN_TRANSPORT_POPUP_DIFFERENT_AUTHENTICATOR_WIN);
-    bool win_api_should_be_priority;
-    if (base::FeatureList::IsEnabled(
-            device::kWebAuthnNewDiscoverableCredentialsUi)) {
-      // Prefer going straight to Windows native UI for requests that are not
-      // clearly passkeys related, i.e. getAssertion with a non-empty allow
-      // list and makeCredential with rk=false except for:
-      //  - conditional UI
-      //  - "legacy" caBLE (caBLEv1 and server-link caBLEv2 on a.g.c)
-      bool is_legacy_cable =
-          cable_ui_type_ && cable_ui_type_ != CableUIType::CABLE_V2_2ND_FACTOR;
-      win_api_should_be_priority =
-          !use_conditional_mediation_ && !is_legacy_cable &&
-          ((is_get_assertion &&
-            !transport_availability_.has_empty_allow_list) ||
-           (!is_get_assertion &&
-            resident_key_requirement() ==
-                device::ResidentKeyRequirement::kDiscouraged));
-    } else {
-      // The Windows API should have priority when requested unless caBLE does
-      // because it's v1 or server-link.
-      win_api_should_be_priority =
-          prefer_native_api ||
-          (!include_add_phone_option && paired_phone_names().empty());
-    }
+    // Prefer going straight to Windows native UI for requests that are not
+    // clearly passkeys related, i.e. getAssertion with a non-empty allow list
+    // and makeCredential with rk=false except for:
+    //  - conditional UI
+    //  - "legacy" caBLE (caBLEv1 and server-link caBLEv2 on a.g.c)
+    bool is_legacy_cable =
+        cable_ui_type_ && cable_ui_type_ != CableUIType::CABLE_V2_2ND_FACTOR;
+    bool win_api_should_be_priority =
+        !use_conditional_mediation_ && !is_legacy_cable &&
+        ((is_get_assertion && !transport_availability_.has_empty_allow_list) ||
+         (!is_get_assertion &&
+          resident_key_requirement() ==
+              device::ResidentKeyRequirement::kDiscouraged));
     mechanisms_.emplace_back(
         Mechanism::WindowsAPI(/*unused*/ true), desc, desc,
         GetTransportIcon(AuthenticatorTransport::kUsbHumanInterfaceDevice),
@@ -1247,11 +1219,8 @@
       }
     }
 
-    const std::u16string label = l10n_util::GetStringUTF16(
-        base::FeatureList::IsEnabled(
-            device::kWebAuthnNewDiscoverableCredentialsUi)
-            ? IDS_WEBAUTHN_PASSKEY_DIFFERENT_DEVICE_LABEL
-            : IDS_WEBAUTHN_CABLEV2_ADD_PHONE);
+    const std::u16string label =
+        l10n_util::GetStringUTF16(IDS_WEBAUTHN_PASSKEY_DIFFERENT_DEVICE_LABEL);
     mechanisms_.emplace_back(
         Mechanism::AddPhone(), label, label, kQrcodeGeneratorIcon,
         base::BindRepeating(
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc b/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc
index 835933f1..925970b 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc
@@ -12,14 +12,12 @@
 #include "base/functional/bind.h"
 #include "base/strings/string_util.h"
 #include "base/test/bind.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
 #include "chrome/browser/webauthn/authenticator_reference.h"
 #include "chrome/browser/webauthn/authenticator_transport.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "device/fido/discoverable_credential_metadata.h"
-#include "device/fido/features.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_request_handler_base.h"
 #include "device/fido/fido_transport_protocol.h"
@@ -890,15 +888,7 @@
 }
 #endif  // BUILDFLAG(IS_WIN)
 
-class AuthenticatorRequestDialogModelPreselectCredentialTest
-    : public AuthenticatorRequestDialogModelTest {
- protected:
-  base::test::ScopedFeatureList scoped_feature_list_{
-      device::kWebAuthnNewDiscoverableCredentialsUi};
-};
-
-TEST_F(AuthenticatorRequestDialogModelPreselectCredentialTest,
-       PreSelectWithEmptyAllowList) {
+TEST_F(AuthenticatorRequestDialogModelTest, PreSelectWithEmptyAllowList) {
   AuthenticatorRequestDialogModel model(/*render_frame_host=*/nullptr);
   int preselect_num_called = 0;
   model.SetAccountPreselectedCallback(base::BindLambdaForTesting(
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc
index 8967b05..4cd0a3f50 100644
--- a/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc
+++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc
@@ -484,80 +484,6 @@
   EXPECT_EQ(cb.value(), true);
 }
 
-class ChromeAuthenticatorRequestDelegateWindowsBehaviorTest
-    : public ChromeAuthenticatorRequestDelegateTest {
- public:
-  ChromeAuthenticatorRequestDelegateWindowsBehaviorTest() {
-    scoped_feature_list_.InitAndDisableFeature(
-        device::kWebAuthnNewDiscoverableCredentialsUi);
-  }
-
-  void CreateObjectsUnderTest() {
-    delegate_.emplace(main_rfh());
-    delegate_->SetRelyingPartyId("example.com");
-
-    AuthenticatorRequestDialogModel* const model = delegate_->dialog_model();
-    observer_.emplace(model);
-    model->AddObserver(&observer_.value());
-    CHECK_EQ(observer_->last_step(),
-             AuthenticatorRequestDialogModel::Step::kNotStarted);
-  }
-
-  absl::optional<ChromeAuthenticatorRequestDelegate> delegate_;
-  absl::optional<TestAuthenticatorModelObserver> observer_;
-
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-TEST_F(ChromeAuthenticatorRequestDelegateWindowsBehaviorTest,
-       CancelAfterMechanismSelection) {
-  // Test that, on Windows, the `ChromeAuthenticatorRequestDelegate` should
-  // remember whether the last successful operation was with the native API or
-  // not and immediately trigger that UI for the next operation accordingly.
-
-  // Setup the Windows native authenticator and configure caBLE such that adding
-  // a phone is an option.
-  AuthenticatorRequestDialogModel::TransportAvailabilityInfo tai;
-  tai.has_win_native_api_authenticator = true;
-  tai.win_native_api_authenticator_id = "ID";
-  tai.available_transports.insert(device::FidoTransportProtocol::kHybrid);
-
-  CreateObjectsUnderTest();
-  delegate_->dialog_model()->set_cable_transport_info(
-      absl::nullopt, {}, base::DoNothing(), "fido:/1234");
-  delegate_->OnTransportAvailabilityEnumerated(tai);
-
-  // Since there are two options, the mechanism selection sheet should be shown.
-  EXPECT_EQ(observer_->last_step(),
-            AuthenticatorRequestDialogModel::Step::kMechanismSelection);
-
-  // Simulate the Windows native API being used successfully.
-  ChromeWebAuthenticationDelegate non_request_delegate;
-  non_request_delegate.OperationSucceeded(profile(), /* used_win_api= */ true);
-
-  CreateObjectsUnderTest();
-  delegate_->dialog_model()->set_cable_transport_info(
-      absl::nullopt, {}, base::DoNothing(), "fido:/1234");
-  delegate_->OnTransportAvailabilityEnumerated(tai);
-
-  // Since the Windows API was used successfully last time, it should jump
-  // directly to the native UI this time.
-  EXPECT_EQ(observer_->last_step(),
-            AuthenticatorRequestDialogModel::Step::kNotStarted);
-
-  // Simulate that caBLE was used successfully.
-  non_request_delegate.OperationSucceeded(profile(), /* used_win_api= */ false);
-
-  CreateObjectsUnderTest();
-  delegate_->dialog_model()->set_cable_transport_info(
-      absl::nullopt, {}, base::DoNothing(), "fido:/1234");
-  delegate_->OnTransportAvailabilityEnumerated(tai);
-
-  // Should show the mechanism selection sheet again.
-  EXPECT_EQ(observer_->last_step(),
-            AuthenticatorRequestDialogModel::Step::kMechanismSelection);
-}
-
 #endif  // BUILDFLAG(IS_WIN)
 
 class OriginMayUseRemoteDesktopClientOverrideTest
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 2a6283a..013f0a7b 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1673956108-bd00efebe22569ffaf0eedf70db4c0a61b70d70b.profdata
+chrome-linux-main-1673978375-041eb5d1962c91f17791f3ce4037790d141e8a73.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 2267d14..ff69ae1 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1673956108-1245eefb80c9997c53be748cea851730cf67c819.profdata
+chrome-mac-main-1673978375-05628ff83ad244eb6d5feefe1ea9e3212c9e055a.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 1634d18..8cebc7e 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1673967225-e3244d8cbb3cde814cdf92607d14b838eea0a928.profdata
+chrome-win32-main-1673978375-04ded555d8b60436d473c3eb2b6673f8d556837a.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index b5cc608..ee12260 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1673967225-466766319c8ac646139cec5592baba7b37c5aeb5.profdata
+chrome-win64-main-1673978375-61b0309bd27c18d5954d4c648c7ecacf62281b9a.profdata
diff --git a/chrome/chrome_cleaner/engines/broker/cleaner_sandbox_interface.cc b/chrome/chrome_cleaner/engines/broker/cleaner_sandbox_interface.cc
index 51c0ee0..684feb8 100644
--- a/chrome/chrome_cleaner/engines/broker/cleaner_sandbox_interface.cc
+++ b/chrome/chrome_cleaner/engines/broker/cleaner_sandbox_interface.cc
@@ -28,7 +28,6 @@
 #include "chrome/chrome_cleaner/os/process.h"
 #include "chrome/chrome_cleaner/os/system_util_cleaner.h"
 #include "chrome/chrome_cleaner/os/task_scheduler.h"
-#include "sandbox/win/src/nt_internals.h"
 #include "sandbox/win/src/win_utils.h"
 
 // This typedef is not included in sandbox/'s nt_internals.h.
diff --git a/chrome/chrome_cleaner/engines/broker/scanner_sandbox_interface.cc b/chrome/chrome_cleaner/engines/broker/scanner_sandbox_interface.cc
index 9a7583f..6780eeba 100644
--- a/chrome/chrome_cleaner/engines/broker/scanner_sandbox_interface.cc
+++ b/chrome/chrome_cleaner/engines/broker/scanner_sandbox_interface.cc
@@ -19,6 +19,7 @@
 #include "base/strings/string_util.h"
 #include "base/win/scoped_co_mem.h"
 #include "base/win/scoped_handle.h"
+#include "chrome/chrome_cleaner/engines/common/nt_functions.h"
 #include "chrome/chrome_cleaner/engines/common/registry_util.h"
 #include "chrome/chrome_cleaner/engines/common/sandbox_error_code.h"
 #include "chrome/chrome_cleaner/os/file_path_sanitization.h"
@@ -27,7 +28,6 @@
 #include "chrome/chrome_cleaner/os/system_util.h"
 #include "chrome/chrome_cleaner/os/task_scheduler.h"
 #include "chrome/chrome_cleaner/settings/settings.h"
-#include "sandbox/win/src/nt_internals.h"
 #include "sandbox/win/src/win_utils.h"
 
 namespace chrome_cleaner_sandbox {
diff --git a/chrome/chrome_cleaner/engines/broker/scanner_sandbox_interface_unittest.cc b/chrome/chrome_cleaner/engines/broker/scanner_sandbox_interface_unittest.cc
index 12cf547..4e078ee20 100644
--- a/chrome/chrome_cleaner/engines/broker/scanner_sandbox_interface_unittest.cc
+++ b/chrome/chrome_cleaner/engines/broker/scanner_sandbox_interface_unittest.cc
@@ -37,7 +37,6 @@
 #include "chrome/chrome_cleaner/test/test_strings.h"
 #include "chrome/chrome_cleaner/test/test_task_scheduler.h"
 #include "chrome/chrome_cleaner/test/test_util.h"
-#include "sandbox/win/src/nt_internals.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using chrome_cleaner::GetWow64RedirectedSystemPath;
diff --git a/chrome/chrome_cleaner/engines/common/BUILD.gn b/chrome/chrome_cleaner/engines/common/BUILD.gn
index f0b24c0..9dc6364 100644
--- a/chrome/chrome_cleaner/engines/common/BUILD.gn
+++ b/chrome/chrome_cleaner/engines/common/BUILD.gn
@@ -10,6 +10,7 @@
     "engine_digest_verifier.cc",
     "engine_digest_verifier.h",
     "engine_result_codes.h",
+    "nt_functions.h",
     "registry_util.cc",
     "registry_util.h",
     "sandbox_error_code.h",
diff --git a/chrome/chrome_cleaner/engines/common/nt_functions.h b/chrome/chrome_cleaner/engines/common/nt_functions.h
new file mode 100644
index 0000000..eebf976
--- /dev/null
+++ b/chrome/chrome_cleaner/engines/common/nt_functions.h
@@ -0,0 +1,72 @@
+// 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 CHROME_CHROME_CLEANER_ENGINES_COMMON_NT_FUNCTIONS_H_
+#define CHROME_CHROME_CLEANER_ENGINES_COMMON_NT_FUNCTIONS_H_
+
+#include <windows.h>
+#include <winternl.h>
+
+// Functions & types used to access non-SDK Nt functions from ntdll.dll.
+
+typedef enum _KEY_VALUE_INFORMATION_CLASS {
+  KeyValueFullInformation = 1
+} KEY_VALUE_INFORMATION_CLASS,
+    *PKEY_VALUE_INFORMATION_CLASS;
+
+typedef struct _KEY_VALUE_FULL_INFORMATION {
+  ULONG TitleIndex;
+  ULONG Type;
+  ULONG DataOffset;
+  ULONG DataLength;
+  ULONG NameLength;
+  WCHAR Name[1];
+} KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION;
+
+typedef NTSTATUS(WINAPI* NtCreateKeyFunction)(OUT PHANDLE KeyHandle,
+                                              IN ACCESS_MASK DesiredAccess,
+                                              IN POBJECT_ATTRIBUTES
+                                                  ObjectAttributes,
+                                              IN ULONG TitleIndex,
+                                              IN PUNICODE_STRING Class OPTIONAL,
+                                              IN ULONG CreateOptions,
+                                              OUT PULONG Disposition OPTIONAL);
+
+typedef NTSTATUS(WINAPI* NtOpenKeyFunction)(OUT PHANDLE KeyHandle,
+                                            IN ACCESS_MASK DesiredAccess,
+                                            IN POBJECT_ATTRIBUTES
+                                                ObjectAttributes);
+
+typedef NTSTATUS(WINAPI* NtDeleteKeyFunction)(IN HANDLE KeyHandle);
+
+typedef NTSTATUS(WINAPI* NtQueryValueKeyFunction)(IN HANDLE KeyHandle,
+                                                  IN PUNICODE_STRING ValueName,
+                                                  IN KEY_VALUE_INFORMATION_CLASS
+                                                      KeyValueInformationClass,
+                                                  OUT PVOID KeyValueInformation,
+                                                  IN ULONG Length,
+                                                  OUT PULONG ResultLength);
+
+typedef NTSTATUS(WINAPI* NtSetValueKeyFunction)(IN HANDLE KeyHandle,
+                                                IN PUNICODE_STRING ValueName,
+                                                IN ULONG TitleIndex OPTIONAL,
+                                                IN ULONG Type,
+                                                IN PVOID Data,
+                                                IN ULONG DataSize);
+
+// Partial definition only for values not in PROCESS_INFO_CLASS.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wenum-constexpr-conversion"
+constexpr auto ProcessCommandLineInformation =
+    static_cast<PROCESSINFOCLASS>(60);
+#pragma clang diagnostic pop
+
+typedef NTSTATUS(WINAPI* NtQueryInformationProcessFunction)(
+    IN HANDLE ProcessHandle,
+    IN PROCESSINFOCLASS ProcessInformationClass,
+    OUT PVOID ProcessInformation,
+    IN ULONG ProcessInformationLength,
+    OUT PULONG ReturnLength OPTIONAL);
+
+#endif  // CHROME_CHROME_CLEANER_ENGINES_COMMON_NT_FUNCTIONS_H_
diff --git a/chrome/chrome_cleaner/engines/common/registry_util.cc b/chrome/chrome_cleaner/engines/common/registry_util.cc
index 43da2c8..0727808 100644
--- a/chrome/chrome_cleaner/engines/common/registry_util.cc
+++ b/chrome/chrome_cleaner/engines/common/registry_util.cc
@@ -4,12 +4,11 @@
 
 #include "chrome/chrome_cleaner/engines/common/registry_util.h"
 
-#include <ntstatus.h>
-
 #include "base/logging.h"
 #include "base/notreached.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/strings/string_util.h"
+#include "chrome/chrome_cleaner/engines/common/nt_functions.h"
 #include "chrome/chrome_cleaner/strings/wstring_embedded_nulls.h"
 #include "sandbox/win/src/win_utils.h"
 
diff --git a/chrome/chrome_cleaner/engines/common/registry_util.h b/chrome/chrome_cleaner/engines/common/registry_util.h
index 78b0b47d..74694a55 100644
--- a/chrome/chrome_cleaner/engines/common/registry_util.h
+++ b/chrome/chrome_cleaner/engines/common/registry_util.h
@@ -5,12 +5,16 @@
 #ifndef CHROME_CHROME_CLEANER_ENGINES_COMMON_REGISTRY_UTIL_H_
 #define CHROME_CHROME_CLEANER_ENGINES_COMMON_REGISTRY_UTIL_H_
 
+#include <Windows.h>
+
+#include <ntstatus.h>
+#include <winternl.h>
+
 #include <limits>
 #include <ostream>
 #include <vector>
 
 #include "chrome/chrome_cleaner/strings/wstring_embedded_nulls.h"
-#include "sandbox/win/src/nt_internals.h"
 
 namespace chrome_cleaner_sandbox {
 
diff --git a/chrome/chrome_cleaner/engines/common/registry_util_unittest.cc b/chrome/chrome_cleaner/engines/common/registry_util_unittest.cc
index 5553a73..032a381a 100644
--- a/chrome/chrome_cleaner/engines/common/registry_util_unittest.cc
+++ b/chrome/chrome_cleaner/engines/common/registry_util_unittest.cc
@@ -20,6 +20,7 @@
 #include "base/strings/string_util.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/win/win_util.h"
+#include "chrome/chrome_cleaner/engines/common/nt_functions.h"
 #include "chrome/chrome_cleaner/ipc/ipc_test_util.h"
 #include "chrome/chrome_cleaner/ipc/mojo_task_runner.h"
 #include "chrome/chrome_cleaner/mojom/windows_handle.mojom.h"
diff --git a/chrome/chrome_elf/BUILD.gn b/chrome/chrome_elf/BUILD.gn
index be50b0d..e2cb049 100644
--- a/chrome/chrome_elf/BUILD.gn
+++ b/chrome/chrome_elf/BUILD.gn
@@ -155,15 +155,18 @@
 }
 
 # This target contains utility functions which must only depend on
-# kernel32. Please don't add dependencies on other system libraries.
+# kernel32 or ntdll. Please don't add dependencies on other system libraries.
 static_library("nt_registry") {
   sources = [
-    "../../sandbox/win/src/nt_internals.h",
     "nt_registry/nt_registry.cc",
     "nt_registry/nt_registry.h",
+    "nt_registry/nt_registry_functions.h",
   ]
 
-  libs = [ "kernel32.lib" ]
+  libs = [
+    "kernel32.lib",
+    "ntdll.lib",
+  ]
 }
 
 source_set("pe_image_safe") {
diff --git a/chrome/chrome_elf/nt_registry/DEPS b/chrome/chrome_elf/nt_registry/DEPS
index ea5a376d..211a09d 100644
--- a/chrome/chrome_elf/nt_registry/DEPS
+++ b/chrome/chrome_elf/nt_registry/DEPS
@@ -4,6 +4,7 @@
   # Nothing from chrome.
   "-chrome",
   "+chrome/chrome_elf/nt_registry/nt_registry.h",
+  "+chrome/chrome_elf/nt_registry/nt_registry_functions.h",
 ]
 specific_include_rules = {
   ".*_unittest\.cc": [
diff --git a/chrome/chrome_elf/nt_registry/nt_registry.cc b/chrome/chrome_elf/nt_registry/nt_registry.cc
index 6bf2e52..d0c71f9 100644
--- a/chrome/chrome_elf/nt_registry/nt_registry.cc
+++ b/chrome/chrome_elf/nt_registry/nt_registry.cc
@@ -11,28 +11,16 @@
 #include <memory>
 #include <string>
 
-#include "sandbox/win/src/nt_internals.h"
+#include "chrome/chrome_elf/nt_registry/nt_registry_functions.h"
 
 namespace {
 
-// Function pointers used for registry access.
-RtlInitUnicodeStringFunction g_rtl_init_unicode_string = nullptr;
-NtCreateKeyFunction g_nt_create_key = nullptr;
-NtDeleteKeyFunction g_nt_delete_key = nullptr;
-NtOpenKeyExFunction g_nt_open_key_ex = nullptr;
-NtCloseFunction g_nt_close = nullptr;
-NtQueryKeyFunction g_nt_query_key = nullptr;
-NtEnumerateKeyFunction g_nt_enumerate_key = nullptr;
-NtQueryValueKeyFunction g_nt_query_value_key = nullptr;
-NtSetValueKeyFunction g_nt_set_value_key = nullptr;
-
 // Lazy init.  No concern about concurrency in chrome_elf.
 bool g_initialized = false;
 bool g_system_install = false;
 bool g_wow64_proc = false;
 wchar_t g_kRegPathHKLM[] = L"\\Registry\\Machine\\";
 wchar_t g_kRegPathHKCU[nt::g_kRegMaxPathLen + 1] = L"";
-wchar_t g_current_user_sid_string[nt::g_kRegMaxPathLen + 1] = L"";
 
 // Max number of tries for system API calls when STATUS_BUFFER_OVERFLOW or
 // STATUS_BUFFER_TOO_SMALL can be returned.
@@ -80,66 +68,17 @@
 }
 
 bool InitNativeRegApi() {
-  HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll");
-
-  // Setup the global function pointers for registry access.
-  g_rtl_init_unicode_string = reinterpret_cast<RtlInitUnicodeStringFunction>(
-      ::GetProcAddress(ntdll, "RtlInitUnicodeString"));
-
-  g_nt_create_key = reinterpret_cast<NtCreateKeyFunction>(
-      ::GetProcAddress(ntdll, "NtCreateKey"));
-
-  g_nt_delete_key = reinterpret_cast<NtDeleteKeyFunction>(
-      ::GetProcAddress(ntdll, "NtDeleteKey"));
-
-  g_nt_open_key_ex = reinterpret_cast<NtOpenKeyExFunction>(
-      ::GetProcAddress(ntdll, "NtOpenKeyEx"));
-
-  g_nt_close =
-      reinterpret_cast<NtCloseFunction>(::GetProcAddress(ntdll, "NtClose"));
-
-  g_nt_query_key = reinterpret_cast<NtQueryKeyFunction>(
-      ::GetProcAddress(ntdll, "NtQueryKey"));
-
-  g_nt_enumerate_key = reinterpret_cast<NtEnumerateKeyFunction>(
-      ::GetProcAddress(ntdll, "NtEnumerateKey"));
-
-  g_nt_query_value_key = reinterpret_cast<NtQueryValueKeyFunction>(
-      ::GetProcAddress(ntdll, "NtQueryValueKey"));
-
-  g_nt_set_value_key = reinterpret_cast<NtSetValueKeyFunction>(
-      ::GetProcAddress(ntdll, "NtSetValueKey"));
-
-  if (!g_rtl_init_unicode_string || !g_nt_create_key || !g_nt_open_key_ex ||
-      !g_nt_delete_key || !g_nt_close || !g_nt_query_key ||
-      !g_nt_enumerate_key || !g_nt_query_value_key || !g_nt_set_value_key)
-    return false;
-
   // We need to set HKCU based on the sid of the current user account.
-  RtlFormatCurrentUserKeyPathFunction rtl_current_user_string =
-      reinterpret_cast<RtlFormatCurrentUserKeyPathFunction>(
-          ::GetProcAddress(ntdll, "RtlFormatCurrentUserKeyPath"));
-
-  RtlFreeUnicodeStringFunction rtl_free_unicode_str =
-      reinterpret_cast<RtlFreeUnicodeStringFunction>(
-          ::GetProcAddress(ntdll, "RtlFreeUnicodeString"));
-
-  if (!rtl_current_user_string || !rtl_free_unicode_str)
-    return false;
-
   UNICODE_STRING current_user_reg_path;
-  if (!NT_SUCCESS(rtl_current_user_string(&current_user_reg_path)))
+  if (!NT_SUCCESS(::RtlFormatCurrentUserKeyPath(&current_user_reg_path))) {
     return false;
+  }
 
   // Finish setting up global HKCU path.
   ::wcsncat(g_kRegPathHKCU, current_user_reg_path.Buffer, nt::g_kRegMaxPathLen);
   ::wcsncat(g_kRegPathHKCU, L"\\",
             (nt::g_kRegMaxPathLen - ::wcslen(g_kRegPathHKCU)));
-  // Keep the sid string as well.
-  wchar_t* ptr = ::wcsrchr(current_user_reg_path.Buffer, L'\\');
-  ptr++;
-  ::wcsncpy(g_current_user_sid_string, ptr, nt::g_kRegMaxPathLen);
-  rtl_free_unicode_str(&current_user_reg_path);
+  ::RtlFreeUnicodeString(&current_user_reg_path);
 
   // Figure out if this is a system or user install.
   g_system_install = IsThisProcSystem();
@@ -608,14 +547,14 @@
                           HANDLE* out_handle,
                           ULONG* create_or_open OPTIONAL) {
   UNICODE_STRING key_path_uni = {};
-  g_rtl_init_unicode_string(&key_path_uni, key_path.c_str());
+  ::RtlInitUnicodeString(&key_path_uni, key_path.c_str());
 
   OBJECT_ATTRIBUTES obj = {};
   InitializeObjectAttributes(&obj, &key_path_uni, OBJ_CASE_INSENSITIVE, NULL,
                              nullptr);
 
-  return g_nt_create_key(out_handle, access, &obj, 0, nullptr,
-                         REG_OPTION_NON_VOLATILE, create_or_open);
+  return ::NtCreateKey(out_handle, access, &obj, 0, nullptr,
+                       REG_OPTION_NON_VOLATILE, create_or_open);
 }
 
 }  // namespace
@@ -664,7 +603,7 @@
 
   size_t subkeys_size = subkeys.size();
   if (subkeys_size != 0)
-    g_nt_close(last_handle);
+    ::NtClose(last_handle);
 
   // Recursively open/create each subkey.
   std::vector<HANDLE> rollback;
@@ -690,19 +629,19 @@
       if (created == REG_CREATED_NEW_KEY)
         rollback.push_back(key_handle);
       else
-        g_nt_close(key_handle);
+        ::NtClose(key_handle);
     }
   }
 
   if (!success) {
     // Delete any subkeys created.
     for (HANDLE handle : rollback) {
-      g_nt_delete_key(handle);
+      ::NtDeleteKey(handle);
     }
   }
   for (HANDLE handle : rollback) {
     // Close the rollback handles, on success or failure.
-    g_nt_close(handle);
+    ::NtClose(handle);
   }
   if (!success)
     return false;
@@ -711,7 +650,7 @@
   if (out_handle)
     *out_handle = last_handle;
   else
-    g_nt_close(last_handle);
+    ::NtClose(last_handle);
 
   return true;
 }
@@ -746,11 +685,11 @@
   }
   full_path.insert(0, ConvertRootKey(root));
 
-  g_rtl_init_unicode_string(&key_path_uni, full_path.c_str());
+  ::RtlInitUnicodeString(&key_path_uni, full_path.c_str());
   InitializeObjectAttributes(&obj, &key_path_uni, OBJ_CASE_INSENSITIVE, NULL,
                              NULL);
 
-  status = g_nt_open_key_ex(out_handle, access, &obj, 0);
+  status = ::NtOpenKeyEx(out_handle, access, &obj, 0);
   // See if caller wants the NTSTATUS.
   if (error_code)
     *error_code = status;
@@ -765,7 +704,7 @@
   if (!g_initialized && !InitNativeRegApi())
     return false;
 
-  NTSTATUS status = g_nt_delete_key(key);
+  NTSTATUS status = ::NtDeleteKey(key);
 
   return NT_SUCCESS(status);
 }
@@ -791,7 +730,7 @@
 void CloseRegKey(HANDLE key) {
   if (!g_initialized)
     InitNativeRegApi();
-  g_nt_close(key);
+  ::NtClose(key);
 }
 
 //------------------------------------------------------------------------------
@@ -806,7 +745,7 @@
     return false;
 
   UNICODE_STRING value_uni = {};
-  g_rtl_init_unicode_string(&value_uni, value_name);
+  ::RtlInitUnicodeString(&value_uni, value_name);
 
   // Use a loop here, to be a little more tolerant of concurrent registry
   // changes.
@@ -819,8 +758,8 @@
     buffer.resize(size_needed);
     value_info = reinterpret_cast<KEY_VALUE_FULL_INFORMATION*>(buffer.data());
 
-    ntstatus = g_nt_query_value_key(key, &value_uni, KeyValueFullInformation,
-                                    value_info, size_needed, &size_needed);
+    ntstatus = ::NtQueryValueKey(key, &value_uni, KeyValueFullInformation,
+                                 value_info, size_needed, &size_needed);
   } while ((ntstatus == STATUS_BUFFER_OVERFLOW ||
             ntstatus == STATUS_BUFFER_TOO_SMALL) &&
            ++tries < kMaxTries);
@@ -985,11 +924,11 @@
 
   NTSTATUS ntstatus = STATUS_UNSUCCESSFUL;
   UNICODE_STRING value_uni = {};
-  g_rtl_init_unicode_string(&value_uni, value_name);
+  ::RtlInitUnicodeString(&value_uni, value_name);
 
   BYTE* non_const_data = const_cast<BYTE*>(data);
   ntstatus =
-      g_nt_set_value_key(key, &value_uni, 0, type, non_const_data, data_size);
+      ::NtSetValueKey(key, &value_uni, 0, type, non_const_data, data_size);
 
   if (NT_SUCCESS(ntstatus))
     return true;
@@ -1106,99 +1045,9 @@
 }
 
 //------------------------------------------------------------------------------
-// Enumeration Support
-//------------------------------------------------------------------------------
-
-bool QueryRegEnumerationInfo(HANDLE key, ULONG* out_subkey_count) {
-  if (!g_initialized && !InitNativeRegApi())
-    return false;
-
-  // Use a loop here, to be a little more tolerant of concurrent registry
-  // changes.
-  NTSTATUS ntstatus = STATUS_UNSUCCESSFUL;
-  int tries = 0;
-  // Start with sizeof the structure.  It's very common for the variable sized
-  // "Class" element to be of length 0.
-  KEY_FULL_INFORMATION* key_info = nullptr;
-  DWORD size_needed = sizeof(*key_info);
-  std::vector<BYTE> buffer(size_needed);
-  do {
-    buffer.resize(size_needed);
-    key_info = reinterpret_cast<KEY_FULL_INFORMATION*>(buffer.data());
-
-    ntstatus = g_nt_query_key(key, KeyFullInformation, key_info, size_needed,
-                              &size_needed);
-  } while ((ntstatus == STATUS_BUFFER_OVERFLOW ||
-            ntstatus == STATUS_BUFFER_TOO_SMALL) &&
-           ++tries < kMaxTries);
-
-  if (!NT_SUCCESS(ntstatus))
-    return false;
-
-  // Move desired information to out variables.
-  *out_subkey_count = key_info->SubKeys;
-
-  return true;
-}
-
-bool QueryRegSubkey(HANDLE key,
-                    ULONG subkey_index,
-                    std::wstring* out_subkey_name) {
-  if (!g_initialized && !InitNativeRegApi())
-    return false;
-
-  // Use a loop here, to be a little more tolerant of concurrent registry
-  // changes.
-  NTSTATUS ntstatus = STATUS_UNSUCCESSFUL;
-  int tries = 0;
-  // Start with sizeof the structure, plus 12 characters.  It's very common for
-  // key names to be < 12 characters (without being inefficient as an initial
-  // allocation).
-  KEY_BASIC_INFORMATION* subkey_info = nullptr;
-  DWORD size_needed = sizeof(*subkey_info) + (12 * sizeof(wchar_t));
-  std::vector<BYTE> buffer(size_needed);
-  do {
-    buffer.resize(size_needed);
-    subkey_info = reinterpret_cast<KEY_BASIC_INFORMATION*>(buffer.data());
-
-    ntstatus = g_nt_enumerate_key(key, subkey_index, KeyBasicInformation,
-                                  subkey_info, size_needed, &size_needed);
-  } while ((ntstatus == STATUS_BUFFER_OVERFLOW ||
-            ntstatus == STATUS_BUFFER_TOO_SMALL) &&
-           ++tries < kMaxTries);
-
-  if (!NT_SUCCESS(ntstatus))
-    return false;
-
-  // Move desired information to out variables.
-  // NOTE: NameLength is size of Name array in bytes.  Name array is also
-  //       NOT null terminated!
-  BYTE* name = reinterpret_cast<BYTE*>(subkey_info->Name);
-  std::vector<BYTE> content(name, name + subkey_info->NameLength);
-  EnsureTerminatedSZ(&content, false);
-  out_subkey_name->assign(reinterpret_cast<wchar_t*>(content.data()));
-
-  return true;
-}
-
-//------------------------------------------------------------------------------
 // Utils
 //------------------------------------------------------------------------------
 
-const wchar_t* GetCurrentUserSidString() {
-  if (!g_initialized && !InitNativeRegApi())
-    return nullptr;
-
-  return g_current_user_sid_string;
-}
-
-bool IsCurrentProcWow64() {
-  if (!g_initialized && !InitNativeRegApi())
-    return false;
-
-  return g_wow64_proc;
-}
-
 bool SetTestingOverride(ROOT_KEY root, const std::wstring& new_path) {
   if (!g_initialized && !InitNativeRegApi())
     return false;
diff --git a/chrome/chrome_elf/nt_registry/nt_registry.h b/chrome/chrome_elf/nt_registry/nt_registry.h
index a38d75f98..200175d 100644
--- a/chrome/chrome_elf/nt_registry/nt_registry.h
+++ b/chrome/chrome_elf/nt_registry/nt_registry.h
@@ -33,7 +33,7 @@
 namespace nt {
 
 // Windows registry maximum lengths (in chars).  Not including null char.
-// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724872(v=vs.85).aspx
+// https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-element-size-limits
 constexpr size_t g_kRegMaxPathLen = 255;
 constexpr size_t g_kRegMaxValueName = 16383;
 
@@ -229,34 +229,9 @@
                         const std::vector<std::wstring>& values);
 
 //------------------------------------------------------------------------------
-// Enumeration Support
-//------------------------------------------------------------------------------
-
-// Query key information for subkey enumeration.
-// - Key handle should have been opened with OpenRegKey (with at least
-//   KEY_ENUMERATE_SUB_KEYS access rights).
-// - Currently only returns the number of subkeys.  Use |subkey_count|
-//   in a loop for calling QueryRegSubkey.
-bool QueryRegEnumerationInfo(HANDLE key, ULONG* out_subkey_count);
-
-// Enumerate subkeys by index.
-// - Key handle should have been opened with OpenRegKey (with at least
-//   KEY_ENUMERATE_SUB_KEYS access rights).
-// - Get subkey count by calling QueryRegEnumerationInfo.
-bool QueryRegSubkey(HANDLE key,
-                    ULONG subkey_index,
-                    std::wstring* out_subkey_name);
-
-//------------------------------------------------------------------------------
 // Utils
 //------------------------------------------------------------------------------
 
-// Returns the current user SID in string form.
-const wchar_t* GetCurrentUserSidString();
-
-// Returns true if this process is WOW64.
-bool IsCurrentProcWow64();
-
 // Setter function for test suites that use reg redirection.
 bool SetTestingOverride(ROOT_KEY root, const std::wstring& new_path);
 
diff --git a/chrome/chrome_elf/nt_registry/nt_registry_functions.h b/chrome/chrome_elf/nt_registry/nt_registry_functions.h
new file mode 100644
index 0000000..6dfb149d
--- /dev/null
+++ b/chrome/chrome_elf/nt_registry/nt_registry_functions.h
@@ -0,0 +1,66 @@
+// 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 CHROME_CHROME_ELF_NT_REGISTRY_NT_REGISTRY_FUNCTIONS_H_
+#define CHROME_CHROME_ELF_NT_REGISTRY_NT_REGISTRY_FUNCTIONS_H_
+
+#include <windows.h>
+#include <winternl.h>
+
+typedef enum _KEY_VALUE_INFORMATION_CLASS {
+  KeyValueFullInformation = 1
+} KEY_VALUE_INFORMATION_CLASS,
+    *PKEY_VALUE_INFORMATION_CLASS;
+
+typedef struct _KEY_VALUE_FULL_INFORMATION {
+  ULONG TitleIndex;
+  ULONG Type;
+  ULONG DataOffset;
+  ULONG DataLength;
+  ULONG NameLength;
+  WCHAR Name[1];
+} KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION;
+
+extern "C" {
+// wdm.h.
+NTSTATUS WINAPI NtCreateKey(OUT PHANDLE KeyHandle,
+                            IN ACCESS_MASK DesiredAccess,
+                            IN POBJECT_ATTRIBUTES ObjectAttributes,
+                            IN ULONG TitleIndex,
+                            IN PUNICODE_STRING Class OPTIONAL,
+                            IN ULONG CreateOptions,
+                            OUT PULONG Disposition OPTIONAL);
+
+// wdm.h.
+NTSTATUS WINAPI NtOpenKeyEx(OUT PHANDLE KeyHandle,
+                            IN ACCESS_MASK DesiredAccess,
+                            IN POBJECT_ATTRIBUTES ObjectAttributes,
+                            IN DWORD open_options);
+
+// wdm.h.
+NTSTATUS WINAPI NtDeleteKey(IN HANDLE KeyHandle);
+
+// wdm.h.
+NTSTATUS WINAPI
+NtQueryValueKey(IN HANDLE KeyHandle,
+                IN PUNICODE_STRING ValueName,
+                IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
+                OUT PVOID KeyValueInformation,
+                IN ULONG Length,
+                OUT PULONG ResultLength);
+
+// wdm.h.
+NTSTATUS WINAPI NtSetValueKey(IN HANDLE KeyHandle,
+                              IN PUNICODE_STRING ValueName,
+                              IN ULONG TitleIndex OPTIONAL,
+                              IN ULONG Type,
+                              IN PVOID Data,
+                              IN ULONG DataSize);
+
+// ntrtl.h.
+NTSTATUS WINAPI RtlFormatCurrentUserKeyPath(OUT PUNICODE_STRING RegistryPath);
+
+}  // extern "C"
+
+#endif  // CHROME_CHROME_ELF_NT_REGISTRY_NT_REGISTRY_FUNCTIONS_H_
diff --git a/chrome/chrome_elf/nt_registry/nt_registry_unittest.cc b/chrome/chrome_elf/nt_registry/nt_registry_unittest.cc
index 344b20d..43cf56e 100644
--- a/chrome/chrome_elf/nt_registry/nt_registry_unittest.cc
+++ b/chrome/chrome_elf/nt_registry/nt_registry_unittest.cc
@@ -567,88 +567,4 @@
   // Clean up done by NtRegistryTest.
 }
 
-TEST_F(NtRegistryTest, ApiEnumeration) {
-  HANDLE key_handle;
-  HANDLE subkey_handle;
-  static constexpr wchar_t key[] = L"NTRegistry\\enum";
-  static constexpr wchar_t subkey1[] = L"NTRegistry\\enum\\subkey1";
-  static constexpr wchar_t subkey2[] = L"NTRegistry\\enum\\subkey2";
-  static constexpr wchar_t subkey3[] = L"NTRegistry\\enum\\subkey3";
-  static constexpr const wchar_t* check_names[] = {
-      L"subkey1",
-      L"subkey2",
-      L"subkey3",
-  };
-  // Test out the "(Default)" value name in this suite.
-  static constexpr wchar_t subkey_val_name[] = L"";
-  DWORD subkey_val = 1234;
-
-  // Create a subkey to play under.
-  // ------------------------------
-  ASSERT_TRUE(nt::CreateRegKey(nt::HKCU, key, KEY_ALL_ACCESS, &key_handle));
-  ASSERT_NE(key_handle, INVALID_HANDLE_VALUE);
-  ASSERT_NE(key_handle, nullptr);
-  base::ScopedClosureRunner key_closer(
-      base::BindOnce(&nt::CloseRegKey, key_handle));
-
-  // Set
-  // ------------------------------
-  // Sub-subkey with a default value.
-  ASSERT_TRUE(
-      nt::CreateRegKey(nt::HKCU, subkey1, KEY_ALL_ACCESS, &subkey_handle));
-  ASSERT_NE(subkey_handle, INVALID_HANDLE_VALUE);
-  ASSERT_NE(subkey_handle, nullptr);
-  EXPECT_TRUE(nt::SetRegValueDWORD(subkey_handle, subkey_val_name, subkey_val));
-  nt::CloseRegKey(subkey_handle);
-
-  // Sub-subkey with a default value.
-  ASSERT_TRUE(
-      nt::CreateRegKey(nt::HKCU, subkey2, KEY_ALL_ACCESS, &subkey_handle));
-  ASSERT_NE(subkey_handle, INVALID_HANDLE_VALUE);
-  ASSERT_NE(subkey_handle, nullptr);
-  EXPECT_TRUE(nt::SetRegValueDWORD(subkey_handle, subkey_val_name, subkey_val));
-  nt::CloseRegKey(subkey_handle);
-
-  // Sub-subkey with a default value.
-  ASSERT_TRUE(
-      nt::CreateRegKey(nt::HKCU, subkey3, KEY_ALL_ACCESS, &subkey_handle));
-  ASSERT_NE(subkey_handle, INVALID_HANDLE_VALUE);
-  ASSERT_NE(subkey_handle, nullptr);
-  EXPECT_TRUE(nt::SetRegValueDWORD(subkey_handle, subkey_val_name, subkey_val));
-  nt::CloseRegKey(subkey_handle);
-
-  // Get (via enumeration)
-  // ------------------------------
-  ULONG subkey_count = 0;
-  EXPECT_TRUE(nt::QueryRegEnumerationInfo(key_handle, &subkey_count));
-  ASSERT_EQ(subkey_count, ULONG{3});
-
-  std::wstring subkey_name;
-  for (ULONG i = 0; i < subkey_count; i++) {
-    ASSERT_TRUE(nt::QueryRegSubkey(key_handle, i, &subkey_name));
-
-    bool found = false;
-    for (size_t index = 0; index < std::size(check_names); index++) {
-      if (0 == subkey_name.compare(check_names[index])) {
-        found = true;
-        break;
-      }
-    }
-    ASSERT_TRUE(found);
-
-    // Grab the default DWORD value out of this subkey.
-    DWORD value = 0;
-    std::wstring temp(key);
-    temp.append(L"\\");
-    temp.append(subkey_name);
-    EXPECT_TRUE(nt::QueryRegValueDWORD(nt::HKCU, nt::NONE, temp.c_str(),
-                                       subkey_val_name, &value));
-    EXPECT_EQ(value, subkey_val);
-  }
-  // Also test a known bad index.
-  EXPECT_FALSE(nt::QueryRegSubkey(key_handle, subkey_count, &subkey_name));
-
-  // Clean up done by NtRegistryTest.
-}
-
 }  // namespace
diff --git a/chrome/services/keymaster/public/mojom/cert_store.mojom b/chrome/services/keymaster/public/mojom/cert_store.mojom
index 7d00537..7ebf4ef 100644
--- a/chrome/services/keymaster/public/mojom/cert_store.mojom
+++ b/chrome/services/keymaster/public/mojom/cert_store.mojom
@@ -9,30 +9,6 @@
 
 module arc.keymaster.mojom;
 
-// Enumerates the crypto algorithms supported by Host.
-[Extensible]
-enum Algorithm {
-  kRsaPkcs1,
-};
-
-// Enumerates the digests supported by Host.
-[Extensible]
-enum Digest {
-  kSha1,
-  kSha256,
-  kSha384,
-  kSha512,
-};
-
-// Enumerates the result codes of signature operation.
-[Extensible]
-enum SignatureResult {
-  kOk,
-  // Failed with net or internal error on chrome side.
-  kFailed,
-  kUnsupportedAlgorithm,
-};
-
 // The possible chaps slots relevant for arc-keymaster. Note this does NOT map
 // to the PKCS#11 CK_SLOT_ID, but rather to an abstract representation of the
 // value. The corresponding CK_SLOT_ID must be queried from cryptohome.
@@ -85,14 +61,9 @@
 };
 
 // Implemented in Chrome.
+// Nothing is using this interface. It is only kept to avoid changing
+// CertStoreHost.
+// Deprecated method IDs: 0
 // Next method ID: 1
 interface SecurityTokenOperation {
-  // Signs input |data| pre-hashed with the given |digest|.
-  // Retrieves a |signature| signed by a certificate identified by
-  // |subject_public_key_info| by |algorithm| (currently, only RSA is
-  // supported).
-  // In case of any error, |signature| is null.
-  SignDigest@0(string subject_public_key_info, Algorithm algorithm,
-       Digest digest, array<uint8> data) => (SignatureResult result,
-           array<uint8>? signature);
 };
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 069d708..cba568f 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -89,6 +89,7 @@
       "android/test_support/src/org/chromium/chrome/test_support/PaymentRequestTestBridge.java",
       "android/test_support/src/org/chromium/chrome/test_support/ToolbarManagerTestHelper.java",
     ]
+    annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
   }
 
   generate_jni("test_support_jni_headers") {
@@ -1547,6 +1548,7 @@
       "//third_party/blink/public/mojom:web_feature_mojo_bindings",
       "//third_party/icu",
       "//third_party/leveldatabase",
+      "//third_party/libwebp",
       "//third_party/openscreen/src/cast/streaming:common",
       "//third_party/protobuf:py_proto_runtime",
       "//third_party/webrtc_overrides:webrtc_component",
diff --git a/chrome/test/android/test_support/src/org/chromium/chrome/test_support/PaymentRequestTestBridge.java b/chrome/test/android/test_support/src/org/chromium/chrome/test_support/PaymentRequestTestBridge.java
index 4106d3d..e16c27cb 100644
--- a/chrome/test/android/test_support/src/org/chromium/chrome/test_support/PaymentRequestTestBridge.java
+++ b/chrome/test/android/test_support/src/org/chromium/chrome/test_support/PaymentRequestTestBridge.java
@@ -10,6 +10,7 @@
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
 import org.chromium.chrome.browser.payments.ChromePaymentRequestFactory;
 import org.chromium.chrome.browser.payments.ChromePaymentRequestService;
 import org.chromium.components.autofill.EditableOption;
@@ -96,8 +97,8 @@
 
     /**
      * Implements NativeObserverForTest by holding pointers to C++ callbacks, and invoking
-     * them through nativeResolvePaymentRequestObserverCallback() when the observer's
-     * methods are called.
+     * them through PaymentRequestTestBridgeJni.get().resolvePaymentRequestObserverCallback() when
+     * the observer's methods are called.
      */
     private static class PaymentRequestNativeObserverBridgeToNativeForTest
             implements NativeObserverForTest {
@@ -152,19 +153,23 @@
 
         @Override
         public void onCanMakePaymentCalled() {
-            nativeResolvePaymentRequestObserverCallback(mOnCanMakePaymentCalledPtr);
+            PaymentRequestTestBridgeJni.get().resolvePaymentRequestObserverCallback(
+                    mOnCanMakePaymentCalledPtr);
         }
         @Override
         public void onCanMakePaymentReturned() {
-            nativeResolvePaymentRequestObserverCallback(mOnCanMakePaymentReturnedPtr);
+            PaymentRequestTestBridgeJni.get().resolvePaymentRequestObserverCallback(
+                    mOnCanMakePaymentReturnedPtr);
         }
         @Override
         public void onHasEnrolledInstrumentCalled() {
-            nativeResolvePaymentRequestObserverCallback(mOnHasEnrolledInstrumentCalledPtr);
+            PaymentRequestTestBridgeJni.get().resolvePaymentRequestObserverCallback(
+                    mOnHasEnrolledInstrumentCalledPtr);
         }
         @Override
         public void onHasEnrolledInstrumentReturned() {
-            nativeResolvePaymentRequestObserverCallback(mOnHasEnrolledInstrumentReturnedPtr);
+            PaymentRequestTestBridgeJni.get().resolvePaymentRequestObserverCallback(
+                    mOnHasEnrolledInstrumentReturnedPtr);
         }
 
         @Override
@@ -184,23 +189,28 @@
                 }
             }
 
-            nativeSetAppDescriptions(mSetAppDescriptionsPtr, appLabels, appSublabels, appTotals);
-            nativeResolvePaymentRequestObserverCallback(mOnAppListReadyPtr);
+            PaymentRequestTestBridgeJni.get().setAppDescriptions(
+                    mSetAppDescriptionsPtr, appLabels, appSublabels, appTotals);
+            PaymentRequestTestBridgeJni.get().resolvePaymentRequestObserverCallback(
+                    mOnAppListReadyPtr);
         }
 
         @Override
         public void onShippingSectionVisibilityChange(boolean isShippingSectionVisible) {
-            nativeInvokeBooleanCallback(mSetShippingSectionVisiblePtr, isShippingSectionVisible);
+            PaymentRequestTestBridgeJni.get().invokeBooleanCallback(
+                    mSetShippingSectionVisiblePtr, isShippingSectionVisible);
         }
 
         @Override
         public void onContactSectionVisibilityChange(boolean isContactSectionVisible) {
-            nativeInvokeBooleanCallback(mSetContactSectionVisiblePtr, isContactSectionVisible);
+            PaymentRequestTestBridgeJni.get().invokeBooleanCallback(
+                    mSetContactSectionVisiblePtr, isContactSectionVisible);
         }
 
         @Override
         public void onErrorDisplayed() {
-            nativeResolvePaymentRequestObserverCallback(mOnErrorDisplayedPtr);
+            PaymentRequestTestBridgeJni.get().resolvePaymentRequestObserverCallback(
+                    mOnErrorDisplayedPtr);
         }
 
         private static String ensureNotNull(@Nullable String value) {
@@ -209,23 +219,27 @@
 
         @Override
         public void onNotSupportedError() {
-            nativeResolvePaymentRequestObserverCallback(mOnNotSupportedErrorPtr);
+            PaymentRequestTestBridgeJni.get().resolvePaymentRequestObserverCallback(
+                    mOnNotSupportedErrorPtr);
         }
         @Override
         public void onConnectionTerminated() {
-            nativeResolvePaymentRequestObserverCallback(mOnConnectionTerminatedPtr);
+            PaymentRequestTestBridgeJni.get().resolvePaymentRequestObserverCallback(
+                    mOnConnectionTerminatedPtr);
         }
         @Override
         public void onAbortCalled() {
-            nativeResolvePaymentRequestObserverCallback(mOnAbortCalledPtr);
+            PaymentRequestTestBridgeJni.get().resolvePaymentRequestObserverCallback(
+                    mOnAbortCalledPtr);
         }
         @Override
         public void onCompleteHandled() {
-            nativeResolvePaymentRequestObserverCallback(mOnCompleteHandledPtr);
+            PaymentRequestTestBridgeJni.get().resolvePaymentRequestObserverCallback(
+                    mOnCompleteHandledPtr);
         }
         @Override
         public void onUiDisplayed() {
-            nativeResolvePaymentRequestObserverCallback(mOnUiDisplayed);
+            PaymentRequestTestBridgeJni.get().resolvePaymentRequestObserverCallback(mOnUiDisplayed);
         }
     }
 
@@ -297,14 +311,16 @@
         return false;
     }
 
-    /**
-     * The native method responsible to executing RepeatingClosure pointers.
-     */
-    private static native void nativeResolvePaymentRequestObserverCallback(long callbackPtr);
+    @NativeMethods
+    interface Natives {
+        /**
+         * The native method responsible to executing RepeatingClosure pointers.
+         */
+        void resolvePaymentRequestObserverCallback(long callbackPtr);
 
-    private static native void nativeSetAppDescriptions(
-            long callbackPtr, String[] appLabels, String[] appSublabels, String[] appTotals);
-
-    /** The native method responsible for executing RepatingCallback<void(bool)> pointers. */
-    private static native void nativeInvokeBooleanCallback(long callbackPtr, boolean value);
+        void setAppDescriptions(
+                long callbackPtr, String[] appLabels, String[] appSublabels, String[] appTotals);
+        /** The native method responsible for executing RepatingCallback<void(bool)> pointers. */
+        void invokeBooleanCallback(long callbackPtr, boolean value);
+    }
 }
diff --git a/chrome/test/chromedriver/session_commands.cc b/chrome/test/chromedriver/session_commands.cc
index e309a91..836fa18 100644
--- a/chrome/test/chromedriver/session_commands.cc
+++ b/chrome/test/chromedriver/session_commands.cc
@@ -210,6 +210,7 @@
   caps.Set("webauthn:extension:largeBlob", !capabilities.IsAndroid());
   caps.Set("webauthn:extension:minPinLength", !capabilities.IsAndroid());
   caps.Set("webauthn:extension:credBlob", !capabilities.IsAndroid());
+  caps.Set("webauthn:extension:prf", !capabilities.IsAndroid());
 
   // Chrome-specific extensions.
   const std::string chrome_driver_version_key = base::StringPrintf(
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index c0efd41..a51079d 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -3270,15 +3270,10 @@
     self.assertEqual(
         is_desktop,
         self._driver.capabilities['webauthn:virtualAuthenticators'])
-    self.assertEqual(
-        is_desktop,
-        self._driver.capabilities['webauthn:extension:largeBlob'])
-    self.assertEqual(
-        is_desktop,
-        self._driver.capabilities['webauthn:extension:minPinLength'])
-    self.assertEqual(
-        is_desktop,
-        self._driver.capabilities['webauthn:extension:credBlob'])
+    for extension in ['largeBlob', 'minPinLength', 'credBlob', 'prf']:
+      self.assertEqual(
+          is_desktop,
+          self._driver.capabilities['webauthn:extension:' + extension])
 
   def testCanClickInIframesInShadow(self):
     """Test that you can interact with a iframe within a shadow element.
@@ -3426,6 +3421,14 @@
       # 0xf5 is 'true' in CBOR.
       self.assertTrue(b'credBlob\xf5' in authData)
 
+    with self.subTest(extension = 'prf'):
+      result = addAuthenticatorAndRegister(
+          "prf: {}",
+          {'extensions': ['prf']},
+          )
+      self.assertEqual('OK', result['status'])
+      self.assertEqual(True, result['extensions']['prf']['enabled'])
+
   def testAddVirtualAuthenticatorProtocolVersion(self):
     self._driver.Load(self.GetHttpsUrlForFile(
         '/chromedriver/webauthn_test.html', 'chromedriver.test'))
diff --git a/chrome/test/chromedriver/webauthn_commands.cc b/chrome/test/chromedriver/webauthn_commands.cc
index 5596894a..cec8f76 100644
--- a/chrome/test/chromedriver/webauthn_commands.cc
+++ b/chrome/test/chromedriver/webauthn_commands.cc
@@ -131,6 +131,8 @@
         mapped_params.SetByDottedPath("options.hasCredBlob", true);
       } else if (extension_string == "minPinLength") {
         mapped_params.SetByDottedPath("options.hasMinPinLength", true);
+      } else if (extension_string == "prf") {
+        mapped_params.SetByDottedPath("options.hasPrf", true);
       } else {
         return Status(kUnsupportedOperation,
                       extension_string + kUnrecognizedExtension);
diff --git a/chrome/test/data/webui/cr_components/BUILD.gn b/chrome/test/data/webui/cr_components/BUILD.gn
index 7656f98..6e2748f 100644
--- a/chrome/test/data/webui/cr_components/BUILD.gn
+++ b/chrome/test/data/webui/cr_components/BUILD.gn
@@ -3,65 +3,39 @@
 # found in the LICENSE file.
 
 import("//crypto/features.gni")
-import("//tools/grit/preprocess_if_expr.gni")
-import("//tools/typescript/ts_library.gni")
-import("//ui/webui/resources/tools/generate_grd.gni")
+import("../build_webui_tests.gni")
 
 assert(!is_android && !is_ios)
 
-preprocessed_files = [ "managed_footnote_test.ts" ]
+build_webui_tests("build") {
+  resource_path_prefix = "cr_components"
+  files = [
+    "app_management/app_management_test_support.ts",
+    "app_management/file_handling_item_test.ts",
+    "app_management/permission_item_test.ts",
+    "app_management/window_mode_item_test.ts",
+    "app_management/uninstall_button_test.ts",
+    "color_change_listener_test.ts",
+    "customize_themes_test.ts",
+    "help_bubble_mixin_test.ts",
+    "help_bubble_test.ts",
+    "history_clusters_test.ts",
+    "localized_link_test.ts",
+    "managed_dialog_test.ts",
+    "most_visited_focus_test.ts",
+    "most_visited_test.ts",
+    "most_visited_test_support.ts",
+    "managed_footnote_test.ts",
+  ]
 
-if (use_nss_certs) {
-  # Test files that contain // <if expr> and therefore require preprocessing.
-  preprocessed_files += [ "certificate_manager_test.ts" ]
-  if (is_chromeos) {
-    preprocessed_files += [ "certificate_manager_provisioning_test.ts" ]
+  if (use_nss_certs) {
+    files += [ "certificate_manager_test.ts" ]
+    if (is_chromeos) {
+      files += [ "certificate_manager_provisioning_test.ts" ]
+    }
   }
-}
 
-# Test files that do not require preprocessing. If adding // <if expr> to any
-# file below, move it to the list above.
-non_preprocessed_files = [
-  "app_management/app_management_test_support.ts",
-  "app_management/file_handling_item_test.ts",
-  "app_management/permission_item_test.ts",
-  "app_management/window_mode_item_test.ts",
-  "app_management/uninstall_button_test.ts",
-  "color_change_listener_test.ts",
-  "customize_themes_test.ts",
-  "help_bubble_mixin_test.ts",
-  "help_bubble_test.ts",
-  "history_clusters_test.ts",
-  "localized_link_test.ts",
-  "managed_dialog_test.ts",
-  "most_visited_focus_test.ts",
-  "most_visited_test.ts",
-  "most_visited_test_support.ts",
-]
-
-preprocessed_folder = "$target_gen_dir/preprocessed"
-
-preprocess_if_expr("preprocess") {
-  in_folder = "."
-  out_folder = preprocessed_folder
-  in_files = preprocessed_files
-}
-
-copy("copy") {
-  sources = non_preprocessed_files
-  outputs = [ "$preprocessed_folder/{{source_target_relative}}" ]
-}
-
-ts_library("build_ts") {
-  root_dir = preprocessed_folder
-  out_dir = "$target_gen_dir/tsc"
-  tsconfig_base = "tsconfig_base.json"
-  path_mappings = [ "chrome://webui-test/*|" +
-                    rebase_path("$root_gen_dir/chrome/test/data/webui/tsc/*",
-                                target_gen_dir) ]
-  in_files = non_preprocessed_files + preprocessed_files
-  deps = [
-    "..:build_ts",
+  ts_deps = [
     "//ui/webui/resources/cr_components/app_management:build_ts",
     "//ui/webui/resources/cr_components/color_change_listener:build_ts",
     "//ui/webui/resources/cr_components/customize_themes:build_ts",
@@ -74,22 +48,7 @@
   ]
 
   if (use_nss_certs) {
-    deps +=
+    ts_deps +=
         [ "//ui/webui/resources/cr_components/certificate_manager:build_ts" ]
   }
-
-  extra_deps = [
-    ":copy",
-    ":preprocess",
-  ]
-}
-
-generate_grd("build_grdp") {
-  grd_prefix = "webui_cr_components"
-  out_grd = "$target_gen_dir/resources.grdp"
-
-  deps = [ ":build_ts" ]
-  manifest_files =
-      filter_include(get_target_outputs(":build_ts"), [ "*.manifest" ])
-  resource_path_prefix = "cr_components"
 }
diff --git a/chrome/test/data/webui/new_tab_page/voice_search_overlay_test.ts b/chrome/test/data/webui/new_tab_page/voice_search_overlay_test.ts
index 15f88c7..7fdca574b 100644
--- a/chrome/test/data/webui/new_tab_page/voice_search_overlay_test.ts
+++ b/chrome/test/data/webui/new_tab_page/voice_search_overlay_test.ts
@@ -146,8 +146,8 @@
     // Arrange.
     windowProxy.setResultFor('random', 0.5);
     const result = createResults(2);
-    Object.assign(result.results[0]![0], {transcript: 'hello'});
-    Object.assign(result.results[1]![0], {confidence: 0, transcript: 'world'});
+    Object.assign(result.results[0]![0]!, {transcript: 'hello'});
+    Object.assign(result.results[1]![0]!, {confidence: 0, transcript: 'world'});
 
     // Act.
     mockSpeechRecognition.onresult!(result);
@@ -171,8 +171,8 @@
     loadTimeData.overrideValues({googleBaseUrl: googleBaseUrl});
     windowProxy.setResultFor('random', 0);
     const result = createResults(1);
-    Object.assign(result.results[0], {isFinal: true});
-    Object.assign(result.results[0]![0], {transcript: 'hello world'});
+    Object.assign(result.results[0]!, {isFinal: true});
+    Object.assign(result.results[0]![0]!, {transcript: 'hello world'});
 
     // Act.
     mockSpeechRecognition.onresult!(result);
@@ -256,7 +256,7 @@
   test('on end received shows result text if final result', () => {
     // Arrange.
     const result = createResults(1);
-    Object.assign(result.results[0], {isFinal: true});
+    Object.assign(result.results[0]!, {isFinal: true});
 
     // Act.
     mockSpeechRecognition.onresult!(result);
diff --git a/chrome/test/data/webui/password_manager/BUILD.gn b/chrome/test/data/webui/password_manager/BUILD.gn
index dfd1dc9..72c73208 100644
--- a/chrome/test/data/webui/password_manager/BUILD.gn
+++ b/chrome/test/data/webui/password_manager/BUILD.gn
@@ -2,26 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//tools/typescript/ts_library.gni")
-import("//ui/webui/resources/tools/generate_grd.gni")
+import("../build_webui_tests.gni")
 
 assert(!is_android)
 
-ts_library("build_ts") {
-  root_dir = "."
-  out_dir = "$target_gen_dir/tsc"
-  tsconfig_base = "tsconfig_base.json"
-  path_mappings = [
-    "chrome://password-manager/*|" +
-        rebase_path(
-            "$root_gen_dir/chrome/browser/resources/password_manager/tsc/*",
-            target_gen_dir),
-    "chrome://webui-test/*|" +
-        rebase_path("$root_gen_dir/chrome/test/data/webui/tsc/*",
-                    target_gen_dir),
-  ]
+build_webui_tests("build") {
+  resource_path_prefix = "password_manager"
 
-  in_files = [
+  files = [
     "checkup_details_section_test.ts",
     "checkup_section_test.ts",
     "password_details_card_test.ts",
@@ -38,23 +26,16 @@
     "test_util.ts",
   ]
 
-  definitions = [
+  ts_definitions = [
     "//tools/typescript/definitions/passwords_private.d.ts",
     "//tools/typescript/definitions/settings_private.d.ts",
   ]
 
-  deps = [
-    "..:build_ts",
-    "//chrome/browser/resources/password_manager:build_ts",
-  ]
-}
+  ts_deps = [ "//chrome/browser/resources/password_manager:build_ts" ]
 
-generate_grd("build_grdp") {
-  grd_prefix = "webui_password_manager"
-  out_grd = "$target_gen_dir/resources.grdp"
-
-  deps = [ ":build_ts" ]
-  manifest_files =
-      filter_include(get_target_outputs(":build_ts"), [ "*.manifest" ])
-  resource_path_prefix = "password_manager"
+  ts_path_mappings =
+      [ "chrome://password-manager/*|" +
+        rebase_path(
+            "$root_gen_dir/chrome/browser/resources/password_manager/tsc/*",
+            target_gen_dir) ]
 }
diff --git a/chrome/test/data/webui/privacy_sandbox/BUILD.gn b/chrome/test/data/webui/privacy_sandbox/BUILD.gn
index 8276af41..e4a5c91b 100644
--- a/chrome/test/data/webui/privacy_sandbox/BUILD.gn
+++ b/chrome/test/data/webui/privacy_sandbox/BUILD.gn
@@ -2,35 +2,16 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//tools/typescript/ts_library.gni")
-import("//ui/webui/resources/tools/generate_grd.gni")
+import("../build_webui_tests.gni")
 
-ts_library("build_ts") {
-  root_dir = "."
-  out_dir = "$target_gen_dir/tsc"
-  tsconfig_base = "tsconfig_base.json"
-  path_mappings = [
-    "chrome://privacy-sandbox-dialog/*|" +
+build_webui_tests("build") {
+  resource_path_prefix = "privacy_sandbox"
+
+  files = [ "privacy_sandbox_dialog_test.ts" ]
+  ts_path_mappings =
+      [ "chrome://privacy-sandbox-dialog/*|" +
         rebase_path(
             "$root_gen_dir/chrome/browser/resources/privacy_sandbox/tsc/*",
-            target_gen_dir),
-    "chrome://webui-test/*|" +
-        rebase_path("$root_gen_dir/chrome/test/data/webui/tsc/*",
-                    target_gen_dir),
-  ]
-  in_files = [ "privacy_sandbox_dialog_test.ts" ]
-  deps = [
-    "..:build_ts",
-    "//chrome/browser/resources/privacy_sandbox:build_ts",
-  ]
-}
-
-generate_grd("build_grdp") {
-  grd_prefix = "webui_privacy_sandbox"
-  out_grd = "$target_gen_dir/resources.grdp"
-
-  deps = [ ":build_ts" ]
-  manifest_files =
-      filter_include(get_target_outputs(":build_ts"), [ "*.manifest" ])
-  resource_path_prefix = "privacy_sandbox"
+            target_gen_dir) ]
+  ts_deps = [ "//chrome/browser/resources/privacy_sandbox:build_ts" ]
 }
diff --git a/chrome/test/data/webui/settings/chromeos/app_notifications_subpage_tests.js b/chrome/test/data/webui/settings/chromeos/app_notifications_subpage_tests.js
index f327b97..f86df26f 100644
--- a/chrome/test/data/webui/settings/chromeos/app_notifications_subpage_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/app_notifications_subpage_tests.js
@@ -3,13 +3,11 @@
 // found in the LICENSE file.
 
 import {appNotificationHandlerMojomWebui, createBoolPermission, getBoolPermissionValue, isBoolValue, setAppNotificationProviderForTesting} from 'chrome://os-settings/chromeos/os_settings.js';
-import {Permission} from 'chrome://resources/cr_components/app_management/app_management.mojom-webui.js';
 import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js';
 import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
-
 import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
 const {App, AppNotificationsObserverRemote, Readiness} =
     appNotificationHandlerMojomWebui;
diff --git a/chrome/test/data/webui/settings/chromeos/apps_page_test.js b/chrome/test/data/webui/settings/chromeos/apps_page_test.js
index 4ae2dc9..9bca3f2 100644
--- a/chrome/test/data/webui/settings/chromeos/apps_page_test.js
+++ b/chrome/test/data/webui/settings/chromeos/apps_page_test.js
@@ -5,10 +5,9 @@
 import 'chrome://os-settings/chromeos/os_settings.js';
 
 import {AndroidAppsBrowserProxyImpl, appNotificationHandlerMojomWebui, createBoolPermission, Router, routes, routesMojomWebui, setAppNotificationProviderForTesting} from 'chrome://os-settings/chromeos/os_settings.js';
-import {Permission} from 'chrome://resources/cr_components/app_management/app_management.mojom-webui.js';
 import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js';
-import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js';
 import {getDeepActiveElement} from 'chrome://resources/ash/common/util.js';
+import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
diff --git a/chrome/test/data/webui/side_panel/customize_chrome/themes_test.ts b/chrome/test/data/webui/side_panel/customize_chrome/themes_test.ts
index bde683b..ac15024 100644
--- a/chrome/test/data/webui/side_panel/customize_chrome/themes_test.ts
+++ b/chrome/test/data/webui/side_panel/customize_chrome/themes_test.ts
@@ -89,18 +89,12 @@
     let themes = themesElement.shadowRoot!.querySelectorAll('.theme');
     assertEquals(themes.length, 3);
     assertEquals(
-        'attribution1_1', themes[0]!.querySelector('.label')!.textContent);
-    assertEquals(
         'https://preview_1.jpg',
         themes[0]!.querySelector('img')!.getAttribute('auto-src'));
     assertEquals(
-        'attribution1_2', themes[1]!.querySelector('.label')!.textContent);
-    assertEquals(
         'https://preview_2.jpg',
         themes[1]!.querySelector('img')!.getAttribute('auto-src'));
     assertEquals(
-        'attribution1_3', themes[2]!.querySelector('.label')!.textContent);
-    assertEquals(
         'https://preview_3.jpg',
         themes[2]!.querySelector('img')!.getAttribute('auto-src'));
 
@@ -111,28 +105,18 @@
     themes = themesElement.shadowRoot!.querySelectorAll('.theme');
     assertEquals(themes.length, 5);
     assertEquals(
-        'attribution1_1', themes[0]!.querySelector('.label')!.textContent);
-    assertEquals(
         'https://preview_1.jpg',
         themes[0]!.querySelector('img')!.getAttribute('auto-src'));
     assertEquals(
-        'attribution1_2', themes[1]!.querySelector('.label')!.textContent);
-    assertEquals(
         'https://preview_2.jpg',
         themes[1]!.querySelector('img')!.getAttribute('auto-src'));
     assertEquals(
-        'attribution1_3', themes[2]!.querySelector('.label')!.textContent);
-    assertEquals(
         'https://preview_3.jpg',
         themes[2]!.querySelector('img')!.getAttribute('auto-src'));
     assertEquals(
-        'attribution1_4', themes[3]!.querySelector('.label')!.textContent);
-    assertEquals(
         'https://preview_4.jpg',
         themes[3]!.querySelector('img')!.getAttribute('auto-src'));
     assertEquals(
-        'attribution1_5', themes[4]!.querySelector('.label')!.textContent);
-    assertEquals(
         'https://preview_5.jpg',
         themes[4]!.querySelector('img')!.getAttribute('auto-src'));
   });
diff --git a/chrome/test/data/webui/signin/BUILD.gn b/chrome/test/data/webui/signin/BUILD.gn
index ea59402e..2bda2c4 100644
--- a/chrome/test/data/webui/signin/BUILD.gn
+++ b/chrome/test/data/webui/signin/BUILD.gn
@@ -4,66 +4,44 @@
 
 import("//build/config/chromeos/ui_mode.gni")
 import("//components/signin/features.gni")
-import("//tools/grit/preprocess_if_expr.gni")
-import("//tools/typescript/ts_library.gni")
-import("//ui/webui/resources/tools/generate_grd.gni")
+import("../build_webui_tests.gni")
 
 assert(!is_chromeos_ash)
 
-# Test files that contain // <if expr> and therefore require preprocessing.
-preprocessed_files = [
-  "profile_card_menu_test.ts",
-  "profile_picker_app_test.ts",
-  "profile_picker_main_view_test.ts",
-  "test_manage_profiles_browser_proxy.ts",
-]
+build_webui_tests("build") {
+  resource_path_prefix = "signin"
 
-# Test files that do not require preprocessing. If adding // <if expr> to any
-# file below, move it to the list above.
-non_preprocessed_files = [
-  "enterprise_profile_welcome_test.ts",
-  "local_profile_customization_focus_test.ts",
-  "local_profile_customization_test.ts",
-  "profile_customization_test.ts",
-  "profile_switch_test.ts",
-  "profile_type_choice_test.ts",
-  "sync_confirmation_test.ts",
-  "test_enterprise_profile_welcome_browser_proxy.ts",
-  "test_profile_customization_browser_proxy.ts",
-  "test_sync_confirmation_browser_proxy.ts",
-]
-
-if (enable_dice_support) {
-  non_preprocessed_files += [
-    "dice_web_signin_intercept_test.ts",
-    "signin_reauth_test.ts",
-    "test_dice_web_signin_intercept_browser_proxy.ts",
-    "test_signin_reauth_browser_proxy.ts",
+  files = [
+    "profile_card_menu_test.ts",
+    "profile_picker_app_test.ts",
+    "profile_picker_main_view_test.ts",
+    "test_manage_profiles_browser_proxy.ts",
+    "enterprise_profile_welcome_test.ts",
+    "local_profile_customization_focus_test.ts",
+    "local_profile_customization_test.ts",
+    "profile_customization_test.ts",
+    "profile_switch_test.ts",
+    "profile_type_choice_test.ts",
+    "sync_confirmation_test.ts",
+    "test_enterprise_profile_welcome_browser_proxy.ts",
+    "test_profile_customization_browser_proxy.ts",
+    "test_sync_confirmation_browser_proxy.ts",
   ]
-}
 
-if (is_chromeos_lacros) {
-  non_preprocessed_files += [ "account_selection_lacros_test.ts" ]
-}
+  if (enable_dice_support) {
+    files += [
+      "dice_web_signin_intercept_test.ts",
+      "signin_reauth_test.ts",
+      "test_dice_web_signin_intercept_browser_proxy.ts",
+      "test_signin_reauth_browser_proxy.ts",
+    ]
+  }
 
-preprocessed_folder = "$target_gen_dir/preprocessed"
+  if (is_chromeos_lacros) {
+    files += [ "account_selection_lacros_test.ts" ]
+  }
 
-preprocess_if_expr("preprocess") {
-  in_folder = "./"
-  out_folder = preprocessed_folder
-  in_files = preprocessed_files
-}
-
-copy("copy") {
-  sources = non_preprocessed_files
-  outputs = [ "$preprocessed_folder/{{source_target_relative}}" ]
-}
-
-ts_library("build_ts") {
-  root_dir = preprocessed_folder
-  out_dir = "$target_gen_dir/tsc"
-  tsconfig_base = "tsconfig_base.json"
-  path_mappings = [
+  ts_path_mappings = [
     "chrome://profile-picker/profile_picker.js|" + rebase_path(
             "$root_gen_dir/chrome/browser/resources/signin/profile_picker/tsc/profile_picker.d.ts",
             target_gen_dir),
@@ -85,27 +63,10 @@
     "chrome://signin-reauth/*|" + rebase_path(
             "$root_gen_dir/chrome/browser/resources/signin/tsc/signin_reauth/*",
             target_gen_dir),
-    "chrome://webui-test/*|" +
-        rebase_path("$root_gen_dir/chrome/test/data/webui/tsc/*",
-                    target_gen_dir),
   ]
-  in_files = preprocessed_files + non_preprocessed_files
-  deps = [
-    "..:build_ts",
+
+  ts_deps = [
     "//chrome/browser/resources/signin:build_ts",
     "//chrome/browser/resources/signin/profile_picker:build_ts",
   ]
-  extra_deps = [
-    ":copy",
-    ":preprocess",
-  ]
-}
-
-generate_grd("build_grdp") {
-  grd_prefix = "webui_signin"
-  out_grd = "$target_gen_dir/resources.grdp"
-  deps = [ ":build_ts" ]
-  manifest_files =
-      filter_include(get_target_outputs(":build_ts"), [ "*.manifest" ])
-  resource_path_prefix = "signin"
 }
diff --git a/chrome/test/data/webui/support_tool/BUILD.gn b/chrome/test/data/webui/support_tool/BUILD.gn
index 9904a9d..7383898 100644
--- a/chrome/test/data/webui/support_tool/BUILD.gn
+++ b/chrome/test/data/webui/support_tool/BUILD.gn
@@ -2,36 +2,18 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//tools/typescript/ts_library.gni")
-import("//ui/webui/resources/tools/generate_grd.gni")
+import("../build_webui_tests.gni")
 
 assert(!is_android)
 
-ts_library("build_ts") {
-  root_dir = "."
-  out_dir = "$target_gen_dir/tsc"
-  tsconfig_base = "tsconfig_base.json"
-  path_mappings = [
-    "chrome://support-tool/*|" +
-        rebase_path("$root_gen_dir/chrome/browser/resources/support_tool/tsc/*",
-                    target_gen_dir),
-    "chrome://webui-test/*|" +
-        rebase_path("$root_gen_dir/chrome/test/data/webui/tsc/*",
-                    target_gen_dir),
-  ]
-  in_files = [ "support_tool_test.ts" ]
-  deps = [
-    "..:build_ts",
-    "//chrome/browser/resources/support_tool:build_ts",
-  ]
-}
-
-generate_grd("build_grdp") {
-  grd_prefix = "webui_support_tool"
-  out_grd = "$target_gen_dir/resources.grdp"
-
-  deps = [ ":build_ts" ]
-  manifest_files =
-      filter_include(get_target_outputs(":build_ts"), [ "*.manifest" ])
+build_webui_tests("build") {
   resource_path_prefix = "support_tool"
+
+  files = [ "support_tool_test.ts" ]
+
+  ts_path_mappings =
+      [ "chrome://support-tool/*|" +
+        rebase_path("$root_gen_dir/chrome/browser/resources/support_tool/tsc/*",
+                    target_gen_dir) ]
+  ts_deps = [ "//chrome/browser/resources/support_tool:build_ts" ]
 }
diff --git a/chrome/test/data/webui/test_browser_proxy.ts b/chrome/test/data/webui/test_browser_proxy.ts
index 95f164b..dddded0d 100644
--- a/chrome/test/data/webui/test_browser_proxy.ts
+++ b/chrome/test/data/webui/test_browser_proxy.ts
@@ -175,7 +175,8 @@
     // Tip: check that the |methodName| is being passed to |this.constructor|.
     const methodData = this.resolverMap_.get(methodName);
     assert(
-        methodData, `Method '${methodName}' not found in TestBrowserProxy.`);
+        methodData,
+        `Method '${String(methodName)}' not found in TestBrowserProxy.`);
     return methodData;
   }
 
diff --git a/chrome/test/data/webui/test_store_ts.ts b/chrome/test/data/webui/test_store_ts.ts
index f1ac8b9..f05f36bf 100644
--- a/chrome/test/data/webui/test_store_ts.ts
+++ b/chrome/test/data/webui/test_store_ts.ts
@@ -21,7 +21,7 @@
       storeImplReducer: (state: T, action: Action) => T) {
     super(storeImplEmptyState, storeImplReducer);
 
-    this.data = Object.assign(this.data, initialData);
+    this.data = Object.assign(this.data as object, initialData);
     this.initialized_ = true;
   }
 
diff --git a/chrome/test/delayload/delayloads_unittest.cc b/chrome/test/delayload/delayloads_unittest.cc
index 6a52a76..7be8ee7 100644
--- a/chrome/test/delayload/delayloads_unittest.cc
+++ b/chrome/test/delayload/delayloads_unittest.cc
@@ -196,8 +196,10 @@
       << "Ensure the delayloads_unittests "
          "target was built, instead of delayloads_unittests.exe";
 
+  // Allowlist of modules that do not delayload.
   static const char* const kValidFilePatterns[] = {
     "KERNEL32.dll",
+    "ntdll.dll",
 #if defined(ADDRESS_SANITIZER) && defined(COMPONENT_BUILD)
     "clang_rt.asan_dynamic-i386.dll",
 #endif
@@ -283,8 +285,10 @@
       << "Ensure the delayloads_unittests "
          "target was built, instead of delayloads_unittests.exe";
 
+  // Allowlist of modules that do not delayload.
   static const char* const kValidFilePatterns[] = {
     "KERNEL32.dll",
+    "ntdll.dll",
     "chrome_elf.dll",
     // On 64 bit the Version API's like VerQueryValue come from VERSION.dll.
     // It depends on kernel32, advapi32 and api-ms-win-crt*.dll. This should
diff --git a/chrome/updater/test/integration_tests_impl.cc b/chrome/updater/test/integration_tests_impl.cc
index f706aba..8851a11 100644
--- a/chrome/updater/test/integration_tests_impl.cc
+++ b/chrome/updater/test/integration_tests_impl.cc
@@ -494,7 +494,8 @@
       base::MakeRefCounted<PersistedData>(
           CreateGlobalPrefs(scope)->GetPrefService())
           ->GetProductVersion(app_id);
-  EXPECT_TRUE(app_version.IsValid() && version == app_version);
+  EXPECT_TRUE(app_version.IsValid());
+  EXPECT_EQ(version, app_version);
 }
 
 void Run(UpdaterScope scope, base::CommandLine command_line, int* exit_code) {
diff --git a/chrome/updater/util/win_util.cc b/chrome/updater/util/win_util.cc
index ca0ef68..cd91cf0 100644
--- a/chrome/updater/util/win_util.cc
+++ b/chrome/updater/util/win_util.cc
@@ -371,12 +371,12 @@
                     const std::wstring& value) {
   base::win::RegKey rkey;
   LONG result = rkey.Open(root, key.c_str(), Wow6432(KEY_WRITE));
-  if (!result) {
+  if (result != ERROR_SUCCESS) {
     VLOG(1) << "Failed to open (" << root << ") " << key << ": " << result;
     return false;
   }
   result = rkey.WriteValue(name.c_str(), value.c_str());
-  if (!result) {
+  if (result != ERROR_SUCCESS) {
     VLOG(1) << "Failed to write (" << root << ") " << key << " @ " << name
             << ": " << result;
     return false;
diff --git a/chromecast/metrics/metrics_recorder.h b/chromecast/metrics/metrics_recorder.h
index 5b5fc918..d9bb574 100644
--- a/chromecast/metrics/metrics_recorder.h
+++ b/chromecast/metrics/metrics_recorder.h
@@ -10,6 +10,7 @@
 #include <string>
 
 #include "base/containers/flat_map.h"
+#include "base/time/time.h"
 #include "chromecast/metrics/cast_event_builder.h"
 
 namespace base {
@@ -137,6 +138,9 @@
   // methods can be called from any thread.
   virtual void MeasureTimeUntilEvent(const std::string& event_name,
                                      const std::string& measurement_name) {}
+  virtual void MeasureTimeUntilEvent(const std::string& event_name,
+                                     const std::string& measurement_name,
+                                     base::TimeTicks start_time) {}
   virtual void RecordTimelineEvent(const std::string& event_name) {}
 
   void AddObserver(Observer* o);
diff --git a/chromecast/metrics/metrics_recorder_base.cc b/chromecast/metrics/metrics_recorder_base.cc
index 0ce25edf..7ce0bbc 100644
--- a/chromecast/metrics/metrics_recorder_base.cc
+++ b/chromecast/metrics/metrics_recorder_base.cc
@@ -4,29 +4,6 @@
 
 #include "chromecast/metrics/metrics_recorder_base.h"
 
-#include <stdint.h>
-
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/check.h"
-#include "base/containers/flat_map.h"
-#include "base/functional/bind.h"
-#include "base/functional/callback_helpers.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/no_destructor.h"
-#include "base/notreached.h"
-#include "base/observer_list.h"
-#include "base/synchronization/lock.h"
-#include "base/task/single_thread_task_runner.h"
-#include "base/time/time.h"
-#include "chromecast/metrics/cast_event_builder.h"
-#include "net/base/ip_address.h"
-
 namespace chromecast {
 
 MetricsRecorderBase::MetricsRecorderBase(const base::TickClock* tick_clock)
@@ -42,6 +19,14 @@
   timed_event_recorder_.MeasureTimeUntilEvent(end_event, measurement_name, now);
 }
 
+void MetricsRecorderBase::MeasureTimeUntilEvent(
+    const std::string& end_event,
+    const std::string& measurement_name,
+    base::TimeTicks start_time) {
+  timed_event_recorder_.MeasureTimeUntilEvent(end_event, measurement_name,
+                                              start_time);
+}
+
 void MetricsRecorderBase::RecordTimelineEvent(const std::string& event_name) {
   base::TimeTicks now =
       tick_clock_ ? tick_clock_->NowTicks() : base::TimeTicks::Now();
diff --git a/chromecast/metrics/metrics_recorder_base.h b/chromecast/metrics/metrics_recorder_base.h
index 5444cd5..530b241 100644
--- a/chromecast/metrics/metrics_recorder_base.h
+++ b/chromecast/metrics/metrics_recorder_base.h
@@ -5,7 +5,6 @@
 #ifndef CHROMECAST_METRICS_METRICS_RECORDER_BASE_H_
 #define CHROMECAST_METRICS_METRICS_RECORDER_BASE_H_
 
-#include <memory>
 #include <string>
 
 #include "base/time/tick_clock.h"
@@ -21,6 +20,9 @@
   // MetricsRecorder implementation (partial):
   void MeasureTimeUntilEvent(const std::string& event_name,
                              const std::string& measurement_name) override;
+  void MeasureTimeUntilEvent(const std::string& event_name,
+                             const std::string& measurement_name,
+                             base::TimeTicks start_time) override;
   void RecordTimelineEvent(const std::string& event_name) override;
 
  protected:
diff --git a/chromeos/ash/components/drivefs/drivefs_pin_manager.cc b/chromeos/ash/components/drivefs/drivefs_pin_manager.cc
index 61a64f5..3a3171e 100644
--- a/chromeos/ash/components/drivefs/drivefs_pin_manager.cc
+++ b/chromeos/ash/components/drivefs/drivefs_pin_manager.cc
@@ -486,9 +486,9 @@
   progress_.stage = SetupStage::kCalculatingFreeSpace;
   NotifyProgress();
 
-  get_free_space_.Run(profile_path_.AppendASCII("GCache"),
-                      base::BindOnce(&DriveFsPinManager::OnFreeSpaceRetrieved,
-                                     weak_ptr_factory_.GetWeakPtr()));
+  get_free_space_.Run(
+      profile_path_.AppendASCII("GCache"),
+      base::BindOnce(&DriveFsPinManager::OnFreeSpaceRetrieved, GetWeakPtr()));
 }
 
 void DriveFsPinManager::Stop() {
@@ -536,9 +536,8 @@
 
   drivefs_interface_->StartSearchQuery(
       search_query_.BindNewPipeAndPassReceiver(), CreateMyDriveQuery());
-  search_query_->GetNextPage(
-      base::BindOnce(&DriveFsPinManager::OnSearchResultForSizeCalculation,
-                     weak_ptr_factory_.GetWeakPtr()));
+  search_query_->GetNextPage(base::BindOnce(
+      &DriveFsPinManager::OnSearchResultForSizeCalculation, GetWeakPtr()));
 }
 
 void DriveFsPinManager::OnSearchResultForSizeCalculation(
@@ -579,9 +578,8 @@
 
   NotifyProgress();
   DCHECK(search_query_);
-  search_query_->GetNextPage(
-      base::BindOnce(&DriveFsPinManager::OnSearchResultForSizeCalculation,
-                     weak_ptr_factory_.GetWeakPtr()));
+  search_query_->GetNextPage(base::BindOnce(
+      &DriveFsPinManager::OnSearchResultForSizeCalculation, GetWeakPtr()));
 }
 
 void DriveFsPinManager::Complete(const SetupStage stage) {
@@ -666,8 +664,7 @@
   // offline from the `files_to_track_` map.
   base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
       FROM_HERE,
-      base::BindOnce(&DriveFsPinManager::CheckUnstartedFiles,
-                     weak_ptr_factory_.GetWeakPtr()),
+      base::BindOnce(&DriveFsPinManager::CheckUnstartedFiles, GetWeakPtr()),
       kPeriodicRemovalInterval);
 
   PinSomeFiles();
@@ -692,8 +689,8 @@
     VLOG(2) << "Pinning " << id << " " << Quote(path);
     drivefs_interface_->SetPinnedByStableId(
         static_cast<int64_t>(id), true,
-        base::BindOnce(&DriveFsPinManager::OnFilePinned,
-                       weak_ptr_factory_.GetWeakPtr(), id, path));
+        base::BindOnce(&DriveFsPinManager::OnFilePinned, GetWeakPtr(), id,
+                       path));
 
     const Files::insert_return_type ir =
         files_to_track_.insert(std::move(node));
@@ -835,8 +832,8 @@
     VLOG(2) << "Checking changed " << id << " " << Quote(path);
     drivefs_interface_->GetMetadataByStableId(
         static_cast<int64_t>(id),
-        base::BindOnce(&DriveFsPinManager::OnMetadataRetrieved,
-                       weak_ptr_factory_.GetWeakPtr(), id, path));
+        base::BindOnce(&DriveFsPinManager::OnMetadataRetrieved, GetWeakPtr(),
+                       id, path));
   }
 }
 
@@ -852,18 +849,18 @@
   }
 
   VLOG(3) << "Notifying observers";
-  for (DriveFsBulkPinObserver& observer : observers_) {
-    observer.OnSetupProgress(progress_);
+  for (Observer& observer : observers_) {
+    observer.OnProgress(progress_);
   }
   VLOG(3) << "Notified observers";
 }
 
-void DriveFsPinManager::AddObserver(DriveFsBulkPinObserver* const observer) {
+void DriveFsPinManager::AddObserver(Observer* const observer) {
   observers_.AddObserver(observer);
   VLOG(3) << "Added observer " << observer;
 }
 
-void DriveFsPinManager::RemoveObserver(DriveFsBulkPinObserver* observer) {
+void DriveFsPinManager::RemoveObserver(Observer* const observer) {
   observers_.RemoveObserver(observer);
   VLOG(3) << "Removed observer " << observer;
 }
@@ -877,15 +874,14 @@
       VLOG(2) << "Checking unstarted " << id << " " << Quote(path);
       drivefs_interface_->GetMetadataByStableId(
           static_cast<int64_t>(id),
-          base::BindOnce(&DriveFsPinManager::OnMetadataRetrieved,
-                         weak_ptr_factory_.GetWeakPtr(), id, path));
+          base::BindOnce(&DriveFsPinManager::OnMetadataRetrieved, GetWeakPtr(),
+                         id, path));
     }
   }
 
   base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
       FROM_HERE,
-      base::BindOnce(&DriveFsPinManager::CheckUnstartedFiles,
-                     weak_ptr_factory_.GetWeakPtr()),
+      base::BindOnce(&DriveFsPinManager::CheckUnstartedFiles, GetWeakPtr()),
       kPeriodicRemovalInterval);
 
   PinSomeFiles();
diff --git a/chromeos/ash/components/drivefs/drivefs_pin_manager.h b/chromeos/ash/components/drivefs/drivefs_pin_manager.h
index 5b2d7694..cd66f9e6 100644
--- a/chromeos/ash/components/drivefs/drivefs_pin_manager.h
+++ b/chromeos/ash/components/drivefs/drivefs_pin_manager.h
@@ -101,19 +101,6 @@
   SetupStage stage = SetupStage::kNotStarted;
 };
 
-// Observe the setup progress via subscribing as an observer on the
-// `DriveFsPinManager`.
-// TODO(b/261633796): Send back monitoring events to the observers.
-class DriveFsBulkPinObserver {
- public:
-  // When the setup progresses, this returns back the information gathered and
-  // the current stage of setup.
-  virtual void OnSetupProgress(const SetupProgress& progress) = 0;
-
- protected:
-  virtual ~DriveFsBulkPinObserver() = default;
-};
-
 // Manages bulk pinning of items via DriveFS. This class handles the following:
 //  - Manage batching of pin actions to avoid sending too many events at once.
 //  - Ensure disk space is not being exceeded whilst pinning files.
@@ -156,8 +143,15 @@
     return progress_;
   }
 
-  void AddObserver(DriveFsBulkPinObserver* observer);
-  void RemoveObserver(DriveFsBulkPinObserver* observer);
+  // Observer interface.
+  class Observer : public base::CheckedObserver {
+   public:
+    // Called when the setup progresses.
+    virtual void OnProgress(const SetupProgress& progress) = 0;
+  };
+
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
 
   // drivefs::DriveFsHostObserver
   void OnSyncingStatusUpdate(const mojom::SyncingStatus& status) override;
@@ -168,6 +162,10 @@
   // Stable ID provided by DriveFS.
   enum class StableId : int64_t { kNone = 0 };
 
+  base::WeakPtr<DriveFsPinManager> GetWeakPtr() {
+    return weak_ptr_factory_.GetWeakPtr();
+  }
+
  private:
   // Adds an item to the files to pin.  Does nothing if an item with the same ID
   // already exists in files_to_pin_. Updates the total number of bytes to
@@ -275,7 +273,7 @@
   const SpaceGetter get_free_space_;
 
   SetupProgress progress_ GUARDED_BY_CONTEXT(sequence_checker_);
-  base::ObserverList<DriveFsBulkPinObserver>::Unchecked observers_;
+  base::ObserverList<Observer> observers_;
 
   const base::FilePath profile_path_;
   const raw_ptr<mojom::DriveFs> drivefs_interface_;
diff --git a/chromeos/ash/components/drivefs/drivefs_pin_manager_unittest.cc b/chromeos/ash/components/drivefs/drivefs_pin_manager_unittest.cc
index e4aaa08d..aad90c9 100644
--- a/chromeos/ash/components/drivefs/drivefs_pin_manager_unittest.cc
+++ b/chromeos/ash/components/drivefs/drivefs_pin_manager_unittest.cc
@@ -655,7 +655,7 @@
   new_run_loop.Run();
 }
 
-class TestBulkPinObserver : public DriveFsBulkPinObserver {
+class TestBulkPinObserver : public DriveFsPinManager::Observer {
  public:
   TestBulkPinObserver() = default;
 
@@ -664,7 +664,7 @@
 
   ~TestBulkPinObserver() override = default;
 
-  MOCK_METHOD(void, OnSetupProgress, (const SetupProgress&), (override));
+  MOCK_METHOD(void, OnProgress, (const SetupProgress&), (override));
 };
 
 TEST_F(DriveFsPinManagerTest,
@@ -702,7 +702,7 @@
           });
 
   TestBulkPinObserver mock_pin_observer;
-  EXPECT_CALL(mock_pin_observer, OnSetupProgress(_)).Times(AnyNumber());
+  EXPECT_CALL(mock_pin_observer, OnProgress(_)).Times(AnyNumber());
 
   DriveFsPinManager manager(
       temp_dir_.GetPath(), &mock_drivefs_,
@@ -721,10 +721,10 @@
   base::RunLoop setup_progress_run_loop;
   SetState(status->item_events, mojom::ItemEvent::State::kInProgress);
   status->item_events.at(0)->bytes_transferred = 10;
-  EXPECT_CALL(mock_pin_observer,
-              OnSetupProgress(
-                  AllOf(Field(&SetupProgress::transferred_bytes, 10),
-                        Field(&SetupProgress::stage, SetupStage::kSyncing))))
+  EXPECT_CALL(
+      mock_pin_observer,
+      OnProgress(AllOf(Field(&SetupProgress::transferred_bytes, 10),
+                       Field(&SetupProgress::stage, SetupStage::kSyncing))))
       .Times(1)
       .WillOnce(RunClosure(setup_progress_run_loop.QuitClosure()));
   manager.OnSyncingStatusUpdate(*status);
@@ -745,10 +745,10 @@
       .WillOnce(RunClosure(new_run_loop.QuitClosure()));
   SetState(status->item_events, mojom::ItemEvent::State::kCompleted);
   status->item_events.at(0)->bytes_transferred = 128;
-  EXPECT_CALL(mock_pin_observer,
-              OnSetupProgress(
-                  AllOf(Field(&SetupProgress::transferred_bytes, 128),
-                        Field(&SetupProgress::stage, SetupStage::kSuccess))))
+  EXPECT_CALL(
+      mock_pin_observer,
+      OnProgress(AllOf(Field(&SetupProgress::transferred_bytes, 128),
+                       Field(&SetupProgress::stage, SetupStage::kSuccess))))
       .Times(1)
       .WillOnce(RunClosure(setup_progress_run_loop.QuitClosure()));
   manager.OnSyncingStatusUpdate(*status);
diff --git a/chromeos/components/quick_answers/utils/spell_check_language.cc b/chromeos/components/quick_answers/utils/spell_check_language.cc
index 1d3f4a7..532df621 100644
--- a/chromeos/components/quick_answers/utils/spell_check_language.cc
+++ b/chromeos/components/quick_answers/utils/spell_check_language.cc
@@ -140,9 +140,7 @@
   }
 
   task_runner_->PostTaskAndReplyWithResult(
-      FROM_HERE,
-      base::BindOnce(&base::ReplaceFile, tmp_path, dictionary_file_path_,
-                     nullptr),
+      FROM_HERE, base::BindOnce(&base::PathExists, dictionary_file_path_),
       base::BindOnce(&SpellCheckLanguage::OnSaveDictionaryDataComplete,
                      weak_factory_.GetWeakPtr()));
 }
@@ -190,10 +188,11 @@
         network::SimpleURLLoader::RetryMode::RETRY_ON_5XX |
             network::SimpleURLLoader::RETRY_ON_NETWORK_CHANGE);
 
-    loader_->DownloadToTempFile(
+    loader_->DownloadToFile(
         url_loader_factory_.get(),
         base::BindOnce(&SpellCheckLanguage::OnSimpleURLLoaderComplete,
-                       base::Unretained(this)));
+                       base::Unretained(this)),
+        dictionary_file_path_);
     return;
   }
 
diff --git a/chromeos/profiles/arm.afdo.newest.txt b/chromeos/profiles/arm.afdo.newest.txt
index e4a51e88..ab10ca1 100644
--- a/chromeos/profiles/arm.afdo.newest.txt
+++ b/chromeos/profiles/arm.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-arm-none-111-5481.21-1673265798-benchmark-111.0.5534.0-r1-redacted.afdo.xz
+chromeos-chrome-arm-none-111-5481.32-1673869449-benchmark-111.0.5544.0-r1-redacted.afdo.xz
diff --git a/chromeos/services/network_config/cros_network_config.cc b/chromeos/services/network_config/cros_network_config.cc
index b934c0a..ea3f5678 100644
--- a/chromeos/services/network_config/cros_network_config.cc
+++ b/chromeos/services/network_config/cros_network_config.cc
@@ -1292,11 +1292,12 @@
 mojom::ManagedApnListPtr GetManagedApnList(const base::Value* value) {
   if (!value)
     return nullptr;
+  bool is_apn_revamp_enabled = ash::features::IsApnRevampEnabled();
   if (value->is_list()) {
     auto result = mojom::ManagedApnList::New();
     std::vector<mojom::ApnPropertiesPtr> active;
     for (const base::Value& e : value->GetList())
-      active.push_back(GetApnProperties(e.GetDict()));
+      active.push_back(GetApnProperties(e.GetDict(), is_apn_revamp_enabled));
     result->active_value = std::move(active);
     return result;
   } else if (value->is_dict()) {
@@ -1307,12 +1308,14 @@
     }
     auto result = mojom::ManagedApnList::New();
     for (const base::Value& e : managed_dict.active_value.GetList())
-      result->active_value.push_back(GetApnProperties(e.GetDict()));
+      result->active_value.push_back(
+          GetApnProperties(e.GetDict(), is_apn_revamp_enabled));
     result->policy_source = managed_dict.policy_source;
     if (!managed_dict.policy_value.is_none()) {
       result->policy_value = std::vector<mojom::ApnPropertiesPtr>();
       for (const base::Value& e : managed_dict.policy_value.GetList())
-        result->policy_value->push_back(GetApnProperties(e.GetDict()));
+        result->policy_value->push_back(
+            GetApnProperties(e.GetDict(), is_apn_revamp_enabled));
     }
     return result;
   }
@@ -1322,7 +1325,8 @@
 
 bool DoesDefaultApnExist(const base::Value::List& apns) {
   for (const base::Value& apn : apns) {
-    mojom::ApnPropertiesPtr apn_ptr = GetApnProperties(apn.GetDict());
+    mojom::ApnPropertiesPtr apn_ptr =
+        GetApnProperties(apn.GetDict(), ash::features::IsApnRevampEnabled());
     for (const mojom::ApnType& type : apn_ptr->apn_types) {
       if (type == mojom::ApnType::kDefault) {
         return true;
@@ -1799,8 +1803,10 @@
       const base::Value* apn_dict =
           GetDictionary(cellular_dict, ::onc::cellular::kLastGoodAPN);
       if (apn_dict) {
-        cellular->last_good_apn = GetApnProperties(apn_dict->GetDict());
-        if (ash::features::IsApnRevampEnabled()) {
+        bool is_apn_revamp_enabled = ash::features::IsApnRevampEnabled();
+        cellular->last_good_apn =
+            GetApnProperties(apn_dict->GetDict(), is_apn_revamp_enabled);
+        if (is_apn_revamp_enabled) {
           const absl::optional<std::string> connection_state =
               GetString(properties, ::onc::network_config::kConnectionState);
 
@@ -1810,7 +1816,8 @@
           // present when the network is not connected.
           if (connection_state &&
               *connection_state == ::onc::connection_state::kConnected) {
-            cellular->connected_apn = GetApnProperties(apn_dict->GetDict());
+            cellular->connected_apn =
+                GetApnProperties(apn_dict->GetDict(), true);
           }
         }
       }
@@ -3104,8 +3111,10 @@
   for (const auto& apn : *custom_apn_list) {
     DCHECK(apn.is_dict());
 
-    mojom::ApnPropertiesPtr mojo_apn = GetApnProperties(apn.GetDict());
-    if (ash::features::IsApnRevampEnabled()) {
+    bool is_apn_revamp_enabled = ash::features::IsApnRevampEnabled();
+    mojom::ApnPropertiesPtr mojo_apn =
+        GetApnProperties(apn.GetDict(), is_apn_revamp_enabled);
+    if (is_apn_revamp_enabled) {
       mojo_apn->state = OncApnStateTypeToMojo(
           base::OptionalToPtr(GetString(&apn, ::onc::cellular_apn::kState)));
     }
diff --git a/chromeos/services/network_config/public/cpp/BUILD.gn b/chromeos/services/network_config/public/cpp/BUILD.gn
index bfec413..18f2fa1 100644
--- a/chromeos/services/network_config/public/cpp/BUILD.gn
+++ b/chromeos/services/network_config/public/cpp/BUILD.gn
@@ -13,7 +13,6 @@
   ]
 
   deps = [
-    "//ash/constants",
     "//chromeos/services/network_config/public/mojom",
     "//components/onc",
     "//services/network/public/cpp:ip_address_mojom_support",
diff --git a/chromeos/services/network_config/public/cpp/cros_network_config_util.cc b/chromeos/services/network_config/public/cpp/cros_network_config_util.cc
index 5c45be3..63db649 100644
--- a/chromeos/services/network_config/public/cpp/cros_network_config_util.cc
+++ b/chromeos/services/network_config/public/cpp/cros_network_config_util.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "chromeos/services/network_config/public/cpp/cros_network_config_util.h"
-#include "ash/constants/ash_features.h"
 #include "components/onc/onc_constants.h"
 
 namespace chromeos::network_config {
@@ -60,7 +59,6 @@
 
 mojom::ApnAuthenticationType OncApnAuthenticationTypeToMojo(
     const std::string& authentication_type) {
-  DCHECK(ash::features::IsApnRevampEnabled());
   if (authentication_type.empty() ||
       authentication_type ==
           ::onc::cellular_apn::kAuthenticationTypeAutomatic) {
@@ -79,7 +77,6 @@
 }
 
 mojom::ApnIpType OncApnIpTypeToMojo(const std::string& ip_type) {
-  DCHECK(ash::features::IsApnRevampEnabled());
   if (ip_type.empty() || ip_type == ::onc::cellular_apn::kIpTypeAutomatic) {
     return mojom::ApnIpType::kAutomatic;
   }
@@ -184,7 +181,6 @@
 
 std::vector<mojom::ApnType> OncApnTypesToMojo(
     const std::vector<std::string>& apn_types) {
-  DCHECK(ash::features::IsApnRevampEnabled());
   DCHECK(!apn_types.empty());
   std::vector<mojom::ApnType> apn_types_result;
   apn_types_result.reserve(apn_types.size());
@@ -204,7 +200,8 @@
   return apn_types_result;
 }
 
-mojom::ApnPropertiesPtr GetApnProperties(const base::Value::Dict& onc_apn) {
+mojom::ApnPropertiesPtr GetApnProperties(const base::Value::Dict& onc_apn,
+                                         bool is_apn_revamp_enabled) {
   auto apn = mojom::ApnProperties::New();
   apn->access_point_name =
       GetRequiredString(onc_apn, ::onc::cellular_apn::kAccessPointName);
@@ -217,7 +214,7 @@
   apn->username = GetString(onc_apn, ::onc::cellular_apn::kUsername);
   apn->attach = GetString(onc_apn, ::onc::cellular_apn::kAttach);
 
-  if (ash::features::IsApnRevampEnabled()) {
+  if (is_apn_revamp_enabled) {
     apn->id = GetString(onc_apn, ::onc::cellular_apn::kId);
     // TODO(b/162365553) Remove missing value checking after Shill implements
     // the interface.
diff --git a/chromeos/services/network_config/public/cpp/cros_network_config_util.h b/chromeos/services/network_config/public/cpp/cros_network_config_util.h
index ac9bad34..319fb6e 100644
--- a/chromeos/services/network_config/public/cpp/cros_network_config_util.h
+++ b/chromeos/services/network_config/public/cpp/cros_network_config_util.h
@@ -40,7 +40,8 @@
     const std::vector<std::string>& apn_types);
 
 // Creates a Mojo APN from a ONC dictionary.
-mojom::ApnPropertiesPtr GetApnProperties(const base::Value::Dict& onc_apn);
+mojom::ApnPropertiesPtr GetApnProperties(const base::Value::Dict& onc_apn,
+                                         bool is_apn_revamp_enabled);
 
 }  // namespace network_config
 }  // namespace chromeos
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 753a72c..c9c4a65 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -581,6 +581,7 @@
       "//components/metrics/structured/mojom:unit_tests",
       "//components/ownership:unit_tests",
       "//components/user_manager:unit_tests",
+      "//components/variations/cros:unit_tests",
     ]
   }
 
diff --git a/components/autofill/core/browser/autofill_experiments_unittest.cc b/components/autofill/core/browser/autofill_experiments_unittest.cc
index b04de383..9b789cd 100644
--- a/components/autofill/core/browser/autofill_experiments_unittest.cc
+++ b/components/autofill/core/browser/autofill_experiments_unittest.cc
@@ -284,8 +284,10 @@
 TEST_F(
     AutofillExperimentsTest,
     IsCardUploadEnabled_UserEmailWithSupportedAdditionalDomain_NotAllowedIfFlagOff) {
-  scoped_feature_list_.InitAndDisableFeature(
-      features::kAutofillUpstreamAllowAdditionalEmailDomains);
+  scoped_feature_list_.InitWithFeatures(
+      /*enabled_features=*/{}, /*disabled_features=*/{
+          features::kAutofillUpstreamAllowAdditionalEmailDomains,
+          features::kAutofillUpstreamAllowAllEmailDomains});
   EXPECT_FALSE(IsCreditCardUploadEnabled(
       "cool.user@hotmail.com",
       AutofillSyncSigninState::kSignedInAndSyncFeatureEnabled));
diff --git a/components/autofill/core/common/autofill_payments_features.cc b/components/autofill/core/common/autofill_payments_features.cc
index 537f52f..c2e1003b 100644
--- a/components/autofill/core/common/autofill_payments_features.cc
+++ b/components/autofill/core/common/autofill_payments_features.cc
@@ -249,7 +249,12 @@
 // the user's email domain.
 BASE_FEATURE(kAutofillUpstreamAllowAllEmailDomains,
              "AutofillUpstreamAllowAllEmailDomains",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+#if BUILDFLAG(IS_ANDROID)
+             base::FEATURE_DISABLED_BY_DEFAULT
+#else
+             base::FEATURE_ENABLED_BY_DEFAULT
+#endif
+);
 
 // The delay required since the last strike before offering another virtual card
 // enrollment attempt.
diff --git a/components/browser_ui/settings/android/BUILD.gn b/components/browser_ui/settings/android/BUILD.gn
index 70a0824..2bee722 100644
--- a/components/browser_ui/settings/android/BUILD.gn
+++ b/components/browser_ui/settings/android/BUILD.gn
@@ -130,6 +130,7 @@
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
+    "//third_party/androidx:androidx_constraintlayout_constraintlayout_java",
     "//third_party/androidx:androidx_fragment_fragment_java",
     "//third_party/androidx:androidx_preference_preference_java",
     "//third_party/androidx:androidx_test_runner_java",
@@ -171,6 +172,7 @@
   deps = [
     ":java_resources",
     ":managed_prefs_java_resources",
+    "//third_party/androidx:androidx_constraintlayout_constraintlayout_java",
     "//third_party/androidx:androidx_preference_preference_java",
     "//ui/android:ui_java_resources",
   ]
diff --git a/components/browser_ui/settings/android/java/managed_prefs_java_resources/layout/chrome_managed_preference.xml b/components/browser_ui/settings/android/java/managed_prefs_java_resources/layout/chrome_managed_preference.xml
index d8c9a43..64d3b6d 100644
--- a/components/browser_ui/settings/android/java/managed_prefs_java_resources/layout/chrome_managed_preference.xml
+++ b/components/browser_ui/settings/android/java/managed_prefs_java_resources/layout/chrome_managed_preference.xml
@@ -5,89 +5,115 @@
 found in the LICENSE file.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:background="?android:attr/activatedBackgroundIndicator"
-    android:baselineAligned="false"
     android:focusable="true"
-    android:gravity="start"
+    android:background="?android:attr/activatedBackgroundIndicator"
     android:minHeight="?android:attr/listPreferredItemHeightSmall"
-    android:orientation="vertical"
-    android:paddingBottom="16dp"
     android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
     android:paddingStart="?android:attr/listPreferredItemPaddingStart"
-    android:paddingTop="16dp" >
+    app:layout_constraintHorizontal_chainStyle="spread_inside">
 
+    <!-- TODO(crbug/1401340): Flatten this layout by moving the image view out of the icon frame,
+                              while keeping it left-aligned inside a box that is 56dp-wide that can
+                              be hidden when icon is hidden. -->
     <LinearLayout
-        android:layout_width="match_parent"
+        android:id="@+id/icon_frame"
+        android:layout_width="56dp"
         android:layout_height="wrap_content"
-        android:gravity="center_vertical"
-        android:baselineAligned="false"
-        android:orientation="horizontal" >
+        android:gravity="center_vertical|start"
+        android:orientation="horizontal"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="@android:id/title"
+        app:layout_constraintBottom_toBottomOf="@android:id/summary" >
 
-      <LinearLayout
-          android:id="@+id/icon_frame"
-          android:layout_width="56dp"
-          android:layout_height="32dp"
-          android:gravity="center_vertical|start"
-          android:orientation="horizontal">
-
-          <ImageView
-              android:id="@android:id/icon"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"
-              android:adjustViewBounds="true"
-              android:scaleType="fitCenter"
-              app:maxHeight="48dp"
-              app:maxWidth="48dp"
-              tools:ignore="ContentDescription" />
-
-      </LinearLayout>
-
-      <RelativeLayout
-          android:layout_width="0dp"
-          android:layout_height="wrap_content"
-          android:layout_marginBottom="0dp"
-          android:layout_marginEnd="0dp"
-          android:layout_marginStart="0dp"
-          android:layout_marginTop="0dp"
-          android:layout_weight="1" >
-
-          <TextView
-              android:id="@android:id/title"
-              style="@style/PreferenceTitle"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content" />
-
-          <TextView
-              android:id="@android:id/summary"
-              style="@style/PreferenceSummary"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"
-              android:layout_alignStart="@android:id/title"
-              android:layout_below="@android:id/title" />
-
-      </RelativeLayout>
-
-      <LinearLayout android:id="@android:id/widget_frame"
-          android:layout_width="wrap_content"
-          android:layout_height="match_parent"
-          android:minWidth="64dp"
-          android:gravity="center_vertical|end"
-          android:orientation="vertical" />
+        <ImageView
+            android:id="@android:id/icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:adjustViewBounds="true"
+            android:importantForAccessibility="no"
+            android:scaleType="fitCenter"
+            app:maxHeight="48dp"
+            app:maxWidth="48dp" />
 
     </LinearLayout>
 
+    <TextView
+        android:id="@android:id/title"
+        style="@style/PreferenceTitle"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        app:layout_constraintHorizontal_weight="1"
+        app:layout_constraintStart_toEndOf="@app:id/icon_frame"
+        app:layout_constraintTop_toBottomOf="@+id/top_space"
+        app:layout_constraintEnd_toStartOf="@android:id/widget_frame" />
+
+    <TextView
+        android:id="@android:id/summary"
+        style="@style/PreferenceSummary"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        app:layout_constraintHorizontal_weight="1"
+        app:layout_constraintStart_toEndOf="@app:id/icon_frame"
+        app:layout_constraintTop_toBottomOf="@android:id/title"
+        app:layout_constraintEnd_toStartOf="@android:id/widget_frame" />
+
+    <LinearLayout
+        android:id="@android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:gravity="center_vertical|end"
+        android:minWidth="64dp"
+        android:orientation="vertical"
+        app:layout_constraintTop_toTopOf="@android:id/title"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintBottom_toBottomOf="@android:id/summary" />
+
     <org.chromium.components.browser_ui.widget.text.TextViewWithCompoundDrawables
         android:id="@+id/managed_disclaimer_text"
         style="@style/ManagedDisclaimerView"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:layout_marginTop="8dp"
         android:drawablePadding="8dp"
-        android:paddingTop="8dp"
-        android:visibility="gone" />
+        android:visibility="gone"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@android:id/summary"
+        app:layout_constraintEnd_toEndOf="parent" />
 
-</LinearLayout>
+    <!-- Reference to the summary and managed disclaimer view that allows constraining views to
+         the bottom of the bottommost view that is displayed (ether the disclaimer view for managed
+         prefs or the summary view for non-managed preferences). Used for setting the bottom space
+         for both managed and unmanaged cases. -->
+    <androidx.constraintlayout.widget.Barrier
+        android:id="@+id/barrier_for_bottom_space"
+        android:layout_width="wrap_content"
+        android:layout_height="0dp"
+        app:barrierDirection="bottom"
+        app:constraint_referenced_ids="summary,managed_disclaimer_text" />
+
+    <!-- Top padding for the title/summary block. This can't be done by setting top-margin for
+         the title, because the title may be hidden for some preferences
+         (e.g. TextMessagePreference). -->
+    <Space
+        android:id="@+id/top_space"
+        android:layout_width="0dp"
+        android:layout_height="16dp"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintEnd_toEndOf="parent" />
+
+    <Space
+        android:id="@+id/bottom_space"
+        android:layout_width="0dp"
+        android:layout_height="16dp"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/barrier_for_bottom_space"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableListLayout.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableListLayout.java
index 1194344..37f9cd7 100644
--- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableListLayout.java
+++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableListLayout.java
@@ -25,6 +25,8 @@
 import androidx.recyclerview.widget.RecyclerView.ItemAnimator;
 import androidx.recyclerview.widget.RecyclerView.OnScrollListener;
 
+import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.components.browser_ui.widget.FadingShadow;
 import org.chromium.components.browser_ui.widget.FadingShadowView;
 import org.chromium.components.browser_ui.widget.R;
@@ -32,6 +34,7 @@
 import org.chromium.components.browser_ui.widget.displaystyle.HorizontalDisplayStyle;
 import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
 import org.chromium.components.browser_ui.widget.displaystyle.UiConfig.DisplayStyle;
+import org.chromium.components.browser_ui.widget.gesture.BackPressHandler;
 import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelegate.SelectionObserver;
 import org.chromium.ui.widget.LoadingView;
 
@@ -49,8 +52,8 @@
  *
  * @param <E> The type of the selectable items this layout holds.
  */
-public class SelectableListLayout<E>
-        extends FrameLayout implements DisplayStyleObserver, SelectionObserver<E> {
+public class SelectableListLayout<E> extends FrameLayout
+        implements DisplayStyleObserver, SelectionObserver<E>, BackPressHandler {
     private static final int WIDE_DISPLAY_MIN_PADDING_DP = 16;
     private RecyclerView.Adapter mAdapter;
     private ViewStub mToolbarStub;
@@ -66,6 +69,9 @@
 
     private UiConfig mUiConfig;
 
+    private final ObservableSupplierImpl<Boolean> mBackPressStateSupplier =
+            new ObservableSupplierImpl<>();
+
     private final AdapterDataObserver mAdapterObserver = new AdapterDataObserver() {
         @Override
         public void onChanged() {
@@ -287,6 +293,7 @@
 
     @Override
     public void onSelectionStateChange(List<E> selectedItems) {
+        onBackPressStateChanged();
         setToolbarShadowVisibility();
     }
 
@@ -308,6 +315,7 @@
         mRecyclerView.setItemAnimator(null);
         mToolbarShadow.setVisibility(View.VISIBLE);
         mEmptyView.setText(searchEmptyString);
+        onBackPressStateChanged();
     }
 
     /**
@@ -317,6 +325,7 @@
         mRecyclerView.setItemAnimator(mItemAnimator);
         setToolbarShadowVisibility();
         mEmptyView.setText(mEmptyStringResId);
+        onBackPressStateChanged();
     }
 
     /**
@@ -389,4 +398,20 @@
 
         return false;
     }
+
+    @Override
+    public void handleBackPress() {
+        var ret = onBackPressed();
+        assert ret;
+    }
+
+    @Override
+    public ObservableSupplier<Boolean> getHandleBackPressChangedSupplier() {
+        return mBackPressStateSupplier;
+    }
+
+    private void onBackPressStateChanged() {
+        mBackPressStateSupplier.set(
+                mToolbar.getSelectionDelegate().isSelectionEnabled() || mToolbar.isSearching());
+    }
 }
diff --git a/components/browsing_data/core/browsing_data_utils.cc b/components/browsing_data/core/browsing_data_utils.cc
index 3b1579d..978da30e1 100644
--- a/components/browsing_data/core/browsing_data_utils.cc
+++ b/components/browsing_data/core/browsing_data_utils.cc
@@ -17,6 +17,7 @@
 #include "components/browsing_data/core/pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "components/strings/grit/components_strings.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/l10n/l10n_util.h"
 
 namespace browsing_data {
@@ -362,7 +363,7 @@
   return false;
 }
 
-BrowsingDataType GetDataTypeFromDeletionPreference(
+absl::optional<BrowsingDataType> GetDataTypeFromDeletionPreference(
     const std::string& pref_name) {
   using DataTypeMap = base::flat_map<std::string, BrowsingDataType>;
   static base::NoDestructor<DataTypeMap> preference_to_datatype(
@@ -381,8 +382,10 @@
       });
 
   auto iter = preference_to_datatype->find(pref_name);
-  DCHECK(iter != preference_to_datatype->end());
-  return iter->second;
+  if (iter != preference_to_datatype->end()) {
+    return iter->second;
+  }
+  return absl::nullopt;
 }
 
 bool IsHttpsCookieSourceScheme(net::CookieSourceScheme cookie_source_scheme) {
diff --git a/components/browsing_data/core/browsing_data_utils.h b/components/browsing_data/core/browsing_data_utils.h
index 28f7630..5d79675 100644
--- a/components/browsing_data/core/browsing_data_utils.h
+++ b/components/browsing_data/core/browsing_data_utils.h
@@ -12,6 +12,7 @@
 #include "components/browsing_data/core/clear_browsing_data_tab.h"
 #include "components/browsing_data/core/counters/browsing_data_counter.h"
 #include "net/cookies/cookie_constants.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace browsing_data {
 
@@ -77,7 +78,8 @@
     ClearBrowsingDataTab clear_browsing_data_tab,
     std::string* out_pref);
 
-BrowsingDataType GetDataTypeFromDeletionPreference(
+// Returns a BrowsingDataType if a type matching |pref_name| is found.
+absl::optional<BrowsingDataType> GetDataTypeFromDeletionPreference(
     const std::string& pref_name);
 
 bool IsHttpsCookieSourceScheme(net::CookieSourceScheme cookie_source_scheme);
diff --git a/components/creator/creator_api_impl.cc b/components/creator/creator_api_impl.cc
index e5e8248..f188685c 100644
--- a/components/creator/creator_api_impl.cc
+++ b/components/creator/creator_api_impl.cc
@@ -14,4 +14,12 @@
   // TODO(crbug.com/1365645) query actual data for given channel id.
   return Creator{u"alexainsley.com", /*title=*/u"Alex Ainsley"};
 }
+
+void CreatorApiImpl::GetWebId(std::string url,
+                              base::OnceCallback<void(std::string)> callback) {
+  if (url.empty()) {
+    std::move(callback).Run({});
+    return;
+  }
+}
 }  // namespace creator
\ No newline at end of file
diff --git a/components/creator/creator_api_impl.h b/components/creator/creator_api_impl.h
index abea965..6e7b58c 100644
--- a/components/creator/creator_api_impl.h
+++ b/components/creator/creator_api_impl.h
@@ -15,8 +15,10 @@
   CreatorApiImpl(const CreatorApiImpl&) = delete;
   CreatorApiImpl& operator=(const CreatorApiImpl&) = delete;
 
-  // Creator
+  // CreatorApi
   Creator GetCreator(std::string web_channel_id);
+  void GetWebId(std::string url,
+                base::OnceCallback<void(std::string)> callback);
 };
 
 }  // namespace creator
diff --git a/components/creator/public/creator_api.h b/components/creator/public/creator_api.h
index a0df6e3..32d0d67c 100644
--- a/components/creator/public/creator_api.h
+++ b/components/creator/public/creator_api.h
@@ -7,6 +7,8 @@
 
 #include <string>
 
+#include "base/callback.h"
+
 namespace creator {
 
 struct Creator {
@@ -23,6 +25,8 @@
   CreatorApi& operator=(const CreatorApi&) = delete;
 
   Creator GetCreator(std::string web_channel_id);
+  void GetWebId(std::string url,
+                base::OnceCallback<void(std::string)> callback);
 };
 
 }  // namespace creator
diff --git a/components/exo/wayland/clients/client_base.cc b/components/exo/wayland/clients/client_base.cc
index 3e4c5722..b423491 100644
--- a/components/exo/wayland/clients/client_base.cc
+++ b/components/exo/wayland/clients/client_base.cc
@@ -478,8 +478,9 @@
     ui::OzonePlatform::InitParams ozone_params;
     ozone_params.single_process = true;
     ui::OzonePlatform::InitializeForGPU(ozone_params);
-    gl::GLDisplayEGL* display = static_cast<gl::GLDisplayEGL*>(
-        gl::init::InitializeGLOneOff(/*system_device_id=*/0));
+    gl::GLDisplayEGL* display =
+        static_cast<gl::GLDisplayEGL*>(gl::init::InitializeGLOneOff(
+            /*gpu_preference=*/gl::GpuPreference::kDefault));
     DCHECK(display);
     gl_surface_ = gl::init::CreateOffscreenGLSurface(display, gfx::Size());
     gl_context_ =
diff --git a/components/global_media_controls/BUILD.gn b/components/global_media_controls/BUILD.gn
index 83c7b6e9..61f131b0 100644
--- a/components/global_media_controls/BUILD.gn
+++ b/components/global_media_controls/BUILD.gn
@@ -28,6 +28,7 @@
     "//components/strings:components_strings_grit",
     "//components/vector_icons",
     "//media",
+    "//media/remoting:remoting_constants",
     "//skia",
     "//ui/color",
     "//ui/message_center/public/cpp",
diff --git a/components/global_media_controls/public/media_session_notification_item.cc b/components/global_media_controls/public/media_session_notification_item.cc
index 42c227ca..88f4158 100644
--- a/components/global_media_controls/public/media_session_notification_item.cc
+++ b/components/global_media_controls/public/media_session_notification_item.cc
@@ -15,6 +15,7 @@
 #include "components/url_formatter/url_formatter.h"
 #include "components/vector_icons/vector_icons.h"
 #include "media/base/media_switches.h"
+#include "media/remoting/remoting_constants.h"
 #include "services/media_session/public/cpp/util.h"
 #include "services/media_session/public/mojom/media_controller.mojom.h"
 #include "services/media_session/public/mojom/media_session.mojom.h"
@@ -282,11 +283,20 @@
 }
 
 media_session::mojom::RemotePlaybackMetadataPtr
-MediaSessionNotificationItem::GetRemotePlaybackMetadata() {
+MediaSessionNotificationItem::GetRemotePlaybackMetadata() const {
+  // Return nullptr if Remote Playback is disabled.
   if (!session_info_ || !session_info_->remote_playback_metadata ||
       session_info_->remote_playback_metadata->remote_playback_disabled) {
     return nullptr;
   }
+
+  // Return nullptr if the media is too short.
+  if (session_position_.has_value() &&
+      session_position_.value().duration() <=
+          base::Seconds(media::remoting::kMinRemotingMediaDurationInSec)) {
+    return nullptr;
+  }
+
   return session_info_->remote_playback_metadata.Clone();
 }
 
diff --git a/components/global_media_controls/public/media_session_notification_item.h b/components/global_media_controls/public/media_session_notification_item.h
index c1a81366..ee21a54 100644
--- a/components/global_media_controls/public/media_session_notification_item.h
+++ b/components/global_media_controls/public/media_session_notification_item.h
@@ -129,8 +129,10 @@
 
   bool frozen() const { return frozen_; }
 
-  // Returns nullptr if `remote_playback_disabled` is true in `session_info_`.
-  media_session::mojom::RemotePlaybackMetadataPtr GetRemotePlaybackMetadata();
+  // Returns nullptr if `remote_playback_disabled` is true in `session_info_` or
+  // the media duration is too short.
+  media_session::mojom::RemotePlaybackMetadataPtr GetRemotePlaybackMetadata()
+      const;
 
   void FlushForTesting();
 
diff --git a/components/headless/command_handler/headless_command.js b/components/headless/command_handler/headless_command.js
index 8599ea9..f959ff8 100644
--- a/components/headless/command_handler/headless_command.js
+++ b/components/headless/command_handler/headless_command.js
@@ -202,6 +202,11 @@
     return this._session;
   }
 
+  async close() {
+    const dp = this._session.protocol();
+    dp.Target.closeTarget({targetId: this._targetId});
+  }
+
   async _navigate(url) {
     const dp = this._session.protocol();
     await dp.Page.enable();
@@ -312,5 +317,9 @@
     await Promise.race(promises);
   }
 
-  return await handleCommands(dp, commands);
+  const result = await handleCommands(dp, commands);
+
+  await targetPage.close();
+
+  return result;
 }
diff --git a/components/headless/command_handler/headless_command_handler.cc b/components/headless/command_handler/headless_command_handler.cc
index 21bc927..210677f 100644
--- a/components/headless/command_handler/headless_command_handler.cc
+++ b/components/headless/command_handler/headless_command_handler.cc
@@ -51,23 +51,36 @@
 const char kHeadlessCommandHtml[] = "headless_command.html";
 const char kHeadlessCommandJs[] = "headless_command.js";
 
-content::WebUIDataSource* CreateHeadlessHostDataSource() {
+void EnsureHeadlessCommandResources() {
+  // Check if our resources are already loaded and bail out early. This happens
+  // when running Chrome with --headless switch and headless command resources
+  // have been merged into the Chrome's resource pack.
+  ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+  if (!bundle.GetRawDataResource(IDR_HEADLESS_COMMAND_HTML).empty()) {
+    DCHECK(!bundle.GetRawDataResource(IDR_HEADLESS_COMMAND_JS).empty());
+    return;
+  }
+
+  // Check if we have headless command resource pack next to our binary and load
+  // it if so. Note that this code is expected to run early during the browser
+  // startup phase when file system access is still allowed.
   base::FilePath resource_dir;
   bool result = base::PathService::Get(base::DIR_ASSETS, &resource_dir);
   DCHECK(result);
 
-  // Try loading the headless library pak file first. If it doesn't exist (i.e.,
-  // when we're running with the --headless switch), fall back to the browser's
-  // resource pak.
   base::FilePath resource_pack =
       resource_dir.Append(FILE_PATH_LITERAL("headless_command_resources.pak"));
   if (base::PathExists(resource_pack)) {
-    ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(
-        resource_pack, ui::kScaleFactorNone);
+    bundle.AddDataPackFromPath(resource_pack, ui::kScaleFactorNone);
   }
+}
+
+content::WebUIDataSource* CreateHeadlessHostDataSource() {
+  EnsureHeadlessCommandResources();
 
   content::WebUIDataSource* source =
       content::WebUIDataSource::Create(kChromeHeadlessHost);
+  DCHECK(source);
 
   source->AddResourcePath(kHeadlessCommandHtml, IDR_HEADLESS_COMMAND_HTML);
   source->AddResourcePath(kHeadlessCommandJs, IDR_HEADLESS_COMMAND_JS);
@@ -232,6 +245,7 @@
       target_url_(std::move(target_url)),
       done_callback_(std::move(done_callback)),
       io_task_runner_(std::move(io_task_runner)) {
+  DCHECK(web_contents_);
   DCHECK(io_task_runner_);
 
   // Load command execution harness resources and create URL data source
diff --git a/components/heap_profiling/multi_process/BUILD.gn b/components/heap_profiling/multi_process/BUILD.gn
index 965853df..f0daff9 100644
--- a/components/heap_profiling/multi_process/BUILD.gn
+++ b/components/heap_profiling/multi_process/BUILD.gn
@@ -33,8 +33,12 @@
   # shim to function correctly.
   android_library("heap_profiling_java_test_support") {
     testonly = true
+    annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
     sources = [ "javatests/src/org/chromium/components/heap_profiling/multi_process/HeapProfilingTestShim.java" ]
-    deps = [ "//build/android:build_java" ]
+    deps = [
+      "//base:jni_java",
+      "//build/android:build_java",
+    ]
   }
 }
 
diff --git a/components/heap_profiling/multi_process/heap_profiling_test_shim.cc b/components/heap_profiling/multi_process/heap_profiling_test_shim.cc
index 186909a..e871ccd 100644
--- a/components/heap_profiling/multi_process/heap_profiling_test_shim.cc
+++ b/components/heap_profiling/multi_process/heap_profiling_test_shim.cc
@@ -21,14 +21,12 @@
 HeapProfilingTestShim::HeapProfilingTestShim(JNIEnv* env, jobject obj) {}
 HeapProfilingTestShim::~HeapProfilingTestShim() = default;
 
-void HeapProfilingTestShim::Destroy(JNIEnv* env,
-                                    const JavaParamRef<jobject>& obj) {
+void HeapProfilingTestShim::Destroy(JNIEnv* env) {
   delete this;
 }
 
 jboolean HeapProfilingTestShim::RunTestForMode(
     JNIEnv* env,
-    const base::android::JavaParamRef<jobject>& obj,
     const base::android::JavaParamRef<jstring>& mode,
     jboolean dynamically_start_profiling,
     const base::android::JavaParamRef<jstring>& stack_mode,
diff --git a/components/heap_profiling/multi_process/heap_profiling_test_shim.h b/components/heap_profiling/multi_process/heap_profiling_test_shim.h
index a2f086b..4378d77 100644
--- a/components/heap_profiling/multi_process/heap_profiling_test_shim.h
+++ b/components/heap_profiling/multi_process/heap_profiling_test_shim.h
@@ -14,14 +14,13 @@
 class HeapProfilingTestShim {
  public:
   HeapProfilingTestShim(JNIEnv* env, jobject obj);
-  void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void Destroy(JNIEnv* env);
 
   HeapProfilingTestShim(const HeapProfilingTestShim&) = delete;
   HeapProfilingTestShim& operator=(const HeapProfilingTestShim&) = delete;
 
   jboolean RunTestForMode(
       JNIEnv* env,
-      const base::android::JavaParamRef<jobject>& obj,
       const base::android::JavaParamRef<jstring>& mode,
       jboolean dynamically_start_profiling,
       const base::android::JavaParamRef<jstring>& stack_mode,
diff --git a/components/heap_profiling/multi_process/javatests/src/org/chromium/components/heap_profiling/multi_process/HeapProfilingTestShim.java b/components/heap_profiling/multi_process/javatests/src/org/chromium/components/heap_profiling/multi_process/HeapProfilingTestShim.java
index bd06dc1..9d08e941 100644
--- a/components/heap_profiling/multi_process/javatests/src/org/chromium/components/heap_profiling/multi_process/HeapProfilingTestShim.java
+++ b/components/heap_profiling/multi_process/javatests/src/org/chromium/components/heap_profiling/multi_process/HeapProfilingTestShim.java
@@ -4,6 +4,7 @@
 
 package org.chromium.components.heap_profiling.multi_process;
 
+import org.chromium.base.annotations.NativeMethods;
 import org.chromium.build.annotations.MainDex;
 
 /**
@@ -13,7 +14,7 @@
 @MainDex
 public class HeapProfilingTestShim {
     public HeapProfilingTestShim() {
-        mNativeHeapProfilingTestShim = nativeInit();
+        mNativeHeapProfilingTestShim = HeapProfilingTestShimJni.get().init(this);
     }
 
     /**
@@ -24,8 +25,8 @@
      */
     public boolean runTestForMode(String mode, boolean dynamicallyStartProfiling, String stackMode,
             boolean shouldSample, boolean sampleEverything) {
-        return nativeRunTestForMode(mNativeHeapProfilingTestShim, mode, dynamicallyStartProfiling,
-                stackMode, shouldSample, sampleEverything);
+        return HeapProfilingTestShimJni.get().runTestForMode(mNativeHeapProfilingTestShim, mode,
+                dynamicallyStartProfiling, stackMode, shouldSample, sampleEverything);
     }
 
     /**
@@ -34,15 +35,19 @@
      */
     public void destroy() {
         if (mNativeHeapProfilingTestShim != 0) {
-            nativeDestroy(mNativeHeapProfilingTestShim);
+            HeapProfilingTestShimJni.get().destroy(mNativeHeapProfilingTestShim);
             mNativeHeapProfilingTestShim = 0;
         }
     }
 
     private long mNativeHeapProfilingTestShim;
-    private native long nativeInit();
-    private native void nativeDestroy(long nativeHeapProfilingTestShim);
-    private native boolean nativeRunTestForMode(long nativeHeapProfilingTestShim, String mode,
-            boolean dynamicallyStartProfiling, String stackMode, boolean shouldSample,
-            boolean sampleEverything);
+
+    @NativeMethods
+    interface Natives {
+        long init(HeapProfilingTestShim obj);
+        void destroy(long nativeHeapProfilingTestShim);
+        boolean runTestForMode(long nativeHeapProfilingTestShim, String mode,
+                boolean dynamicallyStartProfiling, String stackMode, boolean shouldSample,
+                boolean sampleEverything);
+    }
 }
diff --git a/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc b/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc
index b56d5b3..efc2dd3 100644
--- a/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc
+++ b/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc
@@ -267,6 +267,7 @@
           WebFeature::kWebNfcNdefReaderScan,
           WebFeature::kWakeLockAcquireScreenLockWithoutActivation,
           WebFeature::kGetDisplayMediaWithoutUserActivation,
+          WebFeature::kDataUrlInSvgUse,
       }));
   return *opt_in_features;
 }
diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc
index ea3c532..ef8b65b 100644
--- a/components/password_manager/core/common/password_manager_features.cc
+++ b/components/password_manager/core/common/password_manager_features.cc
@@ -101,6 +101,12 @@
 BASE_FEATURE(kIOSPasswordCheckup,
              "IOSPasswordCheckup",
              base::FEATURE_DISABLED_BY_DEFAULT);
+
+// Feature flag to show local/account storage in save/update password infobar
+// subtitle.
+BASE_FEATURE(kIOSShowPasswordStorageInSaveInfobar,
+             "ShowPasswordStorageInSaveInfobar",
+             base::FEATURE_DISABLED_BY_DEFAULT);
 #endif  // IS_IOS
 
 // Enables (un)muting compromised passwords from bulk leak check in settings.
diff --git a/components/password_manager/core/common/password_manager_features.h b/components/password_manager/core/common/password_manager_features.h
index a4d57fb14..f018ebe0 100644
--- a/components/password_manager/core/common/password_manager_features.h
+++ b/components/password_manager/core/common/password_manager_features.h
@@ -43,6 +43,7 @@
 BASE_DECLARE_FEATURE(kIOSPasswordUISplit);
 BASE_DECLARE_FEATURE(kIOSPasswordManagerCrossOriginIframeSupport);
 BASE_DECLARE_FEATURE(kIOSPasswordCheckup);
+BASE_DECLARE_FEATURE(kIOSShowPasswordStorageInSaveInfobar);
 #endif  // IS_IOS
 BASE_DECLARE_FEATURE(kMuteCompromisedPasswords);
 BASE_DECLARE_FEATURE(kNewRegexForOtpFields);
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/BruschettaVMConfiguration.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/BruschettaVMConfiguration.yaml
index 36c4a53..16d84958 100644
--- a/components/policy/resources/templates/policy_definitions/Miscellaneous/BruschettaVMConfiguration.yaml
+++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/BruschettaVMConfiguration.yaml
@@ -56,36 +56,30 @@
           - INSTALL_ALLOWED
         installer_image_x86_64:
           type: object
-          description: The UEFI-bootable disk image used to install the VM on x86_64 devices
+          description: The UEFI-bootable disk image used to install the VM on x86_64 devices.
           required:
           - url
           - hash
           properties:
             url:
               type: string
-              description: URL of the compressed object to download. Objects may
-               be compressed using gzip, bzip2, lzma, or zstd, which will be
-               automatically detected after downloading. Objects may not be
-               uncompressed, as this cannot be autodetected.
+              description: URL of the disk image to download.
             hash:
               type: string
-              description: Hexadecimal encoded SHA-256 hash of the compressed object
+              description: Hexadecimal encoded SHA-256 hash of the disk image.
         uefi_pflash_x86_64:
           type: object
-          description: The initial non-volatile UEFI data used by the VM firmware
+          description: The initial non-volatile UEFI data used by the VM firmware.
           required:
           - url
           - hash
           properties:
             url:
               type: string
-              description: URL of the compressed object to download. Objects may
-               be compressed using gzip, bzip2, lzma, or zstd, which will be
-               automatically detected after downloading. Objects may not be
-               uncompressed, as this cannot be autodetected.
+              description: URL of the data to download.
             hash:
               type: string
-              description: Hexadecimal encoded SHA-256 hash of the compressed object
+              description: Hexadecimal encoded SHA-256 hash of the data.
         uefi_image_x86_64:
           type: object
           description: The UEFI firmware image used by the VM. This exists as a
@@ -96,13 +90,10 @@
           properties:
             url:
               type: string
-              description: URL of the compressed object to download. Objects may
-               be compressed using gzip, bzip2, lzma, or zstd, which will be
-               automatically detected after downloading. Objects may not be
-               uncompressed, as this cannot be autodetected.
+              description: URL of the firmware image to download.
             hash:
               type: string
-              description: Hexadecimal encoded SHA-256 hash of the compressed object
+              description: Hexadecimal encoded SHA-256 hash of the firmware image.
         vtpm:
           type: object
           description: Controls if VMs using this configuration have
@@ -115,12 +106,12 @@
             enabled:
               type: boolean
               description: Controls whether VMs using this configuration have
-               access to a vTPM, defaults to false
+               access to a vTPM, defaults to false.
             policy_update_action:
               type: string
               description: Controls how to treat running VMs that don't match
                this policy setting, defaults to
-               <ph name="FORCE_SHUTDOWN_IF_MORE_RESTRICTED">FORCE_SHUTDOWN_IF_MORE_RESTRICTED</ph>
+               <ph name="FORCE_SHUTDOWN_IF_MORE_RESTRICTED">FORCE_SHUTDOWN_IF_MORE_RESTRICTED</ph>.
               enum:
               - NONE
               - FORCE_SHUTDOWN_IF_MORE_RESTRICTED
diff --git a/components/services/app_service/public/cpp/BUILD.gn b/components/services/app_service/public/cpp/BUILD.gn
index f24af65..d4a1595 100644
--- a/components/services/app_service/public/cpp/BUILD.gn
+++ b/components/services/app_service/public/cpp/BUILD.gn
@@ -76,6 +76,9 @@
   deps = [
     ":icon_types",
     ":run_on_os_login",
+    "//ui/gfx:gfx",
+    "//ui/gfx/geometry:geometry",
+    "//url:url",
   ]
 }
 
@@ -170,6 +173,7 @@
   deps = [
     ":app_types",
     ":icon_types",
+    "//ui/gfx:gfx",
   ]
 }
 
@@ -179,7 +183,11 @@
     "stub_icon_loader.h",
   ]
 
-  deps = [ ":icon_loader" ]
+  deps = [
+    ":icon_loader",
+    "//skia",
+    "//ui/gfx:gfx",
+  ]
 }
 
 component("icon_types") {
diff --git a/components/services/app_service/public/cpp/preferred_apps_impl.cc b/components/services/app_service/public/cpp/preferred_apps_impl.cc
index e1da7337..5ef6dee 100644
--- a/components/services/app_service/public/cpp/preferred_apps_impl.cc
+++ b/components/services/app_service/public/cpp/preferred_apps_impl.cc
@@ -12,6 +12,7 @@
 #include "base/files/file_util.h"
 #include "base/functional/bind.h"
 #include "base/json/json_string_value_serializer.h"
+#include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/ranges/algorithm.h"
diff --git a/components/services/app_service/public/cpp/run_on_os_login_types.cc b/components/services/app_service/public/cpp/run_on_os_login_types.cc
index 060362c..359a039 100644
--- a/components/services/app_service/public/cpp/run_on_os_login_types.cc
+++ b/components/services/app_service/public/cpp/run_on_os_login_types.cc
@@ -23,26 +23,4 @@
   return !(*this == other);
 }
 
-apps::mojom::RunOnOsLoginPtr ConvertRunOnOsLoginToMojomRunOnOsLogin(
-    const RunOnOsLogin& run_on_os_login) {
-  auto run_on_os_login_mojom = apps::mojom::RunOnOsLogin::New();
-  run_on_os_login_mojom->login_mode =
-      ConvertRunOnOsLoginModeToMojomRunOnOsLoginMode(
-          run_on_os_login.login_mode);
-  run_on_os_login_mojom->is_managed = run_on_os_login.is_managed;
-  return run_on_os_login_mojom;
-}
-
-apps::mojom::RunOnOsLoginMode ConvertRunOnOsLoginModeToMojomRunOnOsLoginMode(
-    RunOnOsLoginMode login_mode) {
-  switch (login_mode) {
-    case RunOnOsLoginMode::kUnknown:
-      return apps::mojom::RunOnOsLoginMode::kUnknown;
-    case RunOnOsLoginMode::kNotRun:
-      return apps::mojom::RunOnOsLoginMode::kNotRun;
-    case RunOnOsLoginMode::kWindowed:
-      return apps::mojom::RunOnOsLoginMode::kWindowed;
-  }
-}
-
 }  // namespace apps
\ No newline at end of file
diff --git a/components/services/app_service/public/cpp/run_on_os_login_types.h b/components/services/app_service/public/cpp/run_on_os_login_types.h
index 58b66803..a9d20af 100644
--- a/components/services/app_service/public/cpp/run_on_os_login_types.h
+++ b/components/services/app_service/public/cpp/run_on_os_login_types.h
@@ -5,12 +5,12 @@
 #ifndef COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_RUN_ON_OS_LOGIN_TYPES_H_
 #define COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_RUN_ON_OS_LOGIN_TYPES_H_
 
+#include <memory>
 #include <utility>
 #include <vector>
 
 #include "base/component_export.h"
 #include "components/services/app_service/public/cpp/macros.h"
-#include "components/services/app_service/public/mojom/types.mojom.h"
 
 namespace apps {
 
@@ -48,14 +48,6 @@
 
 using RunOnOsLoginPtr = std::unique_ptr<RunOnOsLogin>;
 
-COMPONENT_EXPORT(LOGIN_MODE)
-apps::mojom::RunOnOsLoginPtr ConvertRunOnOsLoginToMojomRunOnOsLogin(
-    const RunOnOsLogin& run_on_os_login);
-
-COMPONENT_EXPORT(LOGIN_MODE)
-apps::mojom::RunOnOsLoginMode ConvertRunOnOsLoginModeToMojomRunOnOsLoginMode(
-    RunOnOsLoginMode login_mode);
-
 }  // namespace apps
 
 #endif  // COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_RUN_ON_OS_LOGIN_TYPES_H_
\ No newline at end of file
diff --git a/components/services/app_service/public/mojom/BUILD.gn b/components/services/app_service/public/mojom/BUILD.gn
index e22492c..530dfea0 100644
--- a/components/services/app_service/public/mojom/BUILD.gn
+++ b/components/services/app_service/public/mojom/BUILD.gn
@@ -4,24 +4,7 @@
 
 import("//mojo/public/tools/bindings/mojom.gni")
 
-mojom("types") {
-  sources = [ "types.mojom" ]
-  webui_module_path = "/"
-
-  public_deps = [
-    "//mojo/public/mojom/base",
-    "//skia/public/mojom",
-    "//ui/gfx/geometry/mojom",
-    "//ui/gfx/image/mojom",
-    "//ui/gfx/mojom",
-    "//ui/gfx/range/mojom",
-    "//url/mojom:url_mojom_gurl",
-  ]
-}
-
 mojom("mojom") {
   sources = [ "app_service.mojom" ]
   webui_module_path = "/"
-
-  public_deps = [ ":types" ]
 }
diff --git a/components/services/app_service/public/mojom/app_service.mojom b/components/services/app_service/public/mojom/app_service.mojom
index d11894f..7af5e9e 100644
--- a/components/services/app_service/public/mojom/app_service.mojom
+++ b/components/services/app_service/public/mojom/app_service.mojom
@@ -3,5 +3,3 @@
 // found in the LICENSE file.
 
 module apps.mojom;
-
-import "components/services/app_service/public/mojom/types.mojom";
diff --git a/components/services/app_service/public/mojom/types.mojom b/components/services/app_service/public/mojom/types.mojom
deleted file mode 100644
index 023efea..0000000
--- a/components/services/app_service/public/mojom/types.mojom
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2018 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module apps.mojom;
-
-import "mojo/public/mojom/base/safe_base_name.mojom";
-
-// The RunOnOsLoginModes must be kept in sync
-// with RunOnOsLoginMode in
-// chrome/browser/web_applications/web_app_constants.h
-enum RunOnOsLoginMode {
-  kUnknown = 0,
-  // App won't run on OS Login.
-  kNotRun,
-  // App will run in windowed mode on OS Login.
-  kWindowed,
-};
-
-// RunOnOsLoginMode struct to be used
-// to verify if the mode is set by policy
-// or not.
-struct RunOnOsLogin {
-  RunOnOsLoginMode login_mode;
-  // If the run on os login mode is policy
-  // controlled or not.
-  bool is_managed;
-};
diff --git a/components/storage_monitor/storage_info.cc b/components/storage_monitor/storage_info.cc
index 4cfb66e..68ce49c 100644
--- a/components/storage_monitor/storage_info.cc
+++ b/components/storage_monitor/storage_info.cc
@@ -110,17 +110,8 @@
   } else if (prefix == kMacImageCapturePrefix) {
     found_type = MAC_IMAGE_CAPTURE;
   } else {
-#if DCHECK_IS_ON()
-    // Users may have legacy device IDs in their profiles.
-    static const char kLegacyIPhotoPrefix[] = "iphoto:";
-    static const char kLegacyITunesPrefix[] = "itunes:";
-    static const char kLegacyPicasaPrefix[] = "picasa:";
-    if (prefix == kLegacyIPhotoPrefix || prefix == kLegacyITunesPrefix ||
-        prefix == kLegacyPicasaPrefix) {
-      return false;
-    }
-#endif
-    NOTREACHED();
+    // Users may have legacy device IDs in their profiles, like iPhoto, iTunes,
+    // or Picasa. Just reject them as invalid devices here.
     return false;
   }
   if (type)
diff --git a/components/variations/cros/BUILD.gn b/components/variations/cros/BUILD.gn
new file mode 100644
index 0000000..ba3479e
--- /dev/null
+++ b/components/variations/cros/BUILD.gn
@@ -0,0 +1,50 @@
+# 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.
+import("//testing/test.gni")
+
+executable("evaluate_seed") {
+  sources = [ "evaluate_seed_main.cc" ]
+  deps = [
+    ":evaluate_seed_lib",
+    "//base",
+  ]
+  assert_no_deps = [ "//chrome " ]
+}
+
+source_set("evaluate_seed_lib") {
+  sources = [
+    "evaluate_seed.cc",
+    "evaluate_seed.h",
+  ]
+  deps = [
+    "//base",
+    "//components/variations",
+    "//components/variations/proto",
+  ]
+
+  # restrict to only other targets in this BUILD.gn file.
+  visibility = [ ":*" ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [ "evaluate_seed_unittest.cc" ]
+  deps = [
+    ":evaluate_seed_lib",
+    "//base",
+    "//base/test:test_support",
+    "//components/test:test_support",
+    "//components/variations",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+}
+
+test("variations_cros_unittests") {
+  sources = [ "//components/test/run_all_unittests.cc" ]
+  deps = [
+    ":unit_tests",
+    "//components/test:test_support",
+  ]
+}
diff --git a/components/variations/cros/OWNERS b/components/variations/cros/OWNERS
new file mode 100644
index 0000000..14beb4f
--- /dev/null
+++ b/components/variations/cros/OWNERS
@@ -0,0 +1,4 @@
+mutexlox@chromium.org
+
+# Backup
+iby@chromium.org
diff --git a/components/variations/cros/README.md b/components/variations/cros/README.md
new file mode 100644
index 0000000..dab1fb4c
--- /dev/null
+++ b/components/variations/cros/README.md
@@ -0,0 +1,16 @@
+# `evaluate_seed`
+
+The executable `evaluate_seed` is a minimal program (budget: 1MiB of disk space
+for the executable itself) used early in ChromeOS boot to determine which group
+each early-boot experiment should be in, as well as any parameters for the
+binary. It lives here so that it is trivial to keep the code in sync between
+ChromeOS's platform layer and chrome.
+
+It will be executed primarily by `featured`, which lives in
+`//platform2/featured/`.
+
+`featured` will set command-line parameters as appropriate (e.g. to determine
+enterprise enrollment state and whether to use a safe seed), and will feed a
+safe seed (if necessary) via stdin.
+
+`evaluate_seed` will write a serialized version of the computed state to stdout.
diff --git a/components/variations/cros/evaluate_seed.cc b/components/variations/cros/evaluate_seed.cc
new file mode 100644
index 0000000..2d6af85
--- /dev/null
+++ b/components/variations/cros/evaluate_seed.cc
@@ -0,0 +1,56 @@
+// 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 "components/variations/cros/evaluate_seed.h"
+
+#include "base/check.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+
+namespace variations::evaluate_seed {
+
+namespace {
+constexpr char kSafeSeedSwitch[] = "use-safe-seed";
+constexpr char kEnterpriseEnrolledSwitch[] = "enterprise-enrolled";
+}  // namespace
+
+ClientFilterableState GetClientFilterableState(
+    const base::CommandLine* command_line) {
+  bool enterprise_enrolled = command_line->HasSwitch(kEnterpriseEnrolledSwitch);
+
+  // TODO(b/263975722): Fill in the rest of ClientFilterableState.
+  return ClientFilterableState(base::BindOnce(
+      [](bool enrolled) { return enrolled; }, enterprise_enrolled));
+}
+
+absl::optional<SafeSeed> GetSafeSeedData(const base::CommandLine* command_line,
+                                         FILE* stream) {
+  if (command_line->HasSwitch(kSafeSeedSwitch)) {
+    // Read safe seed from |stream|.
+    std::string safe_seed_data;
+    if (!base::ReadStreamToString(stream, &safe_seed_data)) {
+      PLOG(ERROR) << "Failed to read from stream:";
+      return absl::nullopt;
+    }
+    return SafeSeed{true, safe_seed_data};
+  }
+  return SafeSeed{false, ""};
+}
+
+int EvaluateSeedMain(const base::CommandLine* command_line, FILE* stream) {
+  absl::optional<SafeSeed> safe_seed = GetSafeSeedData(command_line, stream);
+  if (!safe_seed.has_value()) {
+    LOG(ERROR) << "Failed to read seed from stdin";
+    return EXIT_FAILURE;
+  }
+
+  ClientFilterableState state = GetClientFilterableState(command_line);
+
+  // TODO(b/263975722): Implement this binary.
+  (void)state;
+
+  return EXIT_SUCCESS;
+}
+
+}  // namespace variations::evaluate_seed
diff --git a/components/variations/cros/evaluate_seed.h b/components/variations/cros/evaluate_seed.h
new file mode 100644
index 0000000..d3d93b1
--- /dev/null
+++ b/components/variations/cros/evaluate_seed.h
@@ -0,0 +1,39 @@
+// 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 COMPONENTS_VARIATIONS_CROS_EVALUATE_SEED_H_
+#define COMPONENTS_VARIATIONS_CROS_EVALUATE_SEED_H_
+
+#include <string>
+
+#include <stdio.h>
+
+#include "base/command_line.h"
+#include "components/variations/client_filterable_state.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace variations::evaluate_seed {
+
+// Retrieve a ClientFilterableState struct based on the given |command_line|.
+ClientFilterableState GetClientFilterableState(
+    const base::CommandLine* command_line);
+
+struct SafeSeed {
+  bool use_safe_seed = false;
+  std::string seed_data;
+};
+
+// Read the safe seed data, but do not parse it, from |stream|, if and only if
+// the |command_line| indicates that we should use the safe seed.
+absl::optional<SafeSeed> GetSafeSeedData(const base::CommandLine* command_line,
+                                         FILE* stream);
+
+// Evaluate the seed state, writing serialized computed output to stdout.
+// Reads a proto from |stream| for data like safe seed.
+// Return values are standard for main methods (EXIT_SUCCESS / EXIT_FAILURE).
+int EvaluateSeedMain(const base::CommandLine* command_line, FILE* stream);
+
+}  // namespace variations::evaluate_seed
+
+#endif  // COMPONENTS_VARIATIONS_CROS_EVALUATE_SEED_H_
diff --git a/components/variations/cros/evaluate_seed_main.cc b/components/variations/cros/evaluate_seed_main.cc
new file mode 100644
index 0000000..cc0d473
--- /dev/null
+++ b/components/variations/cros/evaluate_seed_main.cc
@@ -0,0 +1,21 @@
+// 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 "base/at_exit.h"
+#include "base/threading/platform_thread.h"
+#include "components/variations/cros/evaluate_seed.h"
+
+// evaluate_seed reads the seed data from Local State and prints computed state,
+// in a serialized format, to stdout.
+// It does so with minimal dependencies, so that it can run *before* ash-chrome
+// starts on Chrome OS, with minimal impact to image size and boot time.
+int main(int argc, const char* argv[]) {
+  base::PlatformThread::SetName("EvaluateSeedMain");
+  base::AtExitManager exit_manager;
+
+  base::CommandLine::Init(argc, argv);
+  const base::CommandLine* command_line =
+      base::CommandLine::ForCurrentProcess();
+  return variations::evaluate_seed::EvaluateSeedMain(command_line, stdin);
+}
diff --git a/components/variations/cros/evaluate_seed_unittest.cc b/components/variations/cros/evaluate_seed_unittest.cc
new file mode 100644
index 0000000..2e22551
--- /dev/null
+++ b/components/variations/cros/evaluate_seed_unittest.cc
@@ -0,0 +1,91 @@
+// 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 "components/variations/cros/evaluate_seed.h"
+
+#include "components/variations/client_filterable_state.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace variations::evaluate_seed {
+
+TEST(VariationsCrosEvaluateSeed, GetClientFilterable_Enrolled) {
+  base::CommandLine command_line({"evaluate_seed", "--enterprise-enrolled"});
+  ClientFilterableState state = GetClientFilterableState(&command_line);
+  EXPECT_TRUE(state.IsEnterprise());
+}
+
+TEST(VariationsCrosEvaluateSeed, GetClientFilterable_NotEnrolled) {
+  base::CommandLine command_line({"evaluate_seed"});
+  ClientFilterableState state = GetClientFilterableState(&command_line);
+  EXPECT_FALSE(state.IsEnterprise());
+}
+
+// Should ignore data if flag is off.
+TEST(VariationsCrosEvaluateSeed, GetSafeSeedData_Off) {
+  std::string text("some text");
+  FILE* stream = fmemopen(text.data(), text.size(), "r");
+  ASSERT_NE(stream, nullptr);
+
+  base::CommandLine command_line({"evaluate_seed"});
+  auto data = GetSafeSeedData(&command_line, stream);
+  ASSERT_TRUE(data.has_value());
+  EXPECT_FALSE(data.value().use_safe_seed);
+  EXPECT_EQ(data.value().seed_data, "");
+}
+
+// Should return specified data via stream if flag is on.
+TEST(VariationsCrosEvaluateSeed, GetSafeSeedData_On) {
+  std::string text("some text");
+  FILE* stream = fmemopen(text.data(), text.size(), "r");
+  ASSERT_NE(stream, nullptr);
+
+  base::CommandLine command_line({"evaluate_seed", "--use-safe-seed"});
+  auto data = GetSafeSeedData(&command_line, stream);
+  ASSERT_TRUE(data.has_value());
+  EXPECT_TRUE(data.value().use_safe_seed);
+  EXPECT_EQ(data.value().seed_data, text);
+}
+
+// Should not attempt to read stream if flag is not on.
+TEST(VariationsCrosEvaluateSeed, GetSafeSeedData_Off_FailRead) {
+  std::string text("some text");
+  FILE* stream = fmemopen(text.data(), text.size(), "w");
+  ASSERT_NE(stream, nullptr);
+
+  base::CommandLine command_line({"evaluate_seed"});
+  auto data = GetSafeSeedData(&command_line, stream);
+  ASSERT_TRUE(data.has_value());
+  EXPECT_FALSE(data.value().use_safe_seed);
+  EXPECT_EQ(data.value().seed_data, "");
+}
+
+// If flag is on and reading fails, should return nullopt.
+TEST(VariationsCrosEvaluateSeed, GetSafeSeedData_On_FailRead) {
+  std::string text("some text");
+  FILE* stream = fmemopen(text.data(), text.size(), "w");
+  ASSERT_NE(stream, nullptr);
+
+  base::CommandLine command_line({"evaluate_seed", "--use-safe-seed"});
+  auto data = GetSafeSeedData(&command_line, stream);
+  EXPECT_FALSE(data.has_value());
+}
+
+// If flag is on and reading fails, should return nullopt.
+TEST(VariationsCrosEvaluateSeed, GetSafeSeedData_On_FailRead_Null) {
+  base::CommandLine command_line({"evaluate_seed", "--use-safe-seed"});
+  auto data = GetSafeSeedData(&command_line, nullptr);
+  EXPECT_FALSE(data.has_value());
+}
+
+TEST(VariationsCrosEvaluateSeed, Main_NoFlag) {
+  base::CommandLine command_line({"evaluate_seed"});
+  EXPECT_EQ(0, EvaluateSeedMain(&command_line, nullptr));
+}
+
+TEST(VariationsCrosEvaluateSeed, Main_NoStdin) {
+  base::CommandLine command_line({"evaluate_seed", "--use-safe-seed"});
+  EXPECT_EQ(1, EvaluateSeedMain(&command_line, nullptr));
+}
+
+}  // namespace variations::evaluate_seed
diff --git a/components/variations/net/variations_http_headers.cc b/components/variations/net/variations_http_headers.cc
index a7f46ec..65411d0d 100644
--- a/components/variations/net/variations_http_headers.cc
+++ b/components/variations/net/variations_http_headers.cc
@@ -206,24 +206,17 @@
   return false;
 }
 
-// Returns GoogleWebVisibility::FIRST_PARTY if kRestrictGoogleWebVisibility is
-// enabled and the request is from a first-party context; otherwise, returns
-// GoogleWebVisibility::ANY.
+// Returns GoogleWebVisibility::FIRST_PARTY if the request is from a first-party
+// context; otherwise, returns GoogleWebVisibility::ANY.
 variations::mojom::GoogleWebVisibility GetVisibilityKey(
     Owner owner,
     const network::ResourceRequest& resource_request) {
-  bool use_first_party_visibility =
-      IsFirstPartyContext(owner, resource_request) &&
-      base::FeatureList::IsEnabled(internal::kRestrictGoogleWebVisibility);
-
-  return use_first_party_visibility
+  return IsFirstPartyContext(owner, resource_request)
              ? variations::mojom::GoogleWebVisibility::FIRST_PARTY
              : variations::mojom::GoogleWebVisibility::ANY;
 }
 
-// Returns a variations header from |variations_headers|. When
-// kRestrictGoogleWebVisibility is enabled, the request context is considered
-// and may be used to select a header with a more limited set of IDs.
+// Returns a variations header from |variations_headers|.
 std::string SelectVariationsHeader(
     variations::mojom::VariationsHeadersPtr variations_headers,
     Owner owner,
@@ -285,9 +278,6 @@
 
  private:
   // Returns a variations header containing IDs appropriate for |signed_in|.
-  // When kRestrictGoogleWebVisibility is enabled, the request context is
-  // considered and may be used to select a header with a more limited set of
-  // IDs.
   //
   // Can be used only by code running in the browser process, which is where
   // the populated VariationsIdsProvider exists.
diff --git a/components/variations/variations_associated_data.h b/components/variations/variations_associated_data.h
index 05b42179..b763be5 100644
--- a/components/variations/variations_associated_data.h
+++ b/components/variations/variations_associated_data.h
@@ -56,9 +56,8 @@
   // first- and third-party contexts.
   GOOGLE_WEB_PROPERTIES_ANY_CONTEXT,
   // The IDs in this collection are used by Google web properties and are
-  // transmitted via the X-Client-Data header. When kRestrictGoogleWebVisibility
-  // is enabled, these IDs are transmitted in only first-party contexts;
-  // otherwise, these IDs are transmitted in first- and third-party contexts.
+  // transmitted via the X-Client-Data header. Transmitted in only first-party
+  // contexts.
   GOOGLE_WEB_PROPERTIES_FIRST_PARTY,
   // This collection is used by Google web properties for signed in users only,
   // transmitted through the X-Client-Data header.
@@ -69,9 +68,7 @@
   GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT,
   // The IDs in this collection are used by Google web properties to trigger
   // server-side experimental behavior and are transmitted via the X-Client-Data
-  // header. When kRestrictGoogleWebVisibility is enabled, these IDs are
-  // transmitted in only first-party contexts; otherwise, these IDs are
-  // transmitted in first- and third-party contexts.
+  // header. Transmitted in only first-party contexts.
   GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY,
   // This collection is used by the Google App and is passed at the time
   // the cross-app communication is triggered.
diff --git a/components/variations/variations_features.cc b/components/variations/variations_features.cc
index b2826052..a06583f 100644
--- a/components/variations/variations_features.cc
+++ b/components/variations/variations_features.cc
@@ -8,9 +8,5 @@
 
 namespace internal {
 
-BASE_FEATURE(kRestrictGoogleWebVisibility,
-             "RestrictGoogleWebVisibility",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 }  // namespace internal
 }  // namespace variations
diff --git a/components/variations/variations_features.h b/components/variations/variations_features.h
index 2a1a80f..96d7ab3 100644
--- a/components/variations/variations_features.h
+++ b/components/variations/variations_features.h
@@ -11,12 +11,7 @@
 namespace variations {
 namespace internal {
 
-// A feature that supports more finely-grained control over the transmission of
-// VariationIDs to Google web properties by allowing some VariationIDs to not be
-// transmitted in all contexts. See IsFirstPartyContext() in
-// variations_http_headers.cc for more details.
-COMPONENT_EXPORT(VARIATIONS_FEATURES)
-BASE_DECLARE_FEATURE(kRestrictGoogleWebVisibility);
+// Add Variations Features here...
 
 }  // namespace internal
 }  // namespace variations
diff --git a/components/variations/variations_ids_provider.cc b/components/variations/variations_ids_provider.cc
index 4f0af527..af822ec 100644
--- a/components/variations/variations_ids_provider.cc
+++ b/components/variations/variations_ids_provider.cc
@@ -296,13 +296,6 @@
   if (variation_ids_cache_initialized_)
     return;
 
-  // Query the kRestrictGoogleWebVisibility feature to activate the
-  // associated field trial, if any, so that querying it in
-  // OnFieldTrialGroupFinalized() does not result in deadlock.
-  //
-  // Note: Must be done before the AddObserver() call below.
-  base::FeatureList::IsEnabled(internal::kRestrictGoogleWebVisibility);
-
   // Register for additional cache updates. This is done before initializing the
   // cache to avoid a race that could cause registered FieldTrials to be missed.
   bool success = base::FieldTrialList::AddObserver(this);
@@ -374,21 +367,15 @@
   for (const VariationIDEntry& entry : all_variation_ids_set) {
     switch (entry.second) {
       case GOOGLE_WEB_PROPERTIES_SIGNED_IN:
-        if (is_signed_in)
+        if (is_signed_in) {
           proto.add_variation_id(entry.first);
+        }
         break;
       case GOOGLE_WEB_PROPERTIES_ANY_CONTEXT:
         proto.add_variation_id(entry.first);
         break;
       case GOOGLE_WEB_PROPERTIES_FIRST_PARTY:
-        if (base::FeatureList::IsEnabled(
-                internal::kRestrictGoogleWebVisibility)) {
-          if (is_first_party_context)
-            proto.add_variation_id(entry.first);
-        } else {
-          // When the feature is not enabled, treat VariationIDs associated with
-          // GOOGLE_WEB_PROPERTIES_FIRST_PARTY in the same way as those
-          // associated with GOOGLE_WEB_PROPERTIES_ANY_CONTEXT.
+        if (is_first_party_context) {
           proto.add_variation_id(entry.first);
         }
         break;
@@ -396,14 +383,7 @@
         proto.add_trigger_variation_id(entry.first);
         break;
       case GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY:
-        if (base::FeatureList::IsEnabled(
-                internal::kRestrictGoogleWebVisibility)) {
-          if (is_first_party_context)
-            proto.add_trigger_variation_id(entry.first);
-        } else {
-          // When the feature is not enabled, treat VariationIDs associated with
-          // GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY in the same way as those
-          // associated with GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT.
+        if (is_first_party_context) {
           proto.add_trigger_variation_id(entry.first);
         }
         break;
diff --git a/components/variations/variations_ids_provider.h b/components/variations/variations_ids_provider.h
index e101df7..9ecd27f 100644
--- a/components/variations/variations_ids_provider.h
+++ b/components/variations/variations_ids_provider.h
@@ -171,11 +171,11 @@
                            ForceDisableVariationIds_ValidCommandLine);
   FRIEND_TEST_ALL_PREFIXES(VariationsIdsProviderTest,
                            ForceDisableVariationIds_Invalid);
-  FRIEND_TEST_ALL_PREFIXES(VariationsIdsProviderTestWithRestrictedVisibility,
+  FRIEND_TEST_ALL_PREFIXES(VariationsIdsProviderTest,
                            OnFieldTrialGroupFinalized);
-  FRIEND_TEST_ALL_PREFIXES(VariationsIdsProviderTestWithRestrictedVisibility,
+  FRIEND_TEST_ALL_PREFIXES(VariationsIdsProviderTest,
                            LowEntropySourceValue_Valid);
-  FRIEND_TEST_ALL_PREFIXES(VariationsIdsProviderTestWithRestrictedVisibility,
+  FRIEND_TEST_ALL_PREFIXES(VariationsIdsProviderTest,
                            LowEntropySourceValue_Null);
   FRIEND_TEST_ALL_PREFIXES(VariationsIdsProviderTest,
                            GetGoogleAppVariationsString);
diff --git a/components/variations/variations_ids_provider_unittest.cc b/components/variations/variations_ids_provider_unittest.cc
index f6ae6b92..cb7e9cbd 100644
--- a/components/variations/variations_ids_provider_unittest.cc
+++ b/components/variations/variations_ids_provider_unittest.cc
@@ -8,17 +8,13 @@
 
 #include "base/base64.h"
 #include "base/containers/contains.h"
-#include "base/feature_list.h"
-#include "base/metrics/field_trial.h"
 #include "base/run_loop.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "components/variations/entropy_provider.h"
 #include "components/variations/proto/client_variations.pb.h"
 #include "components/variations/proto/study.pb.h"
 #include "components/variations/variations.mojom.h"
 #include "components/variations/variations_associated_data.h"
-#include "components/variations/variations_features.h"
 #include "components/variations/variations_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -34,25 +30,6 @@
   base::test::SingleThreadTaskEnvironment task_environment_;
 };
 
-// Used for testing the kRestrictGoogleWebVisibility feature.
-class VariationsIdsProviderTestWithRestrictedVisibility
-    : public VariationsIdsProviderTest,
-      public ::testing::WithParamInterface<bool> {
- public:
-  VariationsIdsProviderTestWithRestrictedVisibility() {
-    if (GetParam()) {
-      scoped_feature_list_.InitAndEnableFeature(
-          internal::kRestrictGoogleWebVisibility);
-    } else {
-      scoped_feature_list_.InitAndDisableFeature(
-          internal::kRestrictGoogleWebVisibility);
-    }
-  }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
 TEST_F(VariationsIdsProviderTest, ForceVariationIds_Valid) {
   VariationsIdsProvider provider(
       VariationsIdsProvider::Mode::kUseSignedInState);
@@ -178,12 +155,7 @@
   EXPECT_TRUE(provider.GetClientDataHeaders(/*is_signed_in=*/false).is_null());
 }
 
-INSTANTIATE_TEST_SUITE_P(All,
-                         VariationsIdsProviderTestWithRestrictedVisibility,
-                         ::testing::Bool());
-
-TEST_P(VariationsIdsProviderTestWithRestrictedVisibility,
-       LowEntropySourceValue_Valid) {
+TEST_F(VariationsIdsProviderTest, LowEntropySourceValue_Valid) {
   VariationsIdsProvider provider(
       VariationsIdsProvider::Mode::kUseSignedInState);
 
@@ -215,8 +187,7 @@
   EXPECT_TRUE(base::Contains(variation_ids_any_context, 3320983));
 }
 
-TEST_P(VariationsIdsProviderTestWithRestrictedVisibility,
-       LowEntropySourceValue_Null) {
+TEST_F(VariationsIdsProviderTest, LowEntropySourceValue_Null) {
   VariationsIdsProvider provider(
       VariationsIdsProvider::Mode::kUseSignedInState);
 
@@ -261,8 +232,7 @@
   EXPECT_EQ(2U, variation_ids_any_context.size());
 }
 
-TEST_P(VariationsIdsProviderTestWithRestrictedVisibility,
-       OnFieldTrialGroupFinalized) {
+TEST_F(VariationsIdsProviderTest, OnFieldTrialGroupFinalized) {
   VariationsIdsProvider provider(
       VariationsIdsProvider::Mode::kUseSignedInState);
   provider.InitVariationIDsCacheIfNeeded();
@@ -319,25 +289,14 @@
     EXPECT_TRUE(base::Contains(trigger_ids_first_party, 33));
     EXPECT_TRUE(base::Contains(trigger_ids_first_party, 44));
 
-    if (base::FeatureList::IsEnabled(internal::kRestrictGoogleWebVisibility)) {
-      // When the feature is enabled, IDs associated with FIRST_PARTY
-      // IDCollectionKeys should be excluded from the variations header that may
-      // be sent in third-party contexts.
-      EXPECT_EQ(1U, ids_any_context.size());
-      EXPECT_TRUE(base::Contains(ids_any_context, 11));
-      EXPECT_EQ(1U, trigger_ids_any_context.size());
-      EXPECT_TRUE(base::Contains(trigger_ids_any_context, 33));
-    } else {
-      // When the feature is disabled, IDs associated with FIRST_PARTY
-      // IDCollectionKeys should be included in the variations header that may
-      // be sent in third-party contexts.
-      EXPECT_EQ(2U, ids_any_context.size());
-      EXPECT_TRUE(base::Contains(ids_any_context, 11));
-      EXPECT_TRUE(base::Contains(ids_any_context, 22));
-      EXPECT_EQ(2U, trigger_ids_any_context.size());
-      EXPECT_TRUE(base::Contains(trigger_ids_any_context, 33));
-      EXPECT_TRUE(base::Contains(trigger_ids_any_context, 44));
-    }
+    // IDs associated with FIRST_PARTY ID CollectionKeys should be excluded from
+    // the variations header that may be sent in third-party contexts.
+    EXPECT_EQ(1U, ids_any_context.size());
+    EXPECT_TRUE(base::Contains(ids_any_context, 11));
+    // Note '22' is omitted.
+    EXPECT_EQ(1U, trigger_ids_any_context.size());
+    EXPECT_TRUE(base::Contains(trigger_ids_any_context, 33));
+    // Note '44' is omitted.
   }
 
   // Now, get signed-in ids.
@@ -368,27 +327,15 @@
     EXPECT_TRUE(base::Contains(trigger_ids_first_party, 33));
     EXPECT_TRUE(base::Contains(trigger_ids_first_party, 44));
 
-    if (base::FeatureList::IsEnabled(internal::kRestrictGoogleWebVisibility)) {
-      // When the feature is enabled, IDs associated with FIRST_PARTY
-      // IDCollectionKeys should be excluded from the variations header that may
-      // be sent in third-party contexts.
-      EXPECT_EQ(2U, ids_any_context.size());
-      EXPECT_TRUE(base::Contains(ids_any_context, 11));
-      EXPECT_TRUE(base::Contains(ids_any_context, 55));
-      EXPECT_EQ(1U, trigger_ids_any_context.size());
-      EXPECT_TRUE(base::Contains(trigger_ids_any_context, 33));
-    } else {
-      // When the feature is disabled, IDs associated with FIRST_PARTY
-      // IDCollectionKeys should be included in the variations header that may
-      // be sent in third-party contexts.
-      EXPECT_EQ(3U, ids_any_context.size());
-      EXPECT_TRUE(base::Contains(ids_any_context, 11));
-      EXPECT_TRUE(base::Contains(ids_any_context, 22));
-      EXPECT_TRUE(base::Contains(ids_any_context, 55));
-      EXPECT_EQ(2U, trigger_ids_any_context.size());
-      EXPECT_TRUE(base::Contains(trigger_ids_any_context, 33));
-      EXPECT_TRUE(base::Contains(trigger_ids_any_context, 44));
-    }
+    // IDs associated with FIRST_PARTY ID CollectionKeys should be excluded from
+    // the variations header that may be sent in third-party contexts.
+    EXPECT_EQ(2U, ids_any_context.size());
+    EXPECT_TRUE(base::Contains(ids_any_context, 11));
+    // Note '22' is omitted.
+    EXPECT_TRUE(base::Contains(ids_any_context, 55));
+    EXPECT_EQ(1U, trigger_ids_any_context.size());
+    EXPECT_TRUE(base::Contains(trigger_ids_any_context, 33));
+    // Note '44' is omitted.
   }
 }
 
diff --git a/components/viz/common/resources/resource_format_utils_unittest.cc b/components/viz/common/resources/resource_format_utils_unittest.cc
index 82f45605..edce08d8 100644
--- a/components/viz/common/resources/resource_format_utils_unittest.cc
+++ b/components/viz/common/resources/resource_format_utils_unittest.cc
@@ -26,10 +26,7 @@
 
 TEST_F(ResourceFormatUtilTest, ToClosestSkColorTypeMultiPlaneYUVBiplanar8bit) {
   // 8-bit 4:2:0 Y_UV biplanar format (YUV_420_BIPLANAR)
-  SharedImageFormat format =
-      SharedImageFormat::MultiPlane(SharedImageFormat::PlaneConfig::kY_UV,
-                                    SharedImageFormat::Subsampling::k420,
-                                    SharedImageFormat::ChannelFormat::k8);
+  SharedImageFormat format = MultiPlaneFormat::kYUV_420_BIPLANAR;
   std::vector<SkColorType> expected_types = {kAlpha_8_SkColorType,
                                              kR8G8_unorm_SkColorType};
   TestToClosestSkColorType(expected_types, format, /*gpu_compositing=*/true);
@@ -37,10 +34,7 @@
 
 TEST_F(ResourceFormatUtilTest, ToClosestSkColorTypeMultiPlaneYVU) {
   // 8-bit 4:2:0 Y_V_U format (YVU_420)
-  SharedImageFormat format =
-      SharedImageFormat::MultiPlane(SharedImageFormat::PlaneConfig::kY_V_U,
-                                    SharedImageFormat::Subsampling::k420,
-                                    SharedImageFormat::ChannelFormat::k8);
+  SharedImageFormat format = MultiPlaneFormat::kYVU_420;
   std::vector<SkColorType> expected_types = {
       kAlpha_8_SkColorType, kAlpha_8_SkColorType, kAlpha_8_SkColorType};
   TestToClosestSkColorType(expected_types, format, /*gpu_compositing=*/true);
@@ -48,10 +42,7 @@
 
 TEST_F(ResourceFormatUtilTest, ToClosestSkColorTypeMultiPlaneP010) {
   // 10-bit 4:2:0 Y_UV biplanar format (P010)
-  SharedImageFormat format =
-      SharedImageFormat::MultiPlane(SharedImageFormat::PlaneConfig::kY_UV,
-                                    SharedImageFormat::Subsampling::k420,
-                                    SharedImageFormat::ChannelFormat::k10);
+  SharedImageFormat format = MultiPlaneFormat::kP010;
   std::vector<SkColorType> expected_types = {kA16_unorm_SkColorType,
                                              kR16G16_unorm_SkColorType};
   TestToClosestSkColorType(expected_types, format, /*gpu_compositing=*/true);
@@ -82,16 +73,14 @@
 
 TEST_F(ResourceFormatUtilTest, ToClosestSkColorTypeSinglePlaneRGBX) {
   // Single planar RGBX_8888
-  SharedImageFormat format =
-      SharedImageFormat::SinglePlane(ResourceFormat::RGBX_8888);
+  SharedImageFormat format = SinglePlaneFormat::kRGBX_8888;
   std::vector<SkColorType> expected_types = {kRGB_888x_SkColorType};
   TestToClosestSkColorType(expected_types, format, /*gpu_compositing=*/true);
 }
 
 TEST_F(ResourceFormatUtilTest, ToClosestSkColorTypeSinglePlaneAlpha) {
   // Single planar ALPHA_8
-  SharedImageFormat format =
-      SharedImageFormat::SinglePlane(ResourceFormat::ALPHA_8);
+  SharedImageFormat format = SinglePlaneFormat::kALPHA_8;
   std::vector<SkColorType> expected_types = {kAlpha_8_SkColorType};
   TestToClosestSkColorType(expected_types, format, /*gpu_compositing=*/true);
 }
@@ -99,8 +88,7 @@
 TEST_F(ResourceFormatUtilTest, ToClosestSkColorTypeSoftwareRGBX) {
   // Software Compositing.
   // Single planar RGBX_8888
-  SharedImageFormat format =
-      SharedImageFormat::SinglePlane(ResourceFormat::RGBX_8888);
+  SharedImageFormat format = SinglePlaneFormat::kRGBX_8888;
   std::vector<SkColorType> expected_types = {kN32_SkColorType};
   TestToClosestSkColorType(expected_types, format, /*gpu_compositing=*/false);
 }
@@ -108,10 +96,7 @@
 TEST_F(ResourceFormatUtilTest, ToClosestSkColorTypeSoftwareYUV) {
   // Software Compositing.
   // 10-bit 4:2:0 Y_UV biplanar format (P010)
-  SharedImageFormat format =
-      SharedImageFormat::MultiPlane(SharedImageFormat::PlaneConfig::kY_UV,
-                                    SharedImageFormat::Subsampling::k420,
-                                    SharedImageFormat::ChannelFormat::k10);
+  SharedImageFormat format = MultiPlaneFormat::kP010;
   std::vector<SkColorType> expected_types = {kN32_SkColorType,
                                              kN32_SkColorType};
   TestToClosestSkColorType(expected_types, format, /*gpu_compositing=*/false);
diff --git a/components/viz/common/resources/shared_image_format_unittest.cc b/components/viz/common/resources/shared_image_format_unittest.cc
index 63c6ab0b..7750e480 100644
--- a/components/viz/common/resources/shared_image_format_unittest.cc
+++ b/components/viz/common/resources/shared_image_format_unittest.cc
@@ -32,10 +32,7 @@
 
 TEST_F(SharedImageFormatTest, MultiPlaneYUVBiplanar8bit) {
   // 8-bit 4:2:0 Y_UV biplanar format (YUV_420_BIPLANAR)
-  SharedImageFormat format =
-      SharedImageFormat::MultiPlane(SharedImageFormat::PlaneConfig::kY_UV,
-                                    SharedImageFormat::Subsampling::k420,
-                                    SharedImageFormat::ChannelFormat::k8);
+  SharedImageFormat format = MultiPlaneFormat::kYUV_420_BIPLANAR;
   // Test for NumChannelsInPlane
   std::vector<int> expected_channels = {1, 2};
   TestNumChannelsInPlane(expected_channels, format);
@@ -49,10 +46,7 @@
 
 TEST_F(SharedImageFormatTest, MultiPlaneYVU) {
   // 8-bit 4:2:0 Y_V_U format (YVU_420)
-  SharedImageFormat format =
-      SharedImageFormat::MultiPlane(SharedImageFormat::PlaneConfig::kY_V_U,
-                                    SharedImageFormat::Subsampling::k420,
-                                    SharedImageFormat::ChannelFormat::k8);
+  SharedImageFormat format = MultiPlaneFormat::kYVU_420;
   // Test for NumChannelsInPlane
   std::vector<int> expected_channels = {1, 1, 1};
   TestNumChannelsInPlane(expected_channels, format);
@@ -67,10 +61,7 @@
 
 TEST_F(SharedImageFormatTest, MultiPlaneP010) {
   // 10-bit 4:2:0 Y_UV biplanar format (P010)
-  SharedImageFormat format =
-      SharedImageFormat::MultiPlane(SharedImageFormat::PlaneConfig::kY_UV,
-                                    SharedImageFormat::Subsampling::k420,
-                                    SharedImageFormat::ChannelFormat::k10);
+  SharedImageFormat format = MultiPlaneFormat::kP010;
   // Test for NumChannelsInPlane
   std::vector<int> expected_channels = {1, 2};
   TestNumChannelsInPlane(expected_channels, format);
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc
index adcd2b0f..2db4a5e 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -697,9 +697,13 @@
   nway_canvas_.emplace(characterization_.width(), characterization_.height());
   nway_canvas_->addCanvas(current_paint_->recorder()->getCanvas());
 
+  // Overdraw feedback uses |SkOverdrawCanvas|, which relies on a buffer with an
+  // 8-bit unorm alpha channel to work. RGBA8 is always supported, so we use it.
+  SkColorType color_type_with_alpha = SkColorType::kRGBA_8888_SkColorType;
+
   SkSurfaceCharacterization characterization = CreateSkSurfaceCharacterization(
       gfx::Size(characterization_.width(), characterization_.height()),
-      characterization_.colorType(), characterization_.imageInfo().alphaType(),
+      color_type_with_alpha, characterization_.imageInfo().alphaType(),
       /*mipmap=*/false, characterization_.refColorSpace(),
       /*is_root_render_pass=*/false,
       /*is_overlay=*/false);
diff --git a/content/browser/devtools/protocol/webauthn_handler.cc b/content/browser/devtools/protocol/webauthn_handler.cc
index b6e95e6..aa74604 100644
--- a/content/browser/devtools/protocol/webauthn_handler.cc
+++ b/content/browser/devtools/protocol/webauthn_handler.cc
@@ -203,6 +203,7 @@
   bool has_large_blob = options->GetHasLargeBlob(/*defaultValue=*/false);
   bool has_cred_blob = options->GetHasCredBlob(/*defaultValue=*/false);
   bool has_min_pin_length = options->GetHasMinPinLength(/*defaultValue=*/false);
+  bool has_prf = options->GetHasPrf(/*defaultValue=*/false);
   bool has_resident_key = options->GetHasResidentKey(/*defaultValue=*/false);
 
   if (has_large_blob && !has_resident_key)
@@ -236,6 +237,7 @@
       virt_auth_options->has_large_blob = has_large_blob;
       virt_auth_options->has_cred_blob = has_cred_blob;
       virt_auth_options->has_min_pin_length = has_min_pin_length;
+      virt_auth_options->has_prf = has_prf;
       break;
     case device::ProtocolVersion::kUnknown:
       NOTREACHED();
diff --git a/content/browser/indexed_db/database_impl.cc b/content/browser/indexed_db/database_impl.cc
index 0a8631b..c9b5f0d 100644
--- a/content/browser/indexed_db/database_impl.cc
+++ b/content/browser/indexed_db/database_impl.cc
@@ -738,8 +738,10 @@
 
 void DatabaseImpl::DidBecomeInactive() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  CHECK(base::FeatureList::IsEnabled(
-      blink::features::kAllowPageWithIDBTransactionInBFCache));
+  CHECK(blink::features::
+            IsAllowPageWithIDBConnectionAndTransactionInBFCacheEnabled())
+      << "This method will only be called if a page with IndexedDB transaction "
+         "is eligible for BFCache.";
   if (!connection_->IsConnected()) {
     return;
   }
diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc
index ee7fa2fe..11969416 100644
--- a/content/browser/indexed_db/indexed_db_database.cc
+++ b/content/browser/indexed_db/indexed_db_database.cc
@@ -238,13 +238,8 @@
   std::vector<PartitionedLockManager::PartitionedLockRequest> lock_requests =
       BuildLockRequestsFromTransaction(transaction);
 
-  if (base::FeatureList::IsEnabled(
-          blink::features::kAllowPageWithIDBTransactionInBFCache)) {
-    CHECK(base::FeatureList::IsEnabled(
-        blink::features::kAllowPageWithIDBConnectionInBFCache))
-        << "kAllowPageWithIDBTransactionInBFCache should only be turned on "
-           "when kAllowPageWithIDBConnectionInBFCache is on.";
-
+  if (blink::features::
+          IsAllowPageWithIDBConnectionAndTransactionInBFCacheEnabled()) {
     RequireBlockingTransactionClientsToBeActive(transaction, lock_requests);
   }
 
diff --git a/content/browser/interest_group/interest_group_browsertest.cc b/content/browser/interest_group/interest_group_browsertest.cc
index bfa921e..4d764663 100644
--- a/content/browser/interest_group/interest_group_browsertest.cc
+++ b/content/browser/interest_group/interest_group_browsertest.cc
@@ -4637,8 +4637,15 @@
             EvalJs(shell(), auction_script));
 }
 
+// TODO(crbug.com/1408219) Flaky on Linux.
+#if BUILDFLAG(IS_LINUX)
+#define MAYBE_RunAdAuctionWithBidderWasm DISABLED_RunAdAuctionWithBidderWasm
+#else
+#define MAYBE_RunAdAuctionWithBidderWasm RunAdAuctionWithBidderWasm
+#endif  // BUILDFLAG(IS_LINUX)
 // Runs an auction where the bidding function uses a WASM helper.
-IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, RunAdAuctionWithBidderWasm) {
+IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
+                       MAYBE_RunAdAuctionWithBidderWasm) {
   GURL test_url = https_server_->GetURL("a.test", "/page_with_iframe.html");
   ASSERT_TRUE(NavigateToURL(shell(), test_url));
   url::Origin test_origin = url::Origin::Create(test_url);
diff --git a/content/browser/preloading/preloading_decider_unittest.cc b/content/browser/preloading/preloading_decider_unittest.cc
index ba1451017..49515ef3 100644
--- a/content/browser/preloading/preloading_decider_unittest.cc
+++ b/content/browser/preloading/preloading_decider_unittest.cc
@@ -120,7 +120,15 @@
   raw_ptr<MockAnchorElementPreconnector> delegate_;
 };
 
-class PreloadingDeciderTest : public RenderViewHostTestHarness {
+enum class EventType {
+  kPointerDown,
+  kPointerHover,
+};
+
+class PreloadingDeciderTest
+    : public RenderViewHostTestHarness,
+      public ::testing::WithParamInterface<
+          std::tuple<EventType, blink::mojom::SpeculationEagerness>> {
  public:
   PreloadingDeciderTest() {
     scoped_feature_list_.InitAndEnableFeatureWithParameters(
@@ -185,13 +193,19 @@
       test_cases{{true, GetCrossOriginUrl("/candidate1.html"),
                   blink::mojom::SpeculationAction::kPrefetch,
                   blink::mojom::SpeculationEagerness::kConservative},
-                 {false, GetCrossOriginUrl("/candidate2.html"),
+                 {true, GetCrossOriginUrl("/candidate2.html"),
+                  blink::mojom::SpeculationAction::kPrefetch,
+                  blink::mojom::SpeculationEagerness::kModerate},
+                 {false, GetCrossOriginUrl("/candidate3.html"),
                   blink::mojom::SpeculationAction::kPrefetch,
                   blink::mojom::SpeculationEagerness::kEager},
                  {true, GetCrossOriginUrl("/candidate1.html"),
                   blink::mojom::SpeculationAction::kPrerender,
                   blink::mojom::SpeculationEagerness::kConservative},
-                 {false, GetCrossOriginUrl("/candidate2.html"),
+                 {true, GetCrossOriginUrl("/candidate2.html"),
+                  blink::mojom::SpeculationAction::kPrerender,
+                  blink::mojom::SpeculationEagerness::kModerate},
+                 {false, GetCrossOriginUrl("/candidate3.html"),
                   blink::mojom::SpeculationAction::kPrerender,
                   blink::mojom::SpeculationEagerness::kEager}};
   std::vector<blink::mojom::SpeculationCandidatePtr> candidates;
@@ -214,10 +228,20 @@
   }
 }
 
-TEST_F(PreloadingDeciderTest, PrefetchOnPointerDownHeuristics) {
+TEST_P(PreloadingDeciderTest, PrefetchOnPointerEventHeuristics) {
   base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitWithFeatures(
-      {blink::features::kSpeculationRulesPointerDownHeuristics}, {});
+  switch (std::get<0>(GetParam())) {
+    case EventType::kPointerDown:
+      scoped_features.InitWithFeatures(
+          {blink::features::kSpeculationRulesPointerDownHeuristics}, {});
+      break;
+
+    case EventType::kPointerHover:
+      scoped_features.InitWithFeatures(
+          {blink::features::kSpeculationRulesPointerHoverHeuristics}, {});
+      break;
+  }
+
   MockContentBrowserClient browser_client;
 
   auto* preloading_decider =
@@ -230,40 +254,61 @@
   // Create list of SpeculationCandidatePtrs.
   std::vector<blink::mojom::SpeculationCandidatePtr> candidates;
 
+  auto call_pointer_event_handler = [&preloading_decider](const GURL& url) {
+    switch (std::get<0>(GetParam())) {
+      case EventType::kPointerDown:
+        preloading_decider->OnPointerDown(url);
+        break;
+      case EventType::kPointerHover:
+        preloading_decider->OnPointerHover(url);
+        break;
+    }
+  };
+
   auto candidate1 = blink::mojom::SpeculationCandidate::New();
   candidate1->action = blink::mojom::SpeculationAction::kPrefetch;
   candidate1->requires_anonymous_client_ip_when_cross_origin = true;
   candidate1->url = GetCrossOriginUrl("/candidate1.html");
   candidate1->referrer = blink::mojom::Referrer::New();
-  candidate1->eagerness = blink::mojom::SpeculationEagerness::kConservative;
+  candidate1->eagerness = std::get<1>(GetParam());
   candidates.push_back(std::move(candidate1));
 
   preloading_decider->UpdateSpeculationCandidates(candidates);
-  // It should not pass kDefault candidates directly
+  // It should not pass kModerate or kConservative candidates directly
   EXPECT_TRUE(GetPrefetchService()->prefetches_.empty());
 
-  preloading_decider->OnPointerDown(GetCrossOriginUrl("/candidate1.html"));
+  call_pointer_event_handler(GetCrossOriginUrl("/candidate1.html"));
   EXPECT_FALSE(
       preconnect_delegate->Target().has_value());  // Shouldn't preconnect
   EXPECT_EQ(
       1u,
       GetPrefetchService()->prefetches_.size());  // It should only prefetch
 
-  // Another pointer down should not change anything
-  preloading_decider->OnPointerDown(GetCrossOriginUrl("/candidate1.html"));
+  // Another pointer event should not change anything
+  call_pointer_event_handler(GetCrossOriginUrl("/candidate1.html"));
   EXPECT_FALSE(preconnect_delegate->Target().has_value());
   EXPECT_EQ(1u, GetPrefetchService()->prefetches_.size());
 
   // It should preconnect if the target is not safe to prefetch
-  preloading_decider->OnPointerDown(GetCrossOriginUrl("/candidate2.html"));
+  call_pointer_event_handler(GetCrossOriginUrl("/candidate2.html"));
   EXPECT_TRUE(preconnect_delegate->Target().has_value());
   EXPECT_EQ(1u, GetPrefetchService()->prefetches_.size());
 }
 
-TEST_F(PreloadingDeciderTest, PrerenderOnPointerDownHeuristics) {
+TEST_P(PreloadingDeciderTest, PrerenderOnPointerEventHeuristics) {
   base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitWithFeatures(
-      {blink::features::kSpeculationRulesPointerDownHeuristics}, {});
+  switch (std::get<0>(GetParam())) {
+    case EventType::kPointerDown:
+      scoped_features.InitWithFeatures(
+          {blink::features::kSpeculationRulesPointerDownHeuristics}, {});
+      break;
+
+    case EventType::kPointerHover:
+      scoped_features.InitWithFeatures(
+          {blink::features::kSpeculationRulesPointerHoverHeuristics}, {});
+      break;
+  }
+
   MockContentBrowserClient browser_client;
 
   auto* preloading_decider =
@@ -278,8 +323,8 @@
   // Create list of SpeculationCandidatePtrs.
   std::vector<blink::mojom::SpeculationCandidatePtr> candidates;
 
-  auto CreateCandidate = [this](const auto& action, const auto& url,
-                                const auto& eagerness) {
+  auto create_candidate = [this](const auto& action, const auto& url,
+                                 const auto& eagerness) {
     auto candidate = blink::mojom::SpeculationCandidate::New();
     candidate->action = action;
     candidate->url = GetSameOriginUrl(url);
@@ -288,19 +333,30 @@
     return candidate;
   };
 
-  candidates.push_back(CreateCandidate(
-      blink::mojom::SpeculationAction::kPrerender, "/candidate1.html",
-      blink::mojom::SpeculationEagerness::kConservative));
-  candidates.push_back(CreateCandidate(
-      blink::mojom::SpeculationAction::kPrefetch, "/candidate2.html",
-      blink::mojom::SpeculationEagerness::kConservative));
+  auto call_pointer_event_handler = [&preloading_decider](const GURL& url) {
+    switch (std::get<0>(GetParam())) {
+      case EventType::kPointerDown:
+        preloading_decider->OnPointerDown(url);
+        break;
+      case EventType::kPointerHover:
+        preloading_decider->OnPointerHover(url);
+        break;
+    }
+  };
+
+  candidates.push_back(
+      create_candidate(blink::mojom::SpeculationAction::kPrerender,
+                       "/candidate1.html", std::get<1>(GetParam())));
+  candidates.push_back(
+      create_candidate(blink::mojom::SpeculationAction::kPrefetch,
+                       "/candidate2.html", std::get<1>(GetParam())));
 
   preloading_decider->UpdateSpeculationCandidates(candidates);
-  // It should not pass kDefault candidates directly
+  // It should not pass kModerate or kConservative candidates directly
   EXPECT_TRUE(prerenderer.Get()->prerenders_.empty());
   EXPECT_TRUE(GetPrefetchService()->prefetches_.empty());
 
-  preloading_decider->OnPointerDown(GetSameOriginUrl("/candidate1.html"));
+  call_pointer_event_handler(GetSameOriginUrl("/candidate1.html"));
   EXPECT_FALSE(
       preconnect_delegate->Target().has_value());  // Shouldn't preconnect.
   EXPECT_EQ(0u,
@@ -308,25 +364,34 @@
   EXPECT_EQ(1u,
             prerenderer.Get()->prerenders_.size());  // Should prerender.
 
-  // Another pointer down should not change anything
-  preloading_decider->OnPointerDown(GetSameOriginUrl("/candidate1.html"));
+  // Another pointer event should not change anything
+  call_pointer_event_handler(GetSameOriginUrl("/candidate1.html"));
+
   EXPECT_FALSE(preconnect_delegate->Target().has_value());
   EXPECT_EQ(0u, GetPrefetchService()->prefetches_.size());
   EXPECT_EQ(1u, prerenderer.Get()->prerenders_.size());
 
   // It should prefetch if the target is safe to prefetch.
-  preloading_decider->OnPointerDown(GetSameOriginUrl("/candidate2.html"));
+  call_pointer_event_handler(GetSameOriginUrl("/candidate2.html"));
   EXPECT_FALSE(preconnect_delegate->Target().has_value());
   EXPECT_EQ(1u, GetPrefetchService()->prefetches_.size());
   EXPECT_EQ(1u, prerenderer.Get()->prerenders_.size());
 
   // It should preconnect if the target is not safe to prerender nor safe to
   // prefetch.
-  preloading_decider->OnPointerDown(GetSameOriginUrl("/candidate3.html"));
+  call_pointer_event_handler(GetSameOriginUrl("/candidate3.html"));
   EXPECT_TRUE(preconnect_delegate->Target().has_value());
   EXPECT_EQ(1u, GetPrefetchService()->prefetches_.size());
   EXPECT_EQ(1u, prerenderer.Get()->prerenders_.size());
 }
 
+INSTANTIATE_TEST_SUITE_P(
+    ParametrizedTests,
+    PreloadingDeciderTest,
+    testing::Combine(
+        testing::Values(EventType::kPointerDown, EventType::kPointerHover),
+        testing::Values(blink::mojom::SpeculationEagerness::kModerate,
+                        blink::mojom::SpeculationEagerness::kConservative)));
+
 }  // namespace
 }  // namespace content
diff --git a/content/browser/webauth/authenticator_common_impl.cc b/content/browser/webauth/authenticator_common_impl.cc
index 2162d21..22779aa3 100644
--- a/content/browser/webauth/authenticator_common_impl.cc
+++ b/content/browser/webauth/authenticator_common_impl.cc
@@ -1029,10 +1029,11 @@
                                     GetBrowserContext()->IsOffTheRecord());
   ctap_get_assertion_options_.emplace();
 
-  bool is_first = true;
-  absl::optional<std::vector<uint8_t>> last_id;
   if (options->prf) {
     requested_extensions_.insert(RequestExtension::kPRF);
+
+    bool is_first = true;
+    absl::optional<std::vector<uint8_t>> last_id;
     for (const auto& prf_input_from_renderer : options->prf_inputs) {
       device::CtapGetAssertionOptions::PRFInput prf_input;
 
diff --git a/content/browser/webauth/virtual_authenticator.cc b/content/browser/webauth/virtual_authenticator.cc
index f9272a5..cd945d1 100644
--- a/content/browser/webauth/virtual_authenticator.cc
+++ b/content/browser/webauth/virtual_authenticator.cc
@@ -28,6 +28,7 @@
       has_large_blob_(options.has_large_blob),
       has_cred_blob_(options.has_cred_blob),
       has_min_pin_length_(options.has_min_pin_length),
+      has_prf_(options.has_prf),
       unique_id_(base::GenerateGUID()),
       state_(base::MakeRefCounted<device::VirtualFidoDevice::State>()) {
   state_->transport = options.transport;
@@ -127,9 +128,15 @@
       config.large_blob_support = has_large_blob_;
       config.cred_protect_support = config.cred_blob_support = has_cred_blob_;
       config.min_pin_length_extension_support = has_min_pin_length_;
-      if (has_large_blob_ && has_user_verification_) {
-        // Writing a large blob requires obtaining a PinUvAuthToken with
-        // permissions if the authenticator is protected by user verification.
+      config.hmac_secret_support = has_prf_;
+
+      if (
+          // Writing a large blob requires obtaining a PinUvAuthToken with
+          // permissions if the authenticator is protected by user verification.
+          (has_large_blob_ && has_user_verification_) ||
+          // PRF support always requires PIN support because the exchange is
+          // encrypted.
+          has_prf_) {
         config.pin_uv_auth_token_support = true;
       }
       config.internal_uv_support = has_user_verification_;
diff --git a/content/browser/webauth/virtual_authenticator.h b/content/browser/webauth/virtual_authenticator.h
index 1781edc..b023b08d 100644
--- a/content/browser/webauth/virtual_authenticator.h
+++ b/content/browser/webauth/virtual_authenticator.h
@@ -174,6 +174,7 @@
   const bool has_large_blob_;
   const bool has_cred_blob_;
   const bool has_min_pin_length_;
+  const bool has_prf_;
   bool is_user_verified_ = true;
   const std::string unique_id_;
   bool is_user_present_;
diff --git a/content/browser/webid/federated_auth_request_impl.cc b/content/browser/webid/federated_auth_request_impl.cc
index f05d416..3b597060 100644
--- a/content/browser/webid/federated_auth_request_impl.cc
+++ b/content/browser/webid/federated_auth_request_impl.cc
@@ -35,7 +35,6 @@
 #include "third_party/blink/public/mojom/devtools/inspector_issue.mojom.h"
 #include "third_party/blink/public/mojom/webid/federated_auth_request.mojom.h"
 #include "ui/accessibility/ax_mode.h"
-#include "url/url_constants.h"
 
 using blink::mojom::FederatedAuthRequestResult;
 using blink::mojom::IdentityProviderConfig;
@@ -999,12 +998,13 @@
       if (IsFedCmLoginHintEnabled()) {
         FilterAccountsWithLoginHint(idp_info->provider->login_hint, accounts);
         if (accounts.empty()) {
-          // TODO(crbug.com/1407911): send the right errors here. Also determine
-          // the right behavior with respect to the IDP Sign-In status.
+          // If there are no accounts after filtering based on the login hint,
+          // treat this exactly the same as if we had received an empty accounts
+          // list, i.e. IdpNetworkRequestManager::ParseStatus::kEmptyListError.
           HandleAccountsFetchFailure(
               std::move(idp_info),
-              FederatedAuthRequestResult::kErrorFetchingAccountsNoResponse,
-              TokenStatus::kAccountsInvalidResponse);
+              FederatedAuthRequestResult::kErrorFetchingAccountsListEmpty,
+              TokenStatus::kAccountsListEmpty);
           return;
         }
       }
diff --git a/content/browser/webid/federated_auth_request_impl_unittest.cc b/content/browser/webid/federated_auth_request_impl_unittest.cc
index 85331278..19b9320 100644
--- a/content/browser/webid/federated_auth_request_impl_unittest.cc
+++ b/content/browser/webid/federated_auth_request_impl_unittest.cc
@@ -777,6 +777,8 @@
              "Provider's token is invalid."},
             {FederatedAuthRequestResult::kErrorRpPageNotVisible,
              "RP page is not visible."},
+            {FederatedAuthRequestResult::kErrorFetchingAccountsListEmpty,
+             "Provider's accounts list is empty."},
         };
     std::vector<std::string> messages =
         RenderFrameHostTester::For(main_rfh())->GetConsoleMessages();
@@ -2527,7 +2529,7 @@
   parameters.identity_providers[0].login_hint.is_required = true;
   const RequestExpectations expectations = {
       RequestTokenStatus::kError,
-      /*devtools_issue_statuses=*/{},
+      {FederatedAuthRequestResult::kErrorFetchingAccountsListEmpty},
       /*selected_idp_config_url=*/absl::nullopt};
 
   RunAuthTest(parameters, expectations, kConfigurationValid);
@@ -2588,7 +2590,7 @@
   parameters.identity_providers[0].login_hint.is_required = true;
   const RequestExpectations expectations = {
       RequestTokenStatus::kError,
-      /*devtools_issue_statuses=*/{},
+      {FederatedAuthRequestResult::kErrorFetchingAccountsListEmpty},
       /*selected_idp_config_url=*/absl::nullopt};
   MockConfiguration configuration = kConfigurationValid;
   configuration.idp_info[kProviderUrlFull].accounts = kMultipleAccounts;
diff --git a/content/browser/xr/service/xr_runtime_manager_impl.cc b/content/browser/xr/service/xr_runtime_manager_impl.cc
index 5ed87805..b644127 100644
--- a/content/browser/xr/service/xr_runtime_manager_impl.cc
+++ b/content/browser/xr/service/xr_runtime_manager_impl.cc
@@ -13,6 +13,7 @@
 #include "base/functional/callback.h"
 #include "base/lazy_instance.h"
 #include "base/memory/singleton.h"
+#include "base/no_destructor.h"
 #include "base/observer_list.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/trace_event/trace_event.h"
@@ -43,11 +44,17 @@
 
 namespace content {
 
+using XrRuntimeManagerObservers =
+    base::ObserverList<XRRuntimeManager::Observer>;
+
 namespace {
 XRRuntimeManagerImpl* g_xr_runtime_manager = nullptr;
 
-base::LazyInstance<base::ObserverList<XRRuntimeManager::Observer>>::Leaky
-    g_xr_runtime_manager_observers;
+XrRuntimeManagerObservers& GetXrRuntimeManagerObservers() {
+  static base::NoDestructor<XrRuntimeManagerObservers>
+      xr_runtime_manager_observers;
+  return *xr_runtime_manager_observers;
+}
 
 #if !BUILDFLAG(IS_ANDROID)
 bool IsEnabled(const base::CommandLine* command_line,
@@ -83,11 +90,11 @@
 }
 
 void XRRuntimeManager::AddObserver(XRRuntimeManager::Observer* observer) {
-  g_xr_runtime_manager_observers.Get().AddObserver(observer);
+  GetXrRuntimeManagerObservers().AddObserver(observer);
 }
 
 void XRRuntimeManager::RemoveObserver(XRRuntimeManager::Observer* observer) {
-  g_xr_runtime_manager_observers.Get().RemoveObserver(observer);
+  GetXrRuntimeManagerObservers().RemoveObserver(observer);
 }
 
 void XRRuntimeManager::ExitImmersivePresentation() {
@@ -497,8 +504,9 @@
   runtimes_[id] = std::make_unique<BrowserXRRuntimeImpl>(
       id, std::move(device_data), std::move(runtime));
 
-  for (Observer& obs : g_xr_runtime_manager_observers.Get())
+  for (Observer& obs : GetXrRuntimeManagerObservers()) {
     obs.OnRuntimeAdded(runtimes_[id].get());
+  }
 
   for (VRServiceImpl* service : services_) {
     // TODO(sumankancherla): Consider combining with XRRuntimeManager::Observer.
diff --git a/content/public/test/android/BUILD.gn b/content/public/test/android/BUILD.gn
index effae61..ffe9558 100644
--- a/content/public/test/android/BUILD.gn
+++ b/content/public/test/android/BUILD.gn
@@ -17,6 +17,7 @@
 
 android_library("content_java_test_support") {
   testonly = true
+  annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
   deps = [
     ":android_test_message_pump_support_java",
     "//base:base_java",
@@ -39,7 +40,6 @@
     "//url:gurl_java",
     "//url:origin_java",
   ]
-  annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
   sources = [
     "javatests/src/org/chromium/content_public/browser/test/ChildProcessAllocatorSettings.java",
     "javatests/src/org/chromium/content_public/browser/test/ChildProcessAllocatorSettingsHook.java",
diff --git a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/RenderFrameHostTestExt.java b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/RenderFrameHostTestExt.java
index 9474c9d..e39b16f 100644
--- a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/RenderFrameHostTestExt.java
+++ b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/RenderFrameHostTestExt.java
@@ -6,6 +6,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
 import org.chromium.content.browser.framehost.RenderFrameHostImpl;
 import org.chromium.content_public.browser.RenderFrameHost;
 
@@ -17,7 +18,8 @@
     private final long mNativeRenderFrameHostTestExt;
 
     public RenderFrameHostTestExt(RenderFrameHost host) {
-        mNativeRenderFrameHostTestExt = nativeInit(((RenderFrameHostImpl) host).getNativePtr());
+        mNativeRenderFrameHostTestExt =
+                RenderFrameHostTestExtJni.get().init(((RenderFrameHostImpl) host).getNativePtr());
     }
 
     /**
@@ -28,26 +30,31 @@
      *        serialized to a String using JSONStringValueSerializer.
      */
     public void executeJavaScript(String script, Callback<String> callback) {
-        nativeExecuteJavaScript(mNativeRenderFrameHostTestExt, script, callback, false);
+        RenderFrameHostTestExtJni.get().executeJavaScript(
+                mNativeRenderFrameHostTestExt, script, callback, false);
     }
 
     public void executeJavaScriptWithUserGesture(String script) {
-        nativeExecuteJavaScript(mNativeRenderFrameHostTestExt, script, (String r) -> {}, true);
+        RenderFrameHostTestExtJni.get().executeJavaScript(
+                mNativeRenderFrameHostTestExt, script, (String r) -> {}, true);
     }
 
     public void updateVisualState(Callback<Boolean> callback) {
-        nativeUpdateVisualState(mNativeRenderFrameHostTestExt, callback);
+        RenderFrameHostTestExtJni.get().updateVisualState(mNativeRenderFrameHostTestExt, callback);
     }
 
     public void notifyVirtualKeyboardOverlayRect(int x, int y, int width, int height) {
-        nativeNotifyVirtualKeyboardOverlayRect(mNativeRenderFrameHostTestExt, x, y, width, height);
+        RenderFrameHostTestExtJni.get().notifyVirtualKeyboardOverlayRect(
+                mNativeRenderFrameHostTestExt, x, y, width, height);
     }
 
-    private native long nativeInit(long renderFrameHostAndroidPtr);
-    private native void nativeExecuteJavaScript(long nativeRenderFrameHostTestExt, String script,
-            Callback<String> callback, boolean withUserGesture);
-    private native void nativeUpdateVisualState(
-            long nativeRenderFrameHostTestExt, Callback<Boolean> callback);
-    private native void nativeNotifyVirtualKeyboardOverlayRect(
-            long nativeRenderFrameHostTestExt, int x, int y, int width, int height);
+    @NativeMethods
+    interface Natives {
+        long init(long renderFrameHostAndroidPtr);
+        void executeJavaScript(long nativeRenderFrameHostTestExt, String script,
+                Callback<String> callback, boolean withUserGesture);
+        void updateVisualState(long nativeRenderFrameHostTestExt, Callback<Boolean> callback);
+        void notifyVirtualKeyboardOverlayRect(
+                long nativeRenderFrameHostTestExt, int x, int y, int width, int height);
+    }
 }
diff --git a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/RenderProcessHostUtils.java b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/RenderProcessHostUtils.java
index 2efa585..f393c0b 100644
--- a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/RenderProcessHostUtils.java
+++ b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/RenderProcessHostUtils.java
@@ -5,6 +5,7 @@
 package org.chromium.content_public.browser.test.util;
 
 import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
 
 /**
  * Collection of test-only WebContents utilities.
@@ -15,8 +16,11 @@
 
     public static int getCurrentRenderProcessCount() {
         return TestThreadUtils.runOnUiThreadBlockingNoException(
-                () -> { return nativeGetCurrentRenderProcessCount(); });
+                () -> { return RenderProcessHostUtilsJni.get().getCurrentRenderProcessCount(); });
     }
 
-    private static native int nativeGetCurrentRenderProcessCount();
+    @NativeMethods
+    interface Natives {
+        int getCurrentRenderProcessCount();
+    }
 }
diff --git a/content/public/test/android/render_frame_host_test_ext.cc b/content/public/test/android/render_frame_host_test_ext.cc
index 186b61b..9967fc2 100644
--- a/content/public/test/android/render_frame_host_test_ext.cc
+++ b/content/public/test/android/render_frame_host_test_ext.cc
@@ -35,7 +35,6 @@
 }  // namespace
 
 jlong JNI_RenderFrameHostTestExt_Init(JNIEnv* env,
-                                      const JavaParamRef<jobject>& obj,
                                       jlong render_frame_host_android_ptr) {
   RenderFrameHostAndroid* rfha =
       reinterpret_cast<RenderFrameHostAndroid*>(render_frame_host_android_ptr);
@@ -52,7 +51,6 @@
 
 void RenderFrameHostTestExt::ExecuteJavaScript(
     JNIEnv* env,
-    const JavaParamRef<jobject>& obj,
     const JavaParamRef<jstring>& jscript,
     const JavaParamRef<jobject>& jcallback,
     jboolean with_user_gesture) {
@@ -70,7 +68,6 @@
 
 void RenderFrameHostTestExt::UpdateVisualState(
     JNIEnv* env,
-    const JavaParamRef<jobject>& obj,
     const JavaParamRef<jobject>& jcallback) {
   auto result_callback = base::BindOnce(
       &base::android::RunBooleanCallbackAndroid,
@@ -78,13 +75,11 @@
   render_frame_host_->InsertVisualStateCallback(std::move(result_callback));
 }
 
-void RenderFrameHostTestExt::NotifyVirtualKeyboardOverlayRect(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& obj,
-    jint x,
-    jint y,
-    jint width,
-    jint height) {
+void RenderFrameHostTestExt::NotifyVirtualKeyboardOverlayRect(JNIEnv* env,
+                                                              jint x,
+                                                              jint y,
+                                                              jint width,
+                                                              jint height) {
   gfx::Size size(width, height);
   gfx::Point origin(x, y);
   render_frame_host_->GetPage().NotifyVirtualKeyboardOverlayRect(
diff --git a/content/public/test/android/render_frame_host_test_ext.h b/content/public/test/android/render_frame_host_test_ext.h
index d197fdf..a886665 100644
--- a/content/public/test/android/render_frame_host_test_ext.h
+++ b/content/public/test/android/render_frame_host_test_ext.h
@@ -20,23 +20,19 @@
   explicit RenderFrameHostTestExt(RenderFrameHostImpl* rfhi);
 
   void ExecuteJavaScript(JNIEnv* env,
-                         const base::android::JavaParamRef<jobject>& obj,
                          const base::android::JavaParamRef<jstring>& jscript,
                          const base::android::JavaParamRef<jobject>& jcallback,
                          jboolean with_user_gesture);
   // This calls InsertVisualStateCallback(). See it for details on the return
   // value.
   void UpdateVisualState(JNIEnv* env,
-                         const base::android::JavaParamRef<jobject>& obj,
                          const base::android::JavaParamRef<jobject>& jcallback);
 
-  void NotifyVirtualKeyboardOverlayRect(
-      JNIEnv* env,
-      const base::android::JavaParamRef<jobject>& obj,
-      jint x,
-      jint y,
-      jint width,
-      jint height);
+  void NotifyVirtualKeyboardOverlayRect(JNIEnv* env,
+                                        jint x,
+                                        jint y,
+                                        jint width,
+                                        jint height);
 
  private:
   const raw_ptr<RenderFrameHostImpl> render_frame_host_;
diff --git a/content/shell/browser/shell.cc b/content/shell/browser/shell.cc
index 22270c5..6a1878b 100644
--- a/content/shell/browser/shell.cc
+++ b/content/shell/browser/shell.cc
@@ -216,8 +216,7 @@
   WebContents::CreateParams create_params(browser_context, site_instance);
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kForcePresentationReceiverForTesting)) {
-    create_params.starting_sandbox_flags =
-        content::kPresentationReceiverSandboxFlags;
+    create_params.starting_sandbox_flags = kPresentationReceiverSandboxFlags;
   }
   std::unique_ptr<WebContents> web_contents =
       WebContents::Create(create_params);
@@ -505,7 +504,7 @@
                                     const std::string& protocol,
                                     const GURL& url,
                                     bool user_gesture) {
-  content::BrowserContext* context = requesting_frame->GetBrowserContext();
+  BrowserContext* context = requesting_frame->GetBrowserContext();
   if (context->IsOffTheRecord())
     return;
 
@@ -594,9 +593,9 @@
 }
 
 #if BUILDFLAG(IS_MAC)
-void Shell::PrimaryPageChanged(content::Page& page) {
+void Shell::PrimaryPageChanged(Page& page) {
   g_platform->DidNavigatePrimaryMainFramePostCommit(
-      this, content::WebContents::FromRenderFrameHost(&page.GetMainDocument()));
+      this, WebContents::FromRenderFrameHost(&page.GetMainDocument()));
 }
 
 bool Shell::HandleKeyboardEvent(WebContents* source,
@@ -672,8 +671,8 @@
 }  // namespace
 
 void Shell::UpdateInspectedWebContentsIfNecessary(
-    content::WebContents* old_contents,
-    content::WebContents* new_contents,
+    WebContents* old_contents,
+    WebContents* new_contents,
     base::OnceCallback<void()> callback) {
   scoped_refptr<PendingCallback> pending_callback =
       base::MakeRefCounted<PendingCallback>(std::move(callback));
diff --git a/content/shell/browser/shell.h b/content/shell/browser/shell.h
index a623e85..d77a5d2 100644
--- a/content/shell/browser/shell.h
+++ b/content/shell/browser/shell.h
@@ -163,19 +163,19 @@
   void ActivateContents(WebContents* contents) override;
   bool IsBackForwardCacheSupported() override;
   bool IsPrerender2Supported(WebContents& web_contents) override;
-  std::unique_ptr<content::WebContents> ActivatePortalWebContents(
-      content::WebContents* predecessor_contents,
-      std::unique_ptr<content::WebContents> portal_contents) override;
+  std::unique_ptr<WebContents> ActivatePortalWebContents(
+      WebContents* predecessor_contents,
+      std::unique_ptr<WebContents> portal_contents) override;
   void UpdateInspectedWebContentsIfNecessary(
-      content::WebContents* old_contents,
-      content::WebContents* new_contents,
+      WebContents* old_contents,
+      WebContents* new_contents,
       base::OnceCallback<void()> callback) override;
-  bool ShouldAllowRunningInsecureContent(content::WebContents* web_contents,
+  bool ShouldAllowRunningInsecureContent(WebContents* web_contents,
                                          bool allowed_per_prefs,
                                          const url::Origin& origin,
                                          const GURL& resource_url) override;
   PictureInPictureResult EnterPictureInPicture(
-      content::WebContents* web_contents) override;
+      WebContents* web_contents) override;
   bool ShouldResumeRequestsForCreatedWindow() override;
   void SetContentsBounds(WebContents* source, const gfx::Rect& bounds) override;
 
@@ -216,7 +216,7 @@
   void TitleWasSet(NavigationEntry* entry) override;
   void RenderFrameCreated(RenderFrameHost* frame_host) override;
 #if BUILDFLAG(IS_MAC)
-  void PrimaryPageChanged(content::Page& page) override;
+  void PrimaryPageChanged(Page& page) override;
 #endif
 
   std::unique_ptr<JavaScriptDialogManager> dialog_manager_;
diff --git a/device/BUILD.gn b/device/BUILD.gn
index e42444e1..0baa3c5b4 100644
--- a/device/BUILD.gn
+++ b/device/BUILD.gn
@@ -454,6 +454,7 @@
 
   android_library("bluetooth_test_java") {
     testonly = true
+    annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
     sources = bluetooth_java_sources_needing_jni
     deps = [
       "//base:base_java",
diff --git a/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java b/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java
index f033208..6b8708f 100644
--- a/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java
+++ b/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java
@@ -21,6 +21,7 @@
 import org.chromium.base.Log;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
 import org.chromium.components.location.LocationUtils;
 import org.chromium.device.bluetooth.test.TestRSSI;
 import org.chromium.device.bluetooth.test.TestTxPower;
@@ -71,7 +72,7 @@
      * Sets the factory for ThreadUtilsWrapper to always post a task to the UI thread
      * rather than running the task immediately. This simulates events arriving on a separate
      * thread on Android.
-     * runOnUiThread uses nativePostTaskFromJava. This allows java to post tasks to the
+     * runOnUiThread uses FakesJni.get().postTaskFromJava. This allows java to post tasks to the
      * message loop that the test is using rather than to the Java message loop which
      * is not running during tests.
      */
@@ -83,7 +84,7 @@
                 return new Wrappers.ThreadUtilsWrapper() {
                     @Override
                     public void runOnUiThread(Runnable r) {
-                        nativePostTaskFromJava(nativeBluetoothTestAndroid, r);
+                        FakesJni.get().postTaskFromJava(nativeBluetoothTestAndroid, r);
                     }
                 };
             }
@@ -245,11 +246,11 @@
         public boolean disable() {
             // android.bluetooth.BluetoothAdapter::disable() is an async call, so we simulate this
             // by posting a task to the UI thread.
-            nativePostTaskFromJava(mNativeBluetoothTestAndroid, new Runnable() {
+            FakesJni.get().postTaskFromJava(mNativeBluetoothTestAndroid, new Runnable() {
                 @Override
                 public void run() {
                     mPowered = false;
-                    nativeOnFakeAdapterStateChanged(mNativeBluetoothTestAndroid, false);
+                    FakesJni.get().onFakeAdapterStateChanged(mNativeBluetoothTestAndroid, false);
                 }
             });
             return true;
@@ -259,11 +260,11 @@
         public boolean enable() {
             // android.bluetooth.BluetoothAdapter::enable() is an async call, so we simulate this by
             // posting a task to the UI thread.
-            nativePostTaskFromJava(mNativeBluetoothTestAndroid, new Runnable() {
+            FakesJni.get().postTaskFromJava(mNativeBluetoothTestAndroid, new Runnable() {
                 @Override
                 public void run() {
                     mPowered = true;
-                    nativeOnFakeAdapterStateChanged(mNativeBluetoothTestAndroid, true);
+                    FakesJni.get().onFakeAdapterStateChanged(mNativeBluetoothTestAndroid, true);
                 }
             });
             return true;
@@ -530,7 +531,8 @@
                         "BluetoothGattWrapper doesn't support calls to connectGatt() with "
                         + "multiple distinct callbacks.");
             }
-            nativeOnFakeBluetoothDeviceConnectGattCalled(mAdapter.mNativeBluetoothTestAndroid);
+            FakesJni.get().onFakeBluetoothDeviceConnectGattCalled(
+                    mAdapter.mNativeBluetoothTestAndroid);
             mGattCallback = callback;
             return mGatt;
         }
@@ -576,12 +578,13 @@
 
         @Override
         public void disconnect() {
-            nativeOnFakeBluetoothGattDisconnect(mDevice.mAdapter.mNativeBluetoothTestAndroid);
+            FakesJni.get().onFakeBluetoothGattDisconnect(
+                    mDevice.mAdapter.mNativeBluetoothTestAndroid);
         }
 
         @Override
         public void close() {
-            nativeOnFakeBluetoothGattClose(mDevice.mAdapter.mNativeBluetoothTestAndroid);
+            FakesJni.get().onFakeBluetoothGattClose(mDevice.mAdapter.mNativeBluetoothTestAndroid);
         }
 
         @Override
@@ -591,7 +594,8 @@
 
         @Override
         public void discoverServices() {
-            nativeOnFakeBluetoothGattDiscoverServices(mDevice.mAdapter.mNativeBluetoothTestAndroid);
+            FakesJni.get().onFakeBluetoothGattDiscoverServices(
+                    mDevice.mAdapter.mNativeBluetoothTestAndroid);
         }
 
         @Override
@@ -605,7 +609,7 @@
                 mReadCharacteristicWillFailSynchronouslyOnce = false;
                 return false;
             }
-            nativeOnFakeBluetoothGattReadCharacteristic(
+            FakesJni.get().onFakeBluetoothGattReadCharacteristic(
                     mDevice.mAdapter.mNativeBluetoothTestAndroid);
             return true;
         }
@@ -617,7 +621,7 @@
                 mSetCharacteristicNotificationWillFailSynchronouslyOnce = false;
                 return false;
             }
-            nativeOnFakeBluetoothGattSetCharacteristicNotification(
+            FakesJni.get().onFakeBluetoothGattSetCharacteristicNotification(
                     mDevice.mAdapter.mNativeBluetoothTestAndroid);
             return true;
         }
@@ -628,7 +632,7 @@
                 mWriteCharacteristicWillFailSynchronouslyOnce = false;
                 return false;
             }
-            nativeOnFakeBluetoothGattWriteCharacteristic(
+            FakesJni.get().onFakeBluetoothGattWriteCharacteristic(
                     mDevice.mAdapter.mNativeBluetoothTestAndroid, characteristic.getValue());
             return true;
         }
@@ -639,7 +643,8 @@
                 mReadDescriptorWillFailSynchronouslyOnce = false;
                 return false;
             }
-            nativeOnFakeBluetoothGattReadDescriptor(mDevice.mAdapter.mNativeBluetoothTestAndroid);
+            FakesJni.get().onFakeBluetoothGattReadDescriptor(
+                    mDevice.mAdapter.mNativeBluetoothTestAndroid);
             return true;
         }
 
@@ -649,7 +654,7 @@
                 mWriteDescriptorWillFailSynchronouslyOnce = false;
                 return false;
             }
-            nativeOnFakeBluetoothGattWriteDescriptor(
+            FakesJni.get().onFakeBluetoothGattWriteDescriptor(
                     mDevice.mAdapter.mNativeBluetoothTestAndroid, descriptor.getValue());
             return true;
         }
@@ -987,45 +992,40 @@
 
     // ---------------------------------------------------------------------------------------------
     // BluetoothTestAndroid C++ methods declared for access from java:
+    @NativeMethods
+    interface Natives {
 
-    // Bind to BluetoothTestAndroid::PostTaskFromJava.
-    private static native void nativePostTaskFromJava(long nativeBluetoothTestAndroid, Runnable r);
+        // Bind to BluetoothTestAndroid::PostTaskFromJava.
+        void postTaskFromJava(long nativeBluetoothTestAndroid, Runnable r);
 
-    // Binds to BluetoothTestAndroid::OnFakeAdapterStateChanged.
-    private static native void nativeOnFakeAdapterStateChanged(
-            long nativeBluetoothTestAndroid, boolean powered);
+        // Binds to BluetoothTestAndroid::OnFakeAdapterStateChanged.
+        void onFakeAdapterStateChanged(long nativeBluetoothTestAndroid, boolean powered);
 
-    // Binds to BluetoothTestAndroid::OnFakeBluetoothDeviceConnectGattCalled.
-    private static native void nativeOnFakeBluetoothDeviceConnectGattCalled(
-            long nativeBluetoothTestAndroid);
+        // Binds to BluetoothTestAndroid::OnFakeBluetoothDeviceConnectGattCalled.
+        void onFakeBluetoothDeviceConnectGattCalled(long nativeBluetoothTestAndroid);
 
-    // Binds to BluetoothTestAndroid::OnFakeBluetoothGattDisconnect.
-    private static native void nativeOnFakeBluetoothGattDisconnect(long nativeBluetoothTestAndroid);
+        // Binds to BluetoothTestAndroid::OnFakeBluetoothGattDisconnect.
+        void onFakeBluetoothGattDisconnect(long nativeBluetoothTestAndroid);
 
-    // Binds to BluetoothTestAndroid::OnFakeBluetoothGattClose.
-    private static native void nativeOnFakeBluetoothGattClose(long nativeBluetoothTestAndroid);
+        // Binds to BluetoothTestAndroid::OnFakeBluetoothGattClose.
+        void onFakeBluetoothGattClose(long nativeBluetoothTestAndroid);
 
-    // Binds to BluetoothTestAndroid::OnFakeBluetoothGattDiscoverServices.
-    private static native void nativeOnFakeBluetoothGattDiscoverServices(
-            long nativeBluetoothTestAndroid);
+        // Binds to BluetoothTestAndroid::OnFakeBluetoothGattDiscoverServices.
+        void onFakeBluetoothGattDiscoverServices(long nativeBluetoothTestAndroid);
 
-    // Binds to BluetoothTestAndroid::OnFakeBluetoothGattSetCharacteristicNotification.
-    private static native void nativeOnFakeBluetoothGattSetCharacteristicNotification(
-            long nativeBluetoothTestAndroid);
+        // Binds to BluetoothTestAndroid::OnFakeBluetoothGattSetCharacteristicNotification.
+        void onFakeBluetoothGattSetCharacteristicNotification(long nativeBluetoothTestAndroid);
 
-    // Binds to BluetoothTestAndroid::OnFakeBluetoothGattReadCharacteristic.
-    private static native void nativeOnFakeBluetoothGattReadCharacteristic(
-            long nativeBluetoothTestAndroid);
+        // Binds to BluetoothTestAndroid::OnFakeBluetoothGattReadCharacteristic.
+        void onFakeBluetoothGattReadCharacteristic(long nativeBluetoothTestAndroid);
 
-    // Binds to BluetoothTestAndroid::OnFakeBluetoothGattWriteCharacteristic.
-    private static native void nativeOnFakeBluetoothGattWriteCharacteristic(
-            long nativeBluetoothTestAndroid, byte[] value);
+        // Binds to BluetoothTestAndroid::OnFakeBluetoothGattWriteCharacteristic.
+        void onFakeBluetoothGattWriteCharacteristic(long nativeBluetoothTestAndroid, byte[] value);
 
-    // Binds to BluetoothTestAndroid::OnFakeBluetoothGattReadDescriptor.
-    private static native void nativeOnFakeBluetoothGattReadDescriptor(
-            long nativeBluetoothTestAndroid);
+        // Binds to BluetoothTestAndroid::OnFakeBluetoothGattReadDescriptor.
+        void onFakeBluetoothGattReadDescriptor(long nativeBluetoothTestAndroid);
 
-    // Binds to BluetoothTestAndroid::OnFakeBluetoothGattWriteDescriptor.
-    private static native void nativeOnFakeBluetoothGattWriteDescriptor(
-            long nativeBluetoothTestAndroid, byte[] value);
+        // Binds to BluetoothTestAndroid::OnFakeBluetoothGattWriteDescriptor.
+        void onFakeBluetoothGattWriteDescriptor(long nativeBluetoothTestAndroid, byte[] value);
+    }
 }
diff --git a/device/fido/features.cc b/device/fido/features.cc
index 361f2dc..d30c69d 100644
--- a/device/fido/features.cc
+++ b/device/fido/features.cc
@@ -36,10 +36,6 @@
              "WebAuthenticationPasskeysUI",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-BASE_FEATURE(kWebAuthnNewDiscoverableCredentialsUi,
-             "WebAuthenticationNewDiscoverableCredentialsUi",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 BASE_FEATURE(kWebAuthnNoEmptyDisplayNameCBOR,
              "WebAuthenticationNoEmptyDisplayNameCBOR",
              base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/device/fido/features.h b/device/fido/features.h
index 7ba3470..2237e0fb 100644
--- a/device/fido/features.h
+++ b/device/fido/features.h
@@ -36,11 +36,6 @@
 // Enable some experimental UI changes
 COMPONENT_EXPORT(DEVICE_FIDO) BASE_DECLARE_FEATURE(kWebAuthPasskeysUI);
 
-// Reshuffle WebAuthn request UI to put account selection for discoverable
-// credentials on platform authenticators first, where applicable.
-COMPONENT_EXPORT(DEVICE_FIDO)
-BASE_DECLARE_FEATURE(kWebAuthnNewDiscoverableCredentialsUi);
-
 // Don't send empty displayName values to security keys when creating
 // credentials.
 BASE_DECLARE_FEATURE(kWebAuthnNoEmptyDisplayNameCBOR);
diff --git a/device/fido/fido_request_handler_base.cc b/device/fido/fido_request_handler_base.cc
index ca0e88ea..f05b7410 100644
--- a/device/fido/fido_request_handler_base.cc
+++ b/device/fido/fido_request_handler_base.cc
@@ -8,7 +8,6 @@
 
 #include "base/containers/contains.h"
 #include "base/containers/cxx20_erase.h"
-#include "base/feature_list.h"
 #include "base/functional/bind.h"
 #include "base/location.h"
 #include "base/logging.h"
@@ -20,7 +19,6 @@
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "device/fido/ble_adapter_manager.h"
 #include "device/fido/discoverable_credential_metadata.h"
-#include "device/fido/features.h"
 #include "device/fido/fido_authenticator.h"
 #include "device/fido/fido_discovery_factory.h"
 
@@ -403,9 +401,7 @@
     bool have_credential) {
   DCHECK_EQ(transport_availability_info_.has_platform_authenticator_credential,
             RecognizedCredential::kUnknown);
-  if (base::FeatureList::IsEnabled(
-          device::kWebAuthnNewDiscoverableCredentialsUi) &&
-      !have_credential) {
+  if (!have_credential) {
     transport_availability_info_.has_platform_authenticator_credential =
         RecognizedCredential::kNoRecognizedCredential;
     transport_availability_info_.available_transports.erase(
diff --git a/device/fido/mac/make_credential_operation.mm b/device/fido/mac/make_credential_operation.mm
index 9e5af8d..3743ae7 100644
--- a/device/fido/mac/make_credential_operation.mm
+++ b/device/fido/mac/make_credential_operation.mm
@@ -9,7 +9,6 @@
 #import <Foundation/Foundation.h>
 
 #include "base/containers/contains.h"
-#include "base/feature_list.h"
 #include "base/functional/bind.h"
 #include "base/mac/foundation_util.h"
 #include "base/mac/mac_logging.h"
@@ -20,7 +19,6 @@
 #include "device/fido/attestation_statement_formats.h"
 #include "device/fido/attested_credential_data.h"
 #include "device/fido/authenticator_data.h"
-#include "device/fido/features.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_parsing_utils.h"
 #include "device/fido/fido_transport_protocol.h"
@@ -105,19 +103,13 @@
     return;
   }
 
+  // Generate the new key pair.
+  //
   // New credentials are always discoverable. But older non-discoverable
   // credentials may exist.
-  const bool resident_key =
-      base::FeatureList::IsEnabled(kWebAuthnNewDiscoverableCredentialsUi)
-          ? true
-          : request_.resident_key_required;
-
-  // Generate the new key pair.
   absl::optional<std::pair<Credential, base::ScopedCFTypeRef<SecKeyRef>>>
       credential_result = credential_store_->CreateCredential(
-          request_.rp.id, request_.user,
-          resident_key ? TouchIdCredentialStore::kDiscoverable
-                       : TouchIdCredentialStore::kNonDiscoverable);
+          request_.rp.id, request_.user, TouchIdCredentialStore::kDiscoverable);
   if (!credential_result) {
     FIDO_LOG(ERROR) << "CreateCredential() failed";
     std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
@@ -155,7 +147,8 @@
           std::make_unique<PackedAttestationStatement>(
               CoseAlgorithmIdentifier::kEs256, std::move(*signature),
               /*x509_certificates=*/std::vector<std::vector<uint8_t>>())));
-  response.is_resident_key = resident_key;
+  // New credentials are always discoverable.
+  response.is_resident_key = true;
   response.transports.emplace();
   response.transports->insert(FidoTransportProtocol::kInternal);
   std::move(callback_).Run(CtapDeviceResponseCode::kSuccess,
diff --git a/device/fido/win/logging.cc b/device/fido/win/logging.cc
index 8a112a0d..a6fb562 100644
--- a/device/fido/win/logging.cc
+++ b/device/fido/win/logging.cc
@@ -101,7 +101,8 @@
 }
 
 std::ostream& operator<<(std::ostream& out, const WEBAUTHN_EXTENSION& in) {
-  return out << "{" << Quoted(in.pwszExtensionIdentifier) << "}";
+  return out << "{" << Quoted(in.pwszExtensionIdentifier) << kSep
+             << base::HexEncode(in.pvExtension, in.cbExtension) << "}";
 }
 
 std::ostream& operator<<(std::ostream& out, const WEBAUTHN_EXTENSIONS& in) {
@@ -112,6 +113,34 @@
   return out << "]}";
 }
 
+std::ostream& operator<<(std::ostream& out,
+                         const WEBAUTHN_HMAC_SECRET_SALT& in) {
+  // The salts may be considered sensitive, and this structure is also reused
+  // for the outputs, so only the lengths are logged.
+  return out << "{[" << in.cbFirst << "]" << kSep << "[" << in.cbSecond << "]}";
+}
+
+std::ostream& operator<<(std::ostream& out,
+                         const WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT& in) {
+  return out << "{" << base::HexEncode(in.pbCredID, in.cbCredID) << kSep << "&"
+             << *in.pHmacSecretSalt << "}";
+}
+
+std::ostream& operator<<(std::ostream& out,
+                         const WEBAUTHN_HMAC_SECRET_SALT_VALUES& in) {
+  out << "{";
+  if (in.pGlobalHmacSalt) {
+    out << "&" << *in.pGlobalHmacSalt;
+  } else {
+    out << "(null)";
+  }
+  out << kSep << "[";
+  for (DWORD i = 0; i < in.cCredWithHmacSecretSaltList; i++) {
+    out << (i ? kSep : "") << in.pCredWithHmacSecretSaltList[i];
+  }
+  return out << "]}";
+}
+
 std::ostream& operator<<(
     std::ostream& out,
     const WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS& in) {
@@ -136,6 +165,14 @@
   } else {
     out << ", (null)";
   }
+  if (in.dwVersion < WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_6) {
+    return out << "}";
+  }
+  if (in.pHmacSecretSaltValues) {
+    out << ", &" << *in.pHmacSecretSaltValues;
+  } else {
+    out << ", (null)";
+  }
   return out << "}";
 }
 
@@ -190,9 +227,21 @@
 }
 
 std::ostream& operator<<(std::ostream& out, const WEBAUTHN_ASSERTION& in) {
-  return out << "{" << in.dwVersion << kSep
-             << base::HexEncode(in.pbAuthenticatorData, in.cbAuthenticatorData)
-             << kSep << base::HexEncode(in.pbSignature, in.cbSignature) << kSep
-             << in.Credential << kSep
-             << base::HexEncode(in.pbUserId, in.cbUserId) << "}";
+  out << "{" << in.dwVersion << kSep
+      << base::HexEncode(in.pbAuthenticatorData, in.cbAuthenticatorData) << kSep
+      << base::HexEncode(in.pbSignature, in.cbSignature) << kSep
+      << in.Credential << kSep << base::HexEncode(in.pbUserId, in.cbUserId);
+  if (in.dwVersion < WEBAUTHN_ASSERTION_VERSION_2) {
+    return out << "}";
+  }
+  out << in.Extensions;
+  if (in.dwVersion < WEBAUTHN_ASSERTION_VERSION_3) {
+    return out << "}";
+  }
+  if (in.pHmacSecret) {
+    out << kSep << "&" << *in.pHmacSecret;
+  } else {
+    out << ", (null)";
+  }
+  return out << "}";
 }
diff --git a/device/fido/win/type_conversions.cc b/device/fido/win/type_conversions.cc
index 021ca4d..9384958 100644
--- a/device/fido/win/type_conversions.cc
+++ b/device/fido/win/type_conversions.cc
@@ -29,6 +29,28 @@
 
 namespace device {
 
+namespace {
+
+absl::optional<std::vector<uint8_t>> HMACSecretOutputs(
+    const WEBAUTHN_HMAC_SECRET_SALT& salt) {
+  constexpr size_t kOutputLength = 32;
+  if (salt.cbFirst != kOutputLength ||
+      (salt.cbSecond != 0 && salt.cbSecond != kOutputLength)) {
+    FIDO_LOG(ERROR) << "Incorrect HMAC output lengths: " << salt.cbFirst << " "
+                    << salt.cbSecond;
+    return absl::nullopt;
+  }
+
+  std::vector<uint8_t> ret;
+  ret.insert(ret.end(), salt.pbFirst, salt.pbFirst + salt.cbFirst);
+  if (salt.cbSecond == kOutputLength) {
+    ret.insert(ret.end(), salt.pbSecond, salt.pbSecond + salt.cbSecond);
+  }
+  return ret;
+}
+
+}  // namespace
+
 absl::optional<AuthenticatorMakeCredentialResponse>
 ToAuthenticatorMakeCredentialResponse(
     const WEBAUTHN_CREDENTIAL_ATTESTATION& credential_attestation) {
@@ -120,6 +142,10 @@
     response.user_entity = PublicKeyCredentialUserEntity(std::vector<uint8_t>(
         assertion.pbUserId, assertion.pbUserId + assertion.cbUserId));
   }
+  if (assertion.dwVersion >= WEBAUTHN_ASSERTION_VERSION_3 &&
+      assertion.pHmacSecret) {
+    response.hmac_secret = HMACSecretOutputs(*assertion.pHmacSecret);
+  }
   return response;
 }
 
diff --git a/device/fido/win/webauthn_api.cc b/device/fido/win/webauthn_api.cc
index 53a6f35..021777f 100644
--- a/device/fido/win/webauthn_api.cc
+++ b/device/fido/win/webauthn_api.cc
@@ -39,6 +39,64 @@
   return base::StringPrintf("0x%0lX", hr);
 }
 
+// FillHMACSalts converts `input` to the Windows representation of a pair of
+// HMAC salt values, using `salts_storage` to own the returned pointer.
+WEBAUTHN_HMAC_SECRET_SALT* FillHMACSalts(
+    std::vector<WEBAUTHN_HMAC_SECRET_SALT>* salts_storage,
+    const CtapGetAssertionOptions::PRFInput& input) {
+  const WEBAUTHN_HMAC_SECRET_SALT salts{
+      base::checked_cast<DWORD>(input.salt1.size()),
+      const_cast<PBYTE>(input.salt1.data()),
+      input.salt2.has_value() ? base::checked_cast<DWORD>(input.salt2->size())
+                              : 0,
+      input.salt2.has_value() ? const_cast<PBYTE>(input.salt2->data())
+                              : nullptr,
+  };
+  salts_storage->push_back(salts);
+  return &salts_storage->back();
+}
+
+// FillHMACSaltValues converts `inputs` to the Windows representation of the
+// PRF inputs and uses the `*_storage` arguments to own the returned structures.
+WEBAUTHN_HMAC_SECRET_SALT_VALUES* FillHMACSaltValues(
+    WEBAUTHN_HMAC_SECRET_SALT_VALUES* values_storage,
+    std::vector<WEBAUTHN_HMAC_SECRET_SALT>* salts_storage,
+    std::vector<WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT>* cred_salts_storage,
+    const std::vector<CtapGetAssertionOptions::PRFInput>& inputs) {
+  if (inputs.empty()) {
+    return nullptr;
+  }
+
+  memset(values_storage, 0, sizeof(*values_storage));
+  // These vectors must not reallocate because the Windows structures will have
+  // pointers into their elements.
+  salts_storage->reserve(inputs.size());
+  cred_salts_storage->reserve(inputs.size());
+
+  for (const auto& input : inputs) {
+    if (!input.credential_id.has_value()) {
+      // Only the first input may omit the credential ID.
+      DCHECK(cred_salts_storage->empty());
+      values_storage->pGlobalHmacSalt = FillHMACSalts(salts_storage, input);
+    } else {
+      const WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT cred_salt{
+          base::checked_cast<DWORD>(input.credential_id->size()),
+          const_cast<PBYTE>(input.credential_id->data()),
+          FillHMACSalts(salts_storage, input),
+      };
+      cred_salts_storage->push_back(cred_salt);
+    }
+  }
+
+  if (!cred_salts_storage->empty()) {
+    values_storage->cCredWithHmacSecretSaltList =
+        base::checked_cast<DWORD>(cred_salts_storage->size());
+    values_storage->pCredWithHmacSecretSaltList = cred_salts_storage->data();
+  }
+
+  return values_storage;
+}
+
 }  // namespace
 
 class WinWebAuthnApiImpl : public WinWebAuthnApi {
@@ -501,10 +559,24 @@
     });
   }
 
+  WEBAUTHN_HMAC_SECRET_SALT_VALUES hmac_salt_values_storage;
+  std::vector<WEBAUTHN_HMAC_SECRET_SALT> salts_storage;
+  std::vector<WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT> cred_salts_storage;
+  WEBAUTHN_HMAC_SECRET_SALT_VALUES* const hmac_salt_values =
+      FillHMACSaltValues(&hmac_salt_values_storage, &salts_storage,
+                         &cred_salts_storage, request_options.prf_inputs);
+
+  DWORD flags = 0;
+  if (hmac_salt_values) {
+    // The HMAC salts are hashed in the renderer. This flag indicates that they
+    // should not be hashed again.
+    flags |= WEBAUTHN_AUTHENTICATOR_HMAC_SECRET_VALUES_FLAG;
+  }
+
   static BOOL kUseAppIdTrue = TRUE;    // const
   static BOOL kUseAppIdFalse = FALSE;  // const
   WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS options{
-      WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_4,
+      WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_6,
       kWinWebAuthnTimeoutMilliseconds,
       // As of Nov 2018, the WebAuthNAuthenticatorGetAssertion method will
       // fail to challenge credentials via CTAP1 if the allowList is passed
@@ -522,11 +594,16 @@
                           extensions.data()},
       WEBAUTHN_AUTHENTICATOR_ATTACHMENT_ANY,
       ToWinUserVerificationRequirement(request.user_verification),
-      /*dwFlags=*/0,
+      flags,
       opt_app_id16 ? base::as_wcstr(*opt_app_id16) : nullptr,
       opt_app_id16 ? &kUseAppIdTrue : &kUseAppIdFalse,
       &cancellation_id,
       &allow_credential_list,
+      /*dwCredLargeBlobOperation=*/0,
+      /*cbCredLargeBlob=*/0,
+      /*pbCredLargeBlob=*/nullptr,
+      hmac_salt_values,
+      /*bBrowserInPrivateMode=*/false,
   };
 
   WEBAUTHN_ASSERTION* assertion = nullptr;
@@ -552,8 +629,10 @@
   FIDO_LOG(DEBUG) << "WebAuthNAuthenticatorGetAssertion()=" << *assertion;
   absl::optional<AuthenticatorGetAssertionResponse> response =
       ToAuthenticatorGetAssertionResponse(*assertion, request.allow_list);
-  if (response && !request_options.prf_inputs.empty()) {
-    // Windows does not yet support passing in inputs for hmac_secret.
+  if (response && !request_options.prf_inputs.empty() &&
+      webauthn_api->Version() < WEBAUTHN_API_VERSION_4) {
+    // This version of Windows does not yet support passing in inputs for
+    // hmac_secret.
     response->hmac_secret_not_evaluated = true;
   }
   return {response ? CtapDeviceResponseCode::kSuccess
diff --git a/device/vr/android/arcore/arcore_gl.cc b/device/vr/android/arcore/arcore_gl.cc
index e739c90..68c40f1 100644
--- a/device/vr/android/arcore/arcore_gl.cc
+++ b/device/vr/android/arcore/arcore_gl.cc
@@ -450,7 +450,8 @@
 
   gl::GLDisplay* display = nullptr;
   if (gl::GetGLImplementation() == gl::kGLImplementationNone) {
-    display = gl::init::InitializeGLOneOff(/*system_device_id=*/0);
+    display = gl::init::InitializeGLOneOff(
+        /*gpu_preference=*/gl::GpuPreference::kDefault);
     if (!display) {
       DLOG(ERROR) << "gl::init::InitializeGLOneOff failed";
       return false;
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn
index c4c00e8..4ff8ba47 100644
--- a/gpu/command_buffer/service/BUILD.gn
+++ b/gpu/command_buffer/service/BUILD.gn
@@ -237,6 +237,8 @@
     "shared_image/gl_repack_utils.h",
     "shared_image/gl_texture_common_representations.cc",
     "shared_image/gl_texture_common_representations.h",
+    "shared_image/gl_texture_holder.cc",
+    "shared_image/gl_texture_holder.h",
     "shared_image/gl_texture_image_backing.cc",
     "shared_image/gl_texture_image_backing.h",
     "shared_image/gl_texture_image_backing_factory.cc",
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index 0326145..beeed08 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -2435,7 +2435,7 @@
       /*fallback_to_software_gl=*/false,
       /*disable_gl_drawing=*/false,
       /*init_extensions=*/true,
-      /*system_device_id=*/0);
+      /*gpu_preference=*/gl::GpuPreference::kDefault);
 
   scoped_refptr<gles2::FeatureInfo> feature_info = new gles2::FeatureInfo();
   group_ = new gles2::ContextGroup(
diff --git a/gpu/command_buffer/service/image_reader_gl_owner_unittest.cc b/gpu/command_buffer/service/image_reader_gl_owner_unittest.cc
index f1a90ea4..02929506 100644
--- a/gpu/command_buffer/service/image_reader_gl_owner_unittest.cc
+++ b/gpu/command_buffer/service/image_reader_gl_owner_unittest.cc
@@ -44,7 +44,7 @@
         /*fallback_to_software_gl=*/false,
         /*disable_gl_drawing=*/false,
         /*init_extensions=*/true,
-        /*system_device_id=*/0);
+        /*gpu_preference=*/gl::GpuPreference::kDefault);
 
     surface_ = new gl::PbufferGLSurfaceEGL(gl::GLSurfaceEGL::GetGLDisplayEGL(),
                                            gfx::Size(320, 240));
diff --git a/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing.cc b/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing.cc
index 352bb720..e83dce0 100644
--- a/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing.cc
@@ -264,7 +264,7 @@
   DCHECK(vulkan_implementation->CanImportGpuMemoryBuffer(device_queue,
                                                          handle.type));
 
-  VkFormat vk_format = ToVkFormat(format().resource_format());
+  VkFormat vk_format = ToVkFormat(format());
   auto vulkan_image = vulkan_implementation->CreateImageFromGpuMemoryHandle(
       device_queue, std::move(handle), size(), vk_format, color_space());
 
diff --git a/gpu/command_buffer/service/shared_image/dcomp_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/dcomp_image_backing_factory.cc
index 5c040c1c..5716404 100644
--- a/gpu/command_buffer/service/shared_image/dcomp_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/dcomp_image_backing_factory.cc
@@ -133,7 +133,7 @@
   // dc overlays are to be used for rgb10, the caller should use swap chains
   // instead.
   if (usage == kDCompSurfaceUsage &&
-      format.resource_format() == viz::ResourceFormat::RGBA_1010102) {
+      format == viz::SinglePlaneFormat::kRGBA_1010102) {
     return false;
   }
 
diff --git a/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc
index 5ca146c..d875af67 100644
--- a/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc
@@ -487,14 +487,13 @@
 
   // As long as either |chromium_image_ar30| or |chromium_image_ab30| is
   // enabled, we can create a non-scanout SharedImage with format
-  // viz::ResourceFormat::{BGRA,RGBA}_1010102.
+  // viz::SinglePlaneFormat::{BGRA,RGBA}_1010102.
   const bool supports_ar30 =
       context_state->feature_info()->feature_flags().chromium_image_ar30;
   const bool supports_ab30 =
       context_state->feature_info()->feature_flags().chromium_image_ab30;
-  const auto resource_format = format.resource_format();
-  if ((resource_format == viz::ResourceFormat::BGRA_1010102 ||
-       resource_format == viz::ResourceFormat::RGBA_1010102) &&
+  if ((format == viz::SinglePlaneFormat::kBGRA_1010102 ||
+       format == viz::SinglePlaneFormat::kRGBA_1010102) &&
       !supports_ar30 && !supports_ab30) {
     EXPECT_FALSE(backing_);
     return;
@@ -542,8 +541,8 @@
   // support. It's possible Skia might support these formats even if the Chrome
   // feature flags are false. We just check here that the feature flags don't
   // allow Chrome to do something that Skia doesn't support.
-  if ((resource_format != viz::ResourceFormat::BGRA_1010102 || supports_ar30) &&
-      (resource_format != viz::ResourceFormat::RGBA_1010102 || supports_ab30)) {
+  if ((format != viz::SinglePlaneFormat::kBGRA_1010102 || supports_ar30) &&
+      (format != viz::SinglePlaneFormat::kRGBA_1010102 || supports_ab30)) {
     EXPECT_TRUE(scoped_write_access);
     if (!scoped_write_access)
       return;
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_backing.cc b/gpu/command_buffer/service/shared_image/external_vk_image_backing.cc
index 57eeebf0..803372e 100644
--- a/gpu/command_buffer/service/shared_image/external_vk_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/external_vk_image_backing.cc
@@ -112,8 +112,9 @@
   if (!context_state->support_vulkan_external_object())
     return true;
 
-  if (format.resource_format() != viz::ResourceFormat::BGRA_8888)
+  if (format != viz::SinglePlaneFormat::kBGRA_8888) {
     return false;
+  }
 
   auto* gl_context = context_state->real_context();
   const auto* version_info = gl_context->GetVersionInfo();
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_holder.cc b/gpu/command_buffer/service/shared_image/gl_texture_holder.cc
new file mode 100644
index 0000000..4a7522e
--- /dev/null
+++ b/gpu/command_buffer/service/shared_image/gl_texture_holder.cc
@@ -0,0 +1,335 @@
+// 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 "gpu/command_buffer/service/shared_image/gl_texture_holder.h"
+
+#include "build/build_config.h"
+#include "components/viz/common/resources/resource_sizes.h"
+#include "gpu/command_buffer/service/shared_context_state.h"
+#include "gpu/command_buffer/service/shared_image/gl_repack_utils.h"
+#include "gpu/command_buffer/service/skia_utils.h"
+#include "third_party/skia/include/core/SkPromiseImageTexture.h"
+#include "third_party/skia/include/gpu/GrContextThreadSafeProxy.h"
+#include "ui/gl/gl_version_info.h"
+#include "ui/gl/progress_reporter.h"
+#include "ui/gl/scoped_binders.h"
+
+namespace gpu {
+namespace {
+
+// This value can't be cached as it may change for different contexts.
+bool SupportsUnpackSubimage() {
+  return gl::g_current_gl_version->is_es3_capable ||
+         gl::g_current_gl_driver->ext.b_GL_EXT_unpack_subimage;
+}
+
+// This value can't be cached as it may change for different contexts.
+bool SupportsPackSubimage() {
+#if BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_X86_FAMILY)
+  // GL_PACK_ROW_LENGTH is broken in the Android emulator. glReadPixels()
+  // modifies bytes between the last pixel in a row and the end of the stride
+  // for that row.
+  return false;
+#else
+  return gl::g_current_gl_version->is_es3_capable;
+#endif
+}
+
+}  // anonymous namespace
+
+GLTextureHolder::GLTextureHolder(viz::ResourceFormat format,
+                                 const gfx::Size& size,
+                                 bool is_passthrough)
+    : format_(format), size_(size), is_passthrough_(is_passthrough) {}
+
+GLTextureHolder::GLTextureHolder(GLTextureHolder&& other) {
+  operator=(std::move(other));
+}
+
+GLTextureHolder& GLTextureHolder::operator=(GLTextureHolder&& other) {
+  size_ = other.size_;
+  is_passthrough_ = other.is_passthrough_;
+  context_lost_ = other.context_lost_;
+  texture_ = other.texture_;
+  other.texture_ = nullptr;
+  passthrough_texture_ = std::move(other.passthrough_texture_);
+  format_desc_ = other.format_desc_;
+  return *this;
+}
+
+GLTextureHolder::~GLTextureHolder() {
+  if (is_passthrough_) {
+    if (passthrough_texture_) {
+      if (context_lost_) {
+        passthrough_texture_->MarkContextLost();
+      }
+      passthrough_texture_.reset();
+    }
+  } else {
+    if (texture_) {
+      texture_->RemoveLightweightRef(!context_lost_);
+      texture_ = nullptr;
+    }
+  }
+}
+
+GLuint GLTextureHolder::GetServiceId() const {
+  return is_passthrough_ ? passthrough_texture_->service_id()
+                         : texture_->service_id();
+}
+
+void GLTextureHolder::Initialize(
+    const GLCommonImageBackingFactory::FormatInfo& format_info,
+    bool framebuffer_attachment_angle,
+    base::span<const uint8_t> pixel_data,
+    gl::ProgressReporter* progress_reporter,
+    const std::string& debug_label) {
+  format_desc_.target = GL_TEXTURE_2D;
+  format_desc_.data_format = format_info.gl_format;
+  format_desc_.data_type = format_info.gl_type;
+  format_desc_.image_internal_format = format_info.image_internal_format;
+  format_desc_.storage_internal_format = format_info.storage_internal_format;
+
+  GLTextureImageBackingHelper::MakeTextureAndSetParameters(
+      format_desc_.target, /*service_id=*/0, framebuffer_attachment_angle,
+      is_passthrough_ ? &passthrough_texture_ : nullptr,
+      is_passthrough_ ? nullptr : &texture_);
+
+  if (is_passthrough_) {
+    passthrough_texture_->SetEstimatedSize(
+        viz::ResourceSizes::UncheckedSizeInBytes<size_t>(size_, format_));
+  } else {
+    // TODO(piman): We pretend the texture was created in an ES2 context, so
+    // that it can be used in other ES2 contexts, and so we have to pass
+    // gl_format as the internal format in the LevelInfo.
+    // https://crbug.com/628064
+    texture_->SetLevelInfo(format_desc_.target, 0, format_desc_.data_format,
+                           size_.width(), size_.height(), /*depth=*/1, 0,
+                           format_desc_.data_format, format_desc_.data_type,
+                           /*cleared_rect=*/gfx::Rect());
+    texture_->SetImmutable(true, format_info.supports_storage);
+  }
+
+  gl::GLApi* api = gl::g_current_gl_context;
+  GLTextureImageBackingHelper::ScopedRestoreTexture scoped_restore(
+      api, format_desc_.target, GetServiceId());
+
+  // Initialize the texture storage/image parameters and upload initial pixels
+  // if available.
+  if (format_info.supports_storage) {
+    {
+      gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter);
+      api->glTexStorage2DEXTFn(format_desc_.target, /*levels=*/1,
+                               format_info.adjusted_storage_internal_format,
+                               size_.width(), size_.height());
+    }
+
+    if (!pixel_data.empty()) {
+      ScopedUnpackState scoped_unpack_state(
+          /*uploading_data=*/true);
+      gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter);
+      api->glTexSubImage2DFn(format_desc_.target, /*level=*/0, /*xoffset=*/0,
+                             /*yoffset=*/0, size_.width(), size_.height(),
+                             format_info.adjusted_format,
+                             format_desc_.data_type, pixel_data.data());
+    }
+  } else if (format_info.is_compressed) {
+    ScopedUnpackState scoped_unpack_state(!pixel_data.empty());
+    gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter);
+    api->glCompressedTexImage2DFn(format_desc_.target, 0,
+                                  format_desc_.image_internal_format,
+                                  size_.width(), size_.height(), /*border=*/0,
+                                  pixel_data.size(), pixel_data.data());
+  } else {
+    ScopedUnpackState scoped_unpack_state(!pixel_data.empty());
+    gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter);
+    api->glTexImage2DFn(
+        format_desc_.target, /*level=*/0, format_desc_.image_internal_format,
+        size_.width(), size_.height(), /*border=*/0,
+        format_info.adjusted_format, format_desc_.data_type, pixel_data.data());
+  }
+
+  if (!is_passthrough_) {
+    // Must be set after initial pixel upload.
+    texture_->SetCompatibilitySwizzle(format_info.swizzle);
+  }
+
+  if (!debug_label.empty()) {
+    api->glObjectLabelFn(GL_TEXTURE, GetServiceId(), -1, debug_label.c_str());
+  }
+}
+
+bool GLTextureHolder::UploadFromMemory(const SkPixmap& pixmap) {
+  const GLuint texture_id = GetServiceId();
+  const GLenum gl_format = format_desc_.data_format;
+  const GLenum gl_type = format_desc_.data_type;
+  const GLenum gl_target = format_desc_.target;
+
+  // Actual stride of the given pixmap, not necessarily with the expected
+  // alignment, or equal to expected stride.
+  const size_t pixmap_stride = pixmap.rowBytes();
+  const size_t expected_stride = pixmap.info().minRowBytes64();
+  const GLuint gl_unpack_alignment = pixmap.info().bytesPerPixel();
+  DCHECK_GE(pixmap_stride, expected_stride);
+  DCHECK_EQ(expected_stride % gl_unpack_alignment, 0u);
+
+  GLuint gl_unpack_row_length = 0;
+  std::vector<uint8_t> repacked_data;
+  if (format_ == viz::BGRX_8888 || format_ == viz::RGBX_8888) {
+    DCHECK_EQ(gl_format, static_cast<GLenum>(GL_RGB));
+    // BGRX and RGBX data is uploaded as GL_RGB. Repack from 4 to 3 bytes per
+    // pixel.
+    repacked_data =
+        RepackPixelDataAsRgb(size_, pixmap, format_ == viz::BGRX_8888);
+  } else if (pixmap_stride != expected_stride) {
+    if (SupportsUnpackSubimage()) {
+      // Use GL_UNPACK_ROW_LENGTH to skip data past end of each row on upload.
+      gl_unpack_row_length = pixmap_stride / gl_unpack_alignment;
+    } else {
+      // If GL_UNPACK_ROW_LENGTH isn't supported then repack pixels with the
+      // expected stride.
+      repacked_data = RepackPixelDataWithStride(size_, pixmap, expected_stride);
+    }
+  }
+
+  // TODO(kylechar): Create ScopedProgressReporter for duration of
+  // glTexSubImage2D.
+
+  gl::ScopedTextureBinder scoped_texture_binder(gl_target, texture_id);
+  ScopedUnpackState scoped_unpack_state(
+      /*uploading_data=*/true, gl_unpack_row_length, gl_unpack_alignment);
+
+  const void* pixels =
+      !repacked_data.empty() ? repacked_data.data() : pixmap.addr();
+  gl::GLApi* api = gl::g_current_gl_context;
+  api->glTexSubImage2DFn(gl_target, /*level=*/0, 0, 0, size_.width(),
+                         size_.height(), gl_format, gl_type, pixels);
+  DCHECK_EQ(api->glGetErrorFn(), static_cast<GLenum>(GL_NO_ERROR));
+
+  return true;
+}
+
+bool GLTextureHolder::ReadbackToMemory(SkPixmap& pixmap) {
+  const GLuint texture_id = GetServiceId();
+  GLenum gl_format = format_desc_.data_format;
+  GLenum gl_type = format_desc_.data_type;
+
+  if (format_ == viz::BGRX_8888 || format_ == viz::RGBX_8888) {
+    DCHECK_EQ(gl_format, static_cast<GLenum>(GL_RGB));
+    DCHECK_EQ(gl_type, static_cast<GLenum>(GL_UNSIGNED_BYTE));
+
+    // Always readback RGBX/BGRX as RGBA/BGRA instead of RGB to avoid needing a
+    // temporary buffer.
+    gl_format = format_ == viz::BGRX_8888 ? GL_BGRA_EXT : GL_RGBA;
+  }
+
+  gl::GLApi* api = gl::g_current_gl_context;
+  GLuint framebuffer;
+  api->glGenFramebuffersEXTFn(1, &framebuffer);
+  gl::ScopedFramebufferBinder scoped_framebuffer_binder(framebuffer);
+  // This uses GL_FRAMEBUFFER instead of GL_READ_FRAMEBUFFER as the target for
+  // GLES2 compatibility.
+  api->glFramebufferTexture2DEXTFn(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                                   GL_TEXTURE_2D, texture_id, /*level=*/0);
+  DCHECK_EQ(api->glCheckFramebufferStatusEXTFn(GL_FRAMEBUFFER),
+            static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE));
+
+  bool needs_rb_swizzle = false;
+
+  // GL_RGBA + GL_UNSIGNED_BYTE are always supported. Otherwise there is a
+  // preferred format + type that can be queried and is based on what is bound
+  // to GL_READ_FRAMEBUFFER.
+  if (gl_format != GL_RGBA || gl_type != GL_UNSIGNED_BYTE) {
+    GLint preferred_format = 0;
+    api->glGetIntegervFn(GL_IMPLEMENTATION_COLOR_READ_FORMAT,
+                         &preferred_format);
+    GLint preferred_type = 0;
+    api->glGetIntegervFn(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
+
+    if (gl_format != static_cast<GLenum>(preferred_format) ||
+        gl_type != static_cast<GLenum>(preferred_type)) {
+      if (format_ == viz::BGRA_8888 || format_ == viz::BGRX_8888) {
+        DCHECK_EQ(gl_format, static_cast<GLenum>(GL_BGRA_EXT));
+        DCHECK_EQ(gl_type, static_cast<GLenum>(GL_UNSIGNED_BYTE));
+
+        // If BGRA readback isn't support then use RGBA and swizzle.
+        gl_format = GL_RGBA;
+        needs_rb_swizzle = true;
+      } else {
+        DLOG(ERROR) << viz::SharedImageFormat::SinglePlane(format_).ToString()
+                    << " is not supported by glReadPixels()";
+        return false;
+      }
+    }
+  }
+
+  const size_t pixmap_stride = pixmap.rowBytes();
+  const size_t expected_stride = pixmap.info().minRowBytes64();
+  const GLuint gl_pack_alignment = pixmap.info().bytesPerPixel();
+  DCHECK_GE(pixmap_stride, expected_stride);
+  DCHECK_EQ(expected_stride % gl_pack_alignment, 0u);
+
+  std::vector<uint8_t> unpack_buffer;
+  GLuint gl_pack_row_length = 0;
+  if (pixmap_stride != expected_stride) {
+    if (SupportsPackSubimage()) {
+      // Use GL_PACK_ROW_LENGTH to avoid temporary buffer.
+      gl_pack_row_length = pixmap_stride / gl_pack_alignment;
+    } else {
+      // If GL_PACK_ROW_LENGTH isn't supported then readback to a temporary
+      // buffer with expected stride.
+      unpack_buffer = std::vector<uint8_t>(expected_stride * size_.height());
+    }
+  }
+
+  // TODO(kylechar): Create ScopedProgressReporter for duration of
+  // glReadPixels.
+
+  ScopedPackState scoped_pack_state(gl_pack_row_length, gl_pack_alignment);
+
+  void* pixels =
+      !unpack_buffer.empty() ? unpack_buffer.data() : pixmap.writable_addr();
+  api->glReadPixelsFn(0, 0, size_.width(), size_.height(), gl_format, gl_type,
+                      pixels);
+  DCHECK_EQ(api->glGetErrorFn(), static_cast<GLenum>(GL_NO_ERROR));
+
+  api->glDeleteFramebuffersEXTFn(1, &framebuffer);
+
+  if (!unpack_buffer.empty()) {
+    DCHECK_GT(pixmap_stride, expected_stride);
+    UnpackPixelDataWithStride(size_, unpack_buffer, expected_stride, pixmap);
+  }
+
+  if (needs_rb_swizzle) {
+    SwizzleRedAndBlue(pixmap);
+  }
+
+  return true;
+}
+
+sk_sp<SkPromiseImageTexture> GLTextureHolder::GetPromiseImage(
+    SharedContextState* context_state) {
+  GrBackendTexture backend_texture;
+  GetGrBackendTexture(context_state->feature_info(), format_desc_.target, size_,
+                      GetServiceId(), format_desc_.storage_internal_format,
+                      context_state->gr_context()->threadSafeProxy(),
+                      &backend_texture);
+  return SkPromiseImageTexture::Make(backend_texture);
+}
+
+gfx::Rect GLTextureHolder::GetClearedRect() const {
+  DCHECK(!is_passthrough_);
+  return texture_->GetLevelClearedRect(format_desc_.target, 0);
+}
+
+void GLTextureHolder::SetClearedRect(const gfx::Rect& cleared_rect) {
+  DCHECK(!is_passthrough_);
+  texture_->SetLevelClearedRect(format_desc_.target, 0, cleared_rect);
+}
+
+void GLTextureHolder::SetContextLost() {
+  context_lost_ = true;
+}
+
+}  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_holder.h b/gpu/command_buffer/service/shared_image/gl_texture_holder.h
new file mode 100644
index 0000000..e34ef03
--- /dev/null
+++ b/gpu/command_buffer/service/shared_image/gl_texture_holder.h
@@ -0,0 +1,74 @@
+// 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 GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_GL_TEXTURE_HOLDER_H_
+#define GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_GL_TEXTURE_HOLDER_H_
+
+#include "gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.h"
+#include "gpu/command_buffer/service/shared_image/shared_image_format_utils.h"
+
+namespace gpu {
+
+class SharedContextState;
+
+// Helper class that holds a single GL texture, that works with either
+// validating or passthrough command decoder.
+class GLTextureHolder {
+ public:
+  GLTextureHolder(viz::ResourceFormat format,
+                  const gfx::Size& size,
+                  bool is_passthrough);
+  GLTextureHolder(GLTextureHolder&& other);
+  GLTextureHolder& operator=(GLTextureHolder&& other);
+  ~GLTextureHolder();
+
+  gles2::Texture* texture() { return texture_; }
+  gles2::TexturePassthrough* passthrough_texture() {
+    return passthrough_texture_.get();
+  }
+
+  // Returns the service GL texture id.
+  GLuint GetServiceId() const;
+
+  void Initialize(const GLCommonImageBackingFactory::FormatInfo& format_info,
+                  bool framebuffer_attachment_angle,
+                  base::span<const uint8_t> pixel_data,
+                  gl::ProgressReporter* progress_reporter,
+                  const std::string& debug_label);
+
+  // Uploads pixels from `pixmap` to GL texture.
+  bool UploadFromMemory(const SkPixmap& pixmap);
+
+  // Readback pixels from GL texture to `pixmap`.
+  bool ReadbackToMemory(SkPixmap& pixmap);
+
+  // Returns a promise image for the GL texture.
+  sk_sp<SkPromiseImageTexture> GetPromiseImage(
+      SharedContextState* context_state);
+
+  // Gets/sets cleared rect from gles2::Texture. Only valid to call with
+  // validating command decoder.
+  gfx::Rect GetClearedRect() const;
+  void SetClearedRect(const gfx::Rect& cleared_rect);
+
+  void SetContextLost();
+
+ private:
+  // TODO(kylechar): ResourceFormat isn't the ideal type to represent the format
+  // here since it's really a single plane of SharedImageFormat. This could
+  // potentially be SharedImageFormat + plane_index or some other type entirely.
+  // Figure out the right type to use instead and replace it.
+  viz::ResourceFormat format_;
+  gfx::Size size_;
+  bool is_passthrough_;
+  bool context_lost_ = false;
+
+  gles2::Texture* texture_ = nullptr;
+  scoped_refptr<gles2::TexturePassthrough> passthrough_texture_;
+  GLFormatDesc format_desc_;
+};
+
+}  // namespace gpu
+
+#endif  // GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_GL_TEXTURE_HOLDER_H_
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing.cc b/gpu/command_buffer/service/shared_image/gl_texture_image_backing.cc
index e2e70e4c..054e4d1 100644
--- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing.cc
@@ -9,19 +9,11 @@
 #include <string>
 #include <utility>
 
-#include "base/bits.h"
-#include "base/feature_list.h"
 #include "build/build_config.h"
 #include "components/viz/common/resources/resource_format.h"
-#include "components/viz/common/resources/resource_sizes.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
-#include "gpu/command_buffer/common/shared_image_trace_utils.h"
 #include "gpu/command_buffer/common/shared_image_usage.h"
-#include "gpu/command_buffer/service/context_state.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
-#include "gpu/command_buffer/service/service_utils.h"
 #include "gpu/command_buffer/service/shared_context_state.h"
-#include "gpu/command_buffer/service/shared_image/gl_repack_utils.h"
 #include "gpu/command_buffer/service/shared_image/gl_texture_common_representations.h"
 #include "gpu/command_buffer/service/shared_image/gl_texture_image_backing_helper.h"
 #include "gpu/command_buffer/service/shared_image/shared_image_backing.h"
@@ -29,28 +21,12 @@
 #include "gpu/command_buffer/service/shared_image/shared_image_format_utils.h"
 #include "gpu/command_buffer/service/shared_image/shared_image_representation.h"
 #include "gpu/command_buffer/service/skia_utils.h"
-#include "gpu/config/gpu_finch_features.h"
-#include "gpu/config/gpu_preferences.h"
 #include "third_party/skia/include/core/SkPromiseImageTexture.h"
-#include "third_party/skia/include/gpu/GrContextThreadSafeProxy.h"
-#include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/color_space.h"
 #include "ui/gfx/geometry/size.h"
-#include "ui/gl/buffer_format_utils.h"
-#include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_fence.h"
-#include "ui/gl/gl_gl_api_implementation.h"
+#include "ui/gl/buildflags.h"
 #include "ui/gl/gl_image_native_pixmap.h"
-#include "ui/gl/gl_implementation.h"
-#include "ui/gl/gl_version_info.h"
-#include "ui/gl/scoped_binders.h"
 #include "ui/gl/scoped_make_current.h"
-#include "ui/gl/shared_gl_fence_egl.h"
-#include "ui/gl/trace_util.h"
-
-#if BUILDFLAG(IS_MAC)
-#include "gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.h"
-#endif
 
 #if BUILDFLAG(USE_DAWN) && BUILDFLAG(DAWN_ENABLE_BACKEND_OPENGLES)
 #include "gpu/command_buffer/service/shared_image/dawn_egl_image_representation.h"
@@ -58,35 +34,14 @@
 
 namespace gpu {
 
-namespace {
-
-// This value can't be cached as it may change for different contexts.
-bool SupportsUnpackSubimage() {
-  return gl::g_current_gl_version->is_es3_capable ||
-         gl::g_current_gl_driver->ext.b_GL_EXT_unpack_subimage;
-}
-
-// This value can't be cached as it may change for different contexts.
-bool SupportsPackSubimage() {
-#if BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_X86_FAMILY)
-  // GL_PACK_ROW_LENGTH is broken in the Android emulator. glReadPixels()
-  // modifies bytes between the last pixel in a row and the end of the stride
-  // for that row.
-  return false;
-#else
-  return gl::g_current_gl_version->is_es3_capable;
-#endif
-}
-
-}  // anonymous namespace
-
 ///////////////////////////////////////////////////////////////////////////////
 // GLTextureImageBacking
 
 bool GLTextureImageBacking::SupportsPixelReadbackWithFormat(
     viz::SharedImageFormat format) {
-  if (!format.is_single_plane())
+  if (!format.is_single_plane()) {
     return false;
+  }
 
   switch (format.resource_format()) {
     case viz::ResourceFormat::RGBA_8888:
@@ -103,8 +58,9 @@
 
 bool GLTextureImageBacking::SupportsPixelUploadWithFormat(
     viz::SharedImageFormat format) {
-  if (!format.is_single_plane())
+  if (!format.is_single_plane()) {
     return false;
+  }
 
   switch (format.resource_format()) {
     case viz::ResourceFormat::RGBA_8888:
@@ -150,35 +106,24 @@
                                       alpha_type,
                                       usage,
                                       format.EstimatedSizeInBytes(size),
-                                      false /* is_thread_safe */),
-      is_passthrough_(is_passthrough) {}
+                                      /*is_thread_safe=*/false),
+      is_passthrough_(is_passthrough),
+      texture_(format.resource_format(), size, is_passthrough) {}
 
 GLTextureImageBacking::~GLTextureImageBacking() {
-  if (IsPassthrough()) {
-    if (passthrough_texture_) {
-      if (!have_context())
-        passthrough_texture_->MarkContextLost();
-      passthrough_texture_.reset();
-    }
-  } else {
-    if (texture_) {
-      texture_->RemoveLightweightRef(have_context());
-      texture_ = nullptr;
-    }
+  if (!have_context()) {
+    texture_.SetContextLost();
   }
 }
 
-GLuint GLTextureImageBacking::GetGLServiceId() const {
-  return texture_ ? texture_->service_id() : passthrough_texture_->service_id();
-}
-
 SharedImageBackingType GLTextureImageBacking::GetType() const {
   return SharedImageBackingType::kGLTexture;
 }
 
 gfx::Rect GLTextureImageBacking::ClearedRect() const {
-  if (!IsPassthrough())
-    return texture_->GetLevelClearedRect(texture_->target(), 0);
+  if (!IsPassthrough()) {
+    return texture_.GetClearedRect();
+  }
 
   // Use shared image based tracking for passthrough, because we don't always
   // use angle robust initialization.
@@ -187,7 +132,7 @@
 
 void GLTextureImageBacking::SetClearedRect(const gfx::Rect& cleared_rect) {
   if (!IsPassthrough()) {
-    texture_->SetLevelClearedRect(texture_->target(), 0, cleared_rect);
+    texture_.SetClearedRect(cleared_rect);
     return;
   }
 
@@ -201,58 +146,10 @@
 bool GLTextureImageBacking::UploadFromMemory(
     const std::vector<SkPixmap>& pixmaps) {
   DCHECK_EQ(pixmaps.size(), 1u);
-  auto& pixmap = pixmaps[0];
-
   DCHECK(SupportsPixelUploadWithFormat(format()));
   DCHECK(gl::GLContext::GetCurrent());
 
-  auto resource_format = format().resource_format();
-
-  const GLuint texture_id = GetGLServiceId();
-  const GLenum gl_format = format_desc_.data_format;
-  const GLenum gl_type = format_desc_.data_type;
-  const GLenum gl_target = format_desc_.target;
-
-  // Actual stride of the given pixmap, not necessarily with the expected
-  // alignment, or equal to expected stride.
-  const size_t pixmap_stride = pixmap.rowBytes();
-  const size_t expected_stride = pixmap.info().minRowBytes64();
-  const GLuint gl_unpack_alignment = pixmap.info().bytesPerPixel();
-  DCHECK_GE(pixmap_stride, expected_stride);
-  DCHECK_EQ(expected_stride % gl_unpack_alignment, 0u);
-
-  GLuint gl_unpack_row_length = 0;
-  std::vector<uint8_t> repacked_data;
-  if (resource_format == viz::BGRX_8888 || resource_format == viz::RGBX_8888) {
-    DCHECK_EQ(gl_format, static_cast<GLenum>(GL_RGB));
-    // BGRX and RGBX data is uploaded as GL_RGB. Repack from 4 to 3 bytes per
-    // pixel.
-    repacked_data =
-        RepackPixelDataAsRgb(size(), pixmap, resource_format == viz::BGRX_8888);
-  } else if (pixmap_stride != expected_stride) {
-    if (SupportsUnpackSubimage()) {
-      // Use GL_UNPACK_ROW_LENGTH to skip data past end of each row on upload.
-      gl_unpack_row_length = pixmap_stride / gl_unpack_alignment;
-    } else {
-      // If GL_UNPACK_ROW_LENGTH isn't supported then repack pixels with the
-      // expected stride.
-      repacked_data =
-          RepackPixelDataWithStride(size(), pixmap, expected_stride);
-    }
-  }
-
-  gl::ScopedTextureBinder scoped_texture_binder(gl_target, texture_id);
-  ScopedUnpackState scoped_unpack_state(
-      /*uploading_data=*/true, gl_unpack_row_length, gl_unpack_alignment);
-
-  const void* pixels =
-      !repacked_data.empty() ? repacked_data.data() : pixmap.addr();
-  gl::GLApi* api = gl::g_current_gl_context;
-  api->glTexSubImage2DFn(gl_target, /*level=*/0, 0, 0, size().width(),
-                         size().height(), gl_format, gl_type, pixels);
-  DCHECK_EQ(api->glGetErrorFn(), static_cast<GLenum>(GL_NO_ERROR));
-
-  return true;
+  return texture_.UploadFromMemory(pixmaps[0]);
 }
 
 bool GLTextureImageBacking::ReadbackToMemory(SkPixmap& pixmap) {
@@ -261,111 +158,18 @@
   // TODO(kylechar): Ideally there would be a usage that stated readback was
   // required so support could be verified at creation time and then asserted
   // here instead.
-  if (!SupportsPixelReadbackWithFormat(format()))
+  if (!SupportsPixelReadbackWithFormat(format())) {
     return false;
-
-  viz::ResourceFormat resource_format = format().resource_format();
-
-  const GLuint texture_id = GetGLServiceId();
-  GLenum gl_format = format_desc_.data_format;
-  GLenum gl_type = format_desc_.data_type;
-
-  if (resource_format == viz::BGRX_8888 || resource_format == viz::RGBX_8888) {
-    DCHECK_EQ(gl_format, static_cast<GLenum>(GL_RGB));
-    DCHECK_EQ(gl_type, static_cast<GLenum>(GL_UNSIGNED_BYTE));
-
-    // Always readback RGBX/BGRX as RGBA/BGRA instead of RGB to avoid needing a
-    // temporary buffer.
-    gl_format = resource_format == viz::BGRX_8888 ? GL_BGRA_EXT : GL_RGBA;
   }
 
-  gl::GLApi* api = gl::g_current_gl_context;
-  GLuint framebuffer;
-  api->glGenFramebuffersEXTFn(1, &framebuffer);
-  gl::ScopedFramebufferBinder scoped_framebuffer_binder(framebuffer);
-  // This uses GL_FRAMEBUFFER instead of GL_READ_FRAMEBUFFER as the target for
-  // GLES2 compatibility.
-  api->glFramebufferTexture2DEXTFn(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                                   GL_TEXTURE_2D, texture_id, /*level=*/0);
-  DCHECK_EQ(api->glCheckFramebufferStatusEXTFn(GL_FRAMEBUFFER),
-            static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE));
-
-  bool needs_rb_swizzle = false;
-
-  // GL_RGBA + GL_UNSIGNED_BYTE are always supported. Otherwise there is a
-  // preferred format + type that can be queried and is based on what is bound
-  // to GL_READ_FRAMEBUFFER.
-  if (gl_format != GL_RGBA || gl_type != GL_UNSIGNED_BYTE) {
-    GLint preferred_format = 0;
-    api->glGetIntegervFn(GL_IMPLEMENTATION_COLOR_READ_FORMAT,
-                         &preferred_format);
-    GLint preferred_type = 0;
-    api->glGetIntegervFn(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
-
-    if (gl_format != static_cast<GLenum>(preferred_format) ||
-        gl_type != static_cast<GLenum>(preferred_type)) {
-      if (resource_format == viz::BGRA_8888 ||
-          resource_format == viz::BGRX_8888) {
-        DCHECK_EQ(gl_format, static_cast<GLenum>(GL_BGRA_EXT));
-        DCHECK_EQ(gl_type, static_cast<GLenum>(GL_UNSIGNED_BYTE));
-
-        // If BGRA readback isn't support then use RGBA and swizzle.
-        gl_format = GL_RGBA;
-        needs_rb_swizzle = true;
-      } else {
-        DLOG(ERROR) << format().ToString()
-                    << " is not supported by glReadPixels()";
-        return false;
-      }
-    }
-  }
-
-  const size_t pixmap_stride = pixmap.rowBytes();
-  const size_t expected_stride = pixmap.info().minRowBytes64();
-  const GLuint gl_pack_alignment = pixmap.info().bytesPerPixel();
-  DCHECK_GE(pixmap_stride, expected_stride);
-  DCHECK_EQ(expected_stride % gl_pack_alignment, 0u);
-
-  std::vector<uint8_t> unpack_buffer;
-  GLuint gl_pack_row_length = 0;
-  if (pixmap_stride != expected_stride) {
-    if (SupportsPackSubimage()) {
-      // Use GL_PACK_ROW_LENGTH to avoid temporary buffer.
-      gl_pack_row_length = pixmap_stride / gl_pack_alignment;
-    } else {
-      // If GL_PACK_ROW_LENGTH isn't supported then readback to a temporary
-      // buffer with expected stride.
-      unpack_buffer = std::vector<uint8_t>(expected_stride * size().height());
-    }
-  }
-
-  ScopedPackState scoped_pack_state(gl_pack_row_length, gl_pack_alignment);
-
-  void* pixels =
-      !unpack_buffer.empty() ? unpack_buffer.data() : pixmap.writable_addr();
-  api->glReadPixelsFn(0, 0, size().width(), size().height(), gl_format, gl_type,
-                      pixels);
-  DCHECK_EQ(api->glGetErrorFn(), static_cast<GLenum>(GL_NO_ERROR));
-
-  api->glDeleteFramebuffersEXTFn(1, &framebuffer);
-
-  if (!unpack_buffer.empty()) {
-    DCHECK_GT(pixmap_stride, expected_stride);
-    UnpackPixelDataWithStride(size(), unpack_buffer, expected_stride, pixmap);
-  }
-
-  if (needs_rb_swizzle) {
-    SwizzleRedAndBlue(pixmap);
-  }
-
-  return true;
+  return texture_.ReadbackToMemory(pixmap);
 }
 
 std::unique_ptr<GLTextureImageRepresentation>
 GLTextureImageBacking::ProduceGLTexture(SharedImageManager* manager,
                                         MemoryTypeTracker* tracker) {
-  DCHECK(texture_);
-  std::vector<raw_ptr<gles2::Texture>> gl_textures = {texture_};
+  DCHECK(texture_.texture());
+  std::vector<raw_ptr<gles2::Texture>> gl_textures = {texture_.texture()};
   return std::make_unique<GLTextureGLCommonRepresentation>(
       manager, this, nullptr, tracker, std::move(gl_textures));
 }
@@ -373,9 +177,9 @@
 std::unique_ptr<GLTexturePassthroughImageRepresentation>
 GLTextureImageBacking::ProduceGLTexturePassthrough(SharedImageManager* manager,
                                                    MemoryTypeTracker* tracker) {
-  DCHECK(passthrough_texture_);
+  DCHECK(texture_.passthrough_texture());
   std::vector<scoped_refptr<gles2::TexturePassthrough>> gl_textures = {
-      passthrough_texture_};
+      texture_.passthrough_texture()};
   return std::make_unique<GLTexturePassthroughGLCommonRepresentation>(
       manager, this, nullptr, tracker, std::move(gl_textures));
 }
@@ -396,7 +200,7 @@
       ui::ScopedMakeCurrent smc(shared_context_state->context(),
                                 shared_context_state->surface());
       gl_image_native_pixmap_ = gl::GLImageNativePixmap::CreateFromTexture(
-          size(), ToBufferFormat(format()), GetGLServiceId());
+          size(), ToBufferFormat(format()), texture_.GetServiceId());
       if (!gl_image_native_pixmap_) {
         DLOG(ERROR) << "Unable to create a GLImage";
         return nullptr;
@@ -433,12 +237,7 @@
     MemoryTypeTracker* tracker,
     scoped_refptr<SharedContextState> context_state) {
   if (!cached_promise_texture_) {
-    GrBackendTexture backend_texture;
-    GetGrBackendTexture(
-        context_state->feature_info(), format_desc_.target, size(),
-        GetGLServiceId(), format_desc_.storage_internal_format,
-        context_state->gr_context()->threadSafeProxy(), &backend_texture);
-    cached_promise_texture_ = SkPromiseImageTexture::Make(backend_texture);
+    cached_promise_texture_ = texture_.GetPromiseImage(context_state.get());
   }
   std::vector<sk_sp<SkPromiseImageTexture>> promise_textures = {
       cached_promise_texture_};
@@ -449,39 +248,20 @@
 
 void GLTextureImageBacking::InitializeGLTexture(
     const GLCommonImageBackingFactory::FormatInfo& format_info,
-    bool is_cleared,
+    base::span<const uint8_t> pixel_data,
+    gl::ProgressReporter* progress_reporter,
     bool framebuffer_attachment_angle) {
-  format_desc_.target = GL_TEXTURE_2D;
-  format_desc_.data_format = format_info.gl_format;
-  format_desc_.data_type = format_info.gl_type;
-  format_desc_.image_internal_format = format_info.image_internal_format;
-  format_desc_.storage_internal_format = format_info.storage_internal_format;
-
-  GLTextureImageBackingHelper::MakeTextureAndSetParameters(
-      format_desc_.target, /*service_id=*/0, framebuffer_attachment_angle,
-      IsPassthrough() ? &passthrough_texture_ : nullptr,
-      IsPassthrough() ? nullptr : &texture_);
-
-  if (IsPassthrough()) {
-    passthrough_texture_->SetEstimatedSize(GetEstimatedSize());
-    SetClearedRect(is_cleared ? gfx::Rect(size()) : gfx::Rect());
-  } else {
-    // TODO(piman): We pretend the texture was created in an ES2 context, so
-    // that it can be used in other ES2 contexts, and so we have to pass
-    // gl_format as the internal format in the LevelInfo.
-    // https://crbug.com/628064
-    texture_->SetLevelInfo(format_desc_.target, 0, format_desc_.data_format,
-                           size().width(), size().height(), /*depth=*/1, 0,
-                           format_desc_.data_format, format_desc_.data_type,
-                           is_cleared ? gfx::Rect(size()) : gfx::Rect());
-    texture_->SetImmutable(true, format_info.supports_storage);
+  std::string debug_label;
+  if (gl::g_current_gl_driver->ext.b_GL_KHR_debug) {
+    debug_label =
+        "SharedImage_GLTexture" + CreateLabelForSharedImageUsage(usage());
   }
-}
+  texture_.Initialize(format_info, framebuffer_attachment_angle, pixel_data,
+                      progress_reporter, debug_label);
 
-void GLTextureImageBacking::SetCompatibilitySwizzle(
-    const gles2::Texture::CompatibilitySwizzle* swizzle) {
-  if (!IsPassthrough())
-    texture_->SetCompatibilitySwizzle(swizzle);
+  if (!pixel_data.empty()) {
+    SetCleared();
+  }
 }
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing.h b/gpu/command_buffer/service/shared_image/gl_texture_image_backing.h
index 53e556d..461adef 100644
--- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing.h
@@ -6,7 +6,7 @@
 #define GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_GL_TEXTURE_IMAGE_BACKING_H_
 
 #include "gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.h"
-#include "gpu/command_buffer/service/shared_image/shared_image_format_utils.h"
+#include "gpu/command_buffer/service/shared_image/gl_texture_holder.h"
 
 namespace gl {
 class GLImageNativePixmap;
@@ -35,12 +35,9 @@
 
   void InitializeGLTexture(
       const GLCommonImageBackingFactory::FormatInfo& format_info,
-      bool is_cleared,
+      base::span<const uint8_t> pixel_data,
+      gl::ProgressReporter* progress_reporter,
       bool framebuffer_attachment_angle);
-  void SetCompatibilitySwizzle(
-      const gles2::Texture::CompatibilitySwizzle* swizzle);
-
-  GLuint GetGLServiceId() const;
 
  private:
   // SharedImageBacking:
@@ -70,10 +67,7 @@
   bool IsPassthrough() const { return is_passthrough_; }
 
   const bool is_passthrough_;
-  gles2::Texture* texture_ = nullptr;
-  scoped_refptr<gles2::TexturePassthrough> passthrough_texture_;
-
-  GLFormatDesc format_desc_;
+  GLTextureHolder texture_;
 
   sk_sp<SkPromiseImageTexture> cached_promise_texture_;
   scoped_refptr<gl::GLImageNativePixmap> gl_image_native_pixmap_;
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc
index c1551e6..26e948d 100644
--- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc
@@ -8,10 +8,8 @@
 #include <utility>
 
 #include "build/build_config.h"
-#include "components/viz/common/resources/resource_sizes.h"
 #include "gpu/command_buffer/common/mailbox.h"
 #include "gpu/command_buffer/common/shared_image_usage.h"
-#include "gpu/command_buffer/service/service_utils.h"
 #include "gpu/command_buffer/service/shared_image/gl_texture_image_backing.h"
 #include "gpu/command_buffer/service/shared_image/shared_image_format_utils.h"
 #include "gpu/config/gpu_preferences.h"
@@ -21,12 +19,6 @@
 
 namespace gpu {
 
-namespace {
-
-using ScopedRestoreTexture = GLTextureImageBackingHelper::ScopedRestoreTexture;
-
-}  // anonymous namespace
-
 ///////////////////////////////////////////////////////////////////////////////
 // GLTextureImageBackingFactory
 
@@ -179,9 +171,8 @@
     uint32_t usage,
     base::span<const uint8_t> pixel_data) {
   const FormatInfo& format_info = GetFormatInfo(format);
-  GLenum target = GL_TEXTURE_2D;
+  DCHECK(CanCreateSharedImage(size, pixel_data, format_info, GL_TEXTURE_2D));
 
-  const bool is_cleared = !pixel_data.empty();
   const bool for_framebuffer_attachment =
       (usage & (SHARED_IMAGE_USAGE_RASTER |
                 SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT)) != 0;
@@ -191,52 +182,9 @@
   auto result = std::make_unique<GLTextureImageBacking>(
       mailbox, format, size, color_space, surface_origin, alpha_type, usage,
       use_passthrough_);
-  result->InitializeGLTexture(format_info, is_cleared,
+  result->InitializeGLTexture(format_info, pixel_data, progress_reporter_,
                               framebuffer_attachment_angle);
 
-  gl::GLApi* api = gl::g_current_gl_context;
-  ScopedRestoreTexture scoped_restore(api, target);
-  api->glBindTextureFn(target, result->GetGLServiceId());
-
-  if (format_info.supports_storage) {
-    {
-      gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_);
-      api->glTexStorage2DEXTFn(target, 1,
-                               format_info.adjusted_storage_internal_format,
-                               size.width(), size.height());
-    }
-
-    if (!pixel_data.empty()) {
-      ScopedUnpackState scoped_unpack_state(
-          /*uploading_data=*/true);
-      gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_);
-      api->glTexSubImage2DFn(target, 0, 0, 0, size.width(), size.height(),
-                             format_info.adjusted_format, format_info.gl_type,
-                             pixel_data.data());
-    }
-  } else if (format_info.is_compressed) {
-    ScopedUnpackState scoped_unpack_state(!pixel_data.empty());
-    gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_);
-    api->glCompressedTexImage2DFn(target, 0, format_info.image_internal_format,
-                                  size.width(), size.height(), 0,
-                                  pixel_data.size(), pixel_data.data());
-  } else {
-    ScopedUnpackState scoped_unpack_state(!pixel_data.empty());
-    gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_);
-    api->glTexImage2DFn(target, 0, format_info.image_internal_format,
-                        size.width(), size.height(), 0,
-                        format_info.adjusted_format, format_info.gl_type,
-                        pixel_data.data());
-  }
-
-  if (gl::g_current_gl_driver->ext.b_GL_KHR_debug) {
-    const std::string label =
-        "SharedImage_GLTexture" + CreateLabelForSharedImageUsage(usage);
-    api->glObjectLabelFn(GL_TEXTURE, result->GetGLServiceId(), -1,
-                         label.c_str());
-  }
-
-  result->SetCompatibilitySwizzle(format_info.swizzle);
   return std::move(result);
 }
 
diff --git a/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm b/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm
index 0cbc3c5..d30b2f1 100644
--- a/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm
+++ b/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm
@@ -965,7 +965,7 @@
       gfx::BufferFormat buffer_format;
       if (format().is_single_plane()) {
         plane = io_surface_plane_;
-        buffer_format = viz::BufferFormat(format().resource_format());
+        buffer_format = ToBufferFormat(format());
       } else {
         // For multiplanar formats (without external sampler) get planar buffer
         // format.
diff --git a/gpu/command_buffer/service/surface_texture_gl_owner_unittest.cc b/gpu/command_buffer/service/surface_texture_gl_owner_unittest.cc
index 779312e..8b693f9 100644
--- a/gpu/command_buffer/service/surface_texture_gl_owner_unittest.cc
+++ b/gpu/command_buffer/service/surface_texture_gl_owner_unittest.cc
@@ -44,7 +44,7 @@
         /*fallback_to_software_gl=*/false,
         /*disable_gl_drawing=*/false,
         /*init_extensions=*/true,
-        /*system_device_id=*/0);
+        /*gpu_preference=*/gl::GpuPreference::kDefault);
 
     surface_ = new gl::PbufferGLSurfaceEGL(gl::GLSurfaceEGL::GetGLDisplayEGL(),
                                            gfx::Size(320, 240));
diff --git a/gpu/command_buffer/tests/fuzzer_main.cc b/gpu/command_buffer/tests/fuzzer_main.cc
index 6f077011..8328181 100644
--- a/gpu/command_buffer/tests/fuzzer_main.cc
+++ b/gpu/command_buffer/tests/fuzzer_main.cc
@@ -345,7 +345,7 @@
         /*fallback_to_software_gl=*/false,
         /*disable_gl_drawing=*/false,
         /*init_extensions=*/true,
-        /*system_device_id=*/0);
+        /*gpu_preference=*/gl::GpuPreference::kDefault);
     CHECK(display_);
 #elif defined(GPU_FUZZER_USE_STUB)
     gl::GLSurfaceTestSupport::InitializeOneOffWithStubBindings();
diff --git a/gpu/command_buffer/tests/gl_test_utils.cc b/gpu/command_buffer/tests/gl_test_utils.cc
index 686c482..1939d69d 100644
--- a/gpu/command_buffer/tests/gl_test_utils.cc
+++ b/gpu/command_buffer/tests/gl_test_utils.cc
@@ -38,8 +38,9 @@
 gl::GLDisplay* GLTestHelper::InitializeGL(gl::GLImplementation gl_impl) {
   gl::GLDisplay* display = nullptr;
   if (gl_impl == gl::GLImplementation::kGLImplementationNone) {
-    display = gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings=*/true,
-                                                       /*system_device_id=*/0);
+    display = gl::init::InitializeGLNoExtensionsOneOff(
+        /*init_bindings=*/true,
+        /*gpu_preference=*/gl::GpuPreference::kDefault);
   } else {
     if (!gl::init::InitializeStaticGLBindingsImplementation(
             gl::GLImplementationParts(gl_impl),
@@ -50,7 +51,7 @@
         /*fallback_to_software_gl=*/false,
         /*disable_gl_drawing=*/false,
         /*init_extensions=*/false,
-        /*system_device_id=*/0);
+        /*gpu_preference=*/gl::GpuPreference::kDefault);
   }
 
   if (!display)
diff --git a/gpu/config/gpu_util.cc b/gpu/config/gpu_util.cc
index 197c1eb..750f45b 100644
--- a/gpu/config/gpu_util.cc
+++ b/gpu/config/gpu_util.cc
@@ -769,9 +769,9 @@
   gl::GLDisplay* gl_display = nullptr;
   if (gl::GetGLImplementation() == gl::kGLImplementationNone) {
     // Some tests initialize bindings by themselves.
-    gl_display =
-        gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings=*/true,
-                                                 /*system_device_id=*/0);
+    gl_display = gl::init::InitializeGLNoExtensionsOneOff(
+        /*init_bindings=*/true,
+        /*gpu_preference=*/gl::GpuPreference::kDefault);
     if (!gl_display) {
       VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed";
       return nullptr;
diff --git a/gpu/gles2_conform_support/egl/thread_state.cc b/gpu/gles2_conform_support/egl/thread_state.cc
index d9f19f19..55d9032 100644
--- a/gpu/gles2_conform_support/egl/thread_state.cc
+++ b/gpu/gles2_conform_support/egl/thread_state.cc
@@ -89,9 +89,9 @@
 #if BUILDFLAG(IS_OZONE)
       ui::OzonePlatform::InitializeForGPU(ui::OzonePlatform::InitParams());
 #endif
-      gl::GLDisplay* display =
-          gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings=*/true,
-                                                   /*system_device_id=*/0);
+      gl::GLDisplay* display = gl::init::InitializeGLNoExtensionsOneOff(
+          /*init_bindings=*/true,
+          /*gpu_preference=*/gl::GpuPreference::kDefault);
       gpu::GpuFeatureInfo gpu_feature_info;
       if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) {
         gpu::GPUInfo gpu_info;
diff --git a/gpu/ipc/service/gles2_command_buffer_stub.cc b/gpu/ipc/service/gles2_command_buffer_stub.cc
index 14be9e6..a0077eca 100644
--- a/gpu/ipc/service/gles2_command_buffer_stub.cc
+++ b/gpu/ipc/service/gles2_command_buffer_stub.cc
@@ -186,17 +186,13 @@
       gpu_preference == gl::GpuPreference::kNone || force_default_display) {
     gpu_preference = gl::GpuPreference::kDefault;
   }
-  gl::GLDisplay* display = gl::GetDisplay(gpu_preference);
-  DCHECK(display);
 
-  if (!display->IsInitialized()) {
-    gl::GLDisplay* initialized_display =
-        gl::init::InitializeGLOneOffPlatformImplementation(
-            /*fallback_to_software_gl=*/false, /*disable_gl_drawing=*/false,
-            /*init_extensions=*/true,
-            /*system_device_id=*/display->system_device_id());
-    DCHECK_EQ(initialized_display, display);
-  }
+  // We may be requesting a new GPU/display, so get or initialize the display.
+  gl::GLDisplay* display =
+      gl::init::GetOrInitializeGLOneOffPlatformImplementation(
+          /*fallback_to_software_gl=*/false, /*disable_gl_drawing=*/false,
+          /*init_extensions=*/true,
+          /*gpu_preference=*/gpu_preference);
 
   if (offscreen) {
     // Do we want to create an offscreen rendering context suitable
diff --git a/gpu/ipc/service/gpu_init.cc b/gpu/ipc/service/gpu_init.cc
index 16ca4009..f167a83a5 100644
--- a/gpu/ipc/service/gpu_init.cc
+++ b/gpu/ipc/service/gpu_init.cc
@@ -190,8 +190,8 @@
 // GPU picking is only effective with ANGLE/Metal backend on Mac and
 // on Windows with EGL.
 // Returns the default GPU's system_device_id.
-uint64_t SetupGLDisplayManagerEGL(const GPUInfo& gpu_info,
-                                  const GpuFeatureInfo& gpu_feature_info) {
+void SetupGLDisplayManagerEGL(const GPUInfo& gpu_info,
+                              const GpuFeatureInfo& gpu_feature_info) {
   const GPUInfo::GPUDevice* gpu_high_perf =
       gpu_info.GetGpuByPreference(gl::GpuPreference::kHighPerformance);
   const GPUInfo::GPUDevice* gpu_low_power =
@@ -219,26 +219,26 @@
   if (gpu_info.GpuCount() <= 1) {
     gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
                             system_device_id_default);
-    return system_device_id_default;
+    return;
   }
   if (gpu_feature_info.IsWorkaroundEnabled(FORCE_LOW_POWER_GPU) &&
       system_device_id_low_power) {
     gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
                             system_device_id_low_power);
-    return system_device_id_low_power;
+    return;
   }
   if (gpu_feature_info.IsWorkaroundEnabled(FORCE_HIGH_PERFORMANCE_GPU) &&
       system_device_id_high_perf) {
     gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
                             system_device_id_high_perf);
-    return system_device_id_high_perf;
+    return;
   }
   if (gpu_default == gpu_high_perf) {
     // If the default GPU is already the high performance GPU, then it's better
     // for Chrome to always use this GPU.
     gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
                             system_device_id_high_perf);
-    return system_device_id_high_perf;
+    return;
   }
 
   // Chrome uses the default GPU for internal rendering and the high
@@ -247,11 +247,11 @@
   // supported.
   gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
                           system_device_id_default);
-  if (system_device_id_high_perf && features::SupportsEGLDualGPURendering()) {
+  if (system_device_id_high_perf) {
     gl::SetGpuPreferenceEGL(gl::GpuPreference::kHighPerformance,
                             system_device_id_high_perf);
   }
-  return system_device_id_default;
+  return;
 }
 #endif  // USE_EGL && (IS_WIN || IS_MAC)
 
@@ -270,7 +270,6 @@
   // need more context based GPUInfo. In such situations, switching to
   // SwiftShader needs to wait until creating a context.
   bool needs_more_info = true;
-  uint64_t system_device_id = 0;
 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CASTOS)
   needs_more_info = false;
   if (!PopGPUInfoCache(&gpu_info_)) {
@@ -309,7 +308,7 @@
   }
 
 #if defined(USE_EGL) && (BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC))
-  system_device_id = SetupGLDisplayManagerEGL(gpu_info_, gpu_feature_info_);
+  SetupGLDisplayManagerEGL(gpu_info_, gpu_feature_info_);
 #endif  // USE_EGL && (IS_WIN || IS_MAC)
 #endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CASTOS)
 
@@ -470,7 +469,7 @@
 #endif
     if (gl::GetGLImplementation() != gl::kGLImplementationDisabled) {
       gl_display = gl::init::InitializeGLNoExtensionsOneOff(
-          /*init_bindings*/ false, system_device_id);
+          /*init_bindings*/ false, gl::GpuPreference::kDefault);
       gl_initialized = !!gl_display;
       if (!gl_initialized) {
         VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed";
@@ -557,7 +556,7 @@
         watchdog_thread_ = nullptr;
         watchdog_init.SetGpuWatchdogPtr(nullptr);
         gl_display = gl::init::InitializeGLNoExtensionsOneOff(
-            /*init_bindings=*/true, system_device_id);
+            /*init_bindings=*/true, gl::GpuPreference::kDefault);
         if (!gl_display) {
           VLOG(1)
               << "gl::init::InitializeGLNoExtensionsOneOff with SwiftShader "
@@ -862,8 +861,9 @@
   gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
       command_line, gpu_feature_info_,
       gpu_preferences_.disable_software_rasterizer, needs_more_info);
-  gl_display = gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings=*/true,
-                                                        /*system_device_id=*/0);
+  gl_display = gl::init::InitializeGLNoExtensionsOneOff(
+      /*init_bindings=*/true,
+      /*gpu_preference=*/gl::GpuPreference::kDefault);
   if (!gl_display) {
     VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed";
     return;
@@ -892,7 +892,8 @@
       SaveHardwareGpuInfoAndGpuFeatureInfo();
       gl::init::ShutdownGL(gl_display, true);
       gl_display = gl::init::InitializeGLNoExtensionsOneOff(
-          /*init_bindings=*/true, /*system_device_id=*/0);
+          /*init_bindings=*/true,
+          /*gpu_preference=*/gl::GpuPreference::kDefault);
       if (!gl_display) {
         VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed "
                 << "with SwiftShader";
@@ -948,7 +949,8 @@
       SaveHardwareGpuInfoAndGpuFeatureInfo();
       gl::init::ShutdownGL(gl_display, true);
       gl_display = gl::init::InitializeGLNoExtensionsOneOff(
-          /*init_bindings=*/true, /*system_device_id=*/0);
+          /*init_bindings=*/true,
+          /*gpu_preference=*/gl::GpuPreference::kDefault);
       if (!gl_display) {
         VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed "
                 << "with SwiftShader";
diff --git a/gpu/perftests/run_all_tests.cc b/gpu/perftests/run_all_tests.cc
index 36ba253..70508ee 100644
--- a/gpu/perftests/run_all_tests.cc
+++ b/gpu/perftests/run_all_tests.cc
@@ -30,7 +30,8 @@
       base::MessagePumpType::IO);
 #endif
 
-  CHECK(gl::init::InitializeGLOneOff(/*system_device_id=*/0));
+  CHECK(gl::init::InitializeGLOneOff(
+      /*gpu_preference=*/gl::GpuPreference::kDefault));
   return test_suite->Run();
 }
 
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index 70ffdd8..3feda14 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -22200,7 +22200,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "free_space:standard"
-      dimensions: "os:Ubuntu-18.04"
+      dimensions: "os:Ubuntu-20.04"
       dimensions: "pool:luci.chromium.ci"
       dimensions: "ssd:0"
       exe {
@@ -79818,7 +79818,7 @@
       dimensions: "builderless:1"
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
-      dimensions: "os:Ubuntu-18.04"
+      dimensions: "os:Ubuntu-20.04"
       dimensions: "pool:luci.chromium.try"
       dimensions: "ssd:0"
       exe {
diff --git a/infra/config/subprojects/chromium/ci/chromium.memory.star b/infra/config/subprojects/chromium/ci/chromium.memory.star
index 610f648b..dbcdb9c 100644
--- a/infra/config/subprojects/chromium/ci/chromium.memory.star
+++ b/infra/config/subprojects/chromium/ci/chromium.memory.star
@@ -539,6 +539,7 @@
         category = "linux|webkit",
         short_name = "msn",
     ),
+    os = os.LINUX_FOCAL,
 )
 
 ci.builder(
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
index 6d39cbb..af100991 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
@@ -312,6 +312,7 @@
     ],
     goma_backend = None,
     reclient_jobs = reclient.jobs.LOW_JOBS_FOR_CQ,
+    os = os.LINUX_FOCAL,
 )
 
 try_.builder(
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 279eb913..ba49f294 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1905,6 +1905,12 @@
       <message name="IDS_IOS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT" desc="Info bar message to save a password. [Length: 60em]">
         Save password?
       </message>
+      <message name="IDS_IOS_PASSWORD_MANAGER_ON_ACCOUNT_SAVE_SUBTITLE" desc="Infobar subtitle to save a password on account. [Length: 60em]">
+        To Google Password Manager for <ph name="EMAIL">$1<ex>johndoe@gmail.com</ex></ph>
+      </message>
+      <message name="IDS_IOS_PASSWORD_MANAGER_LOCAL_SAVE_SUBTITLE" desc="Infobar subtitle to save a password on device. [Length: 60em]">
+        To Google Password Manager on this device
+      </message>
       <message name="IDS_IOS_PASSWORD_MANAGER_SAVE_PASSWORD_TITLE" desc="Infobar title to save a password. [Length: 70em]">
         Save password
       </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PASSWORD_MANAGER_LOCAL_SAVE_SUBTITLE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PASSWORD_MANAGER_LOCAL_SAVE_SUBTITLE.png.sha1
new file mode 100644
index 0000000..2c88714
--- /dev/null
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PASSWORD_MANAGER_LOCAL_SAVE_SUBTITLE.png.sha1
@@ -0,0 +1 @@
+cbc1a68e15ccae895636c42043f2fc2d2b91d416
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PASSWORD_MANAGER_ON_ACCOUNT_SAVE_SUBTITLE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PASSWORD_MANAGER_ON_ACCOUNT_SAVE_SUBTITLE.png.sha1
new file mode 100644
index 0000000..cabd6da
--- /dev/null
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PASSWORD_MANAGER_ON_ACCOUNT_SAVE_SUBTITLE.png.sha1
@@ -0,0 +1 @@
+7208b94687233dbf14e3749422adb8f8b5b2f498
\ No newline at end of file
diff --git a/ios/chrome/browser/overlays/public/infobar_banner/BUILD.gn b/ios/chrome/browser/overlays/public/infobar_banner/BUILD.gn
index 0a1cdfc2..f5eb950d 100644
--- a/ios/chrome/browser/overlays/public/infobar_banner/BUILD.gn
+++ b/ios/chrome/browser/overlays/public/infobar_banner/BUILD.gn
@@ -34,6 +34,7 @@
     "//base",
     "//components/autofill/core/browser",
     "//components/infobars/core",
+    "//components/password_manager/core/common:features",
     "//components/translate/core/browser",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser/infobars",
diff --git a/ios/chrome/browser/overlays/public/infobar_banner/password_infobar_banner_overlay.h b/ios/chrome/browser/overlays/public/infobar_banner/password_infobar_banner_overlay.h
index ecf6f5b..1016a36 100644
--- a/ios/chrome/browser/overlays/public/infobar_banner/password_infobar_banner_overlay.h
+++ b/ios/chrome/browser/overlays/public/infobar_banner/password_infobar_banner_overlay.h
@@ -26,7 +26,9 @@
   NSString* title() const { return title_; }
   // The infobar delegate's subtitle text.
   NSString* subtitle() const { return subtitle_; }
-  // The infobar delegate's accessibility text.
+  // The infobar delegate's accessibility text. This is used when the subtitle
+  // includes a hidden password text. Other than this, it will be null and the
+  // default value of accessibility label will be used.
   NSString* customAccessibilityLabel() const {
     return custom_accessibility_label_;
   }
diff --git a/ios/chrome/browser/overlays/public/infobar_banner/password_infobar_banner_overlay.mm b/ios/chrome/browser/overlays/public/infobar_banner/password_infobar_banner_overlay.mm
index d6fd5611..c55953c 100644
--- a/ios/chrome/browser/overlays/public/infobar_banner/password_infobar_banner_overlay.mm
+++ b/ios/chrome/browser/overlays/public/infobar_banner/password_infobar_banner_overlay.mm
@@ -6,7 +6,9 @@
 
 #import "base/check.h"
 #import "base/strings/sys_string_conversions.h"
+#import "base/strings/utf_string_conversions.h"
 #import "components/infobars/core/infobar.h"
+#import "components/password_manager/core/common/password_manager_features.h"
 #import "ios/chrome/browser/infobars/infobar_ios.h"
 #import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h"
 #import "ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h"
@@ -29,16 +31,28 @@
       IOSChromeSavePasswordInfoBarDelegate::FromInfobarDelegate(
           infobar_->delegate());
   title_ = base::SysUTF16ToNSString(delegate->GetMessageText());
-  NSString* username = delegate->GetUserNameText();
-  NSString* password =
-      [@"" stringByPaddingToLength:delegate->GetPasswordText().length
-                        withString:@"•"
-                   startingAtIndex:0];
-  subtitle_ = [NSString stringWithFormat:@"%@ %@", username, password];
-  custom_accessibility_label_ =
-      [NSString stringWithFormat:@"%@,%@, %@", title_, username,
-                                 l10n_util::GetNSString(
-                                     IDS_IOS_SETTINGS_PASSWORD_HIDDEN_LABEL)];
+  if (base::FeatureList::IsEnabled(
+          password_manager::features::kIOSShowPasswordStorageInSaveInfobar)) {
+    absl::optional<std::string> account_string =
+        delegate->GetAccountToStorePassword();
+    subtitle_ = account_string
+                    ? l10n_util::GetNSStringF(
+                          IDS_IOS_PASSWORD_MANAGER_ON_ACCOUNT_SAVE_SUBTITLE,
+                          base::UTF8ToUTF16(*account_string))
+                    : l10n_util::GetNSString(
+                          IDS_IOS_PASSWORD_MANAGER_LOCAL_SAVE_SUBTITLE);
+  } else {
+    NSString* username = delegate->GetUserNameText();
+    NSString* password =
+        [@"" stringByPaddingToLength:delegate->GetPasswordText().length
+                          withString:@"•"
+                     startingAtIndex:0];
+    subtitle_ = [NSString stringWithFormat:@"%@ %@", username, password];
+    custom_accessibility_label_ =
+        [NSString stringWithFormat:@"%@,%@, %@", title_, username,
+                                   l10n_util::GetNSString(
+                                       IDS_IOS_SETTINGS_PASSWORD_HIDDEN_LABEL)];
+  }
   button_text_ = base::SysUTF16ToNSString(
       delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK));
 }
diff --git a/ios/chrome/browser/overlays/public/infobar_modal/BUILD.gn b/ios/chrome/browser/overlays/public/infobar_modal/BUILD.gn
index 44f57415..24efcd63e 100644
--- a/ios/chrome/browser/overlays/public/infobar_modal/BUILD.gn
+++ b/ios/chrome/browser/overlays/public/infobar_modal/BUILD.gn
@@ -29,6 +29,7 @@
   deps = [
     "//base",
     "//components/autofill/core/browser",
+    "//components/password_manager/core/common:features",
     "//components/translate/core/browser",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser/infobars",
diff --git a/ios/chrome/browser/prefs/browser_prefs.mm b/ios/chrome/browser/prefs/browser_prefs.mm
index 1f876a0..bad0a781 100644
--- a/ios/chrome/browser/prefs/browser_prefs.mm
+++ b/ios/chrome/browser/prefs/browser_prefs.mm
@@ -229,8 +229,6 @@
 
   registry->RegisterDictionaryPref(prefs::kOverflowMenuDestinationUsageHistory,
                                    PrefRegistry::LOSSY_PREF);
-  registry->RegisterListPref(prefs::kOverflowMenuNewDestinations,
-                             PrefRegistry::LOSSY_PREF);
 
   // Preferences related to Enterprise policies.
   registry->RegisterListPref(prefs::kRestrictAccountsToPatterns);
diff --git a/ios/chrome/browser/prefs/pref_names.cc b/ios/chrome/browser/prefs/pref_names.cc
index 73d7606c..f9ad265 100644
--- a/ios/chrome/browser/prefs/pref_names.cc
+++ b/ios/chrome/browser/prefs/pref_names.cc
@@ -162,10 +162,6 @@
 const char kOverflowMenuDestinationUsageHistory[] =
     "overflow_menu.destination_usage_history";
 
-// List preference which tracks new destinations added to the overflow menu
-// carousel.
-const char kOverflowMenuNewDestinations[] = "overflow_menu.new_destinations";
-
 // Boolean that is true when Suggest support is enabled.
 const char kSearchSuggestEnabled[] = "search.suggest_enabled";
 
diff --git a/ios/chrome/browser/prefs/pref_names.h b/ios/chrome/browser/prefs/pref_names.h
index b7077db..f611833f 100644
--- a/ios/chrome/browser/prefs/pref_names.h
+++ b/ios/chrome/browser/prefs/pref_names.h
@@ -46,7 +46,6 @@
 extern const char kNTPFollowingFeedSortType[];
 extern const char kDefaultFollowingFeedSortTypeChanged[];
 extern const char kOverflowMenuDestinationUsageHistory[];
-extern const char kOverflowMenuNewDestinations[];
 extern const char kPrintingEnabled[];
 extern const char kSearchSuggestEnabled[];
 extern const char kTrackPricesOnTabsEnabled[];
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/password_infobar_banner_overlay_mediator.mm b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/password_infobar_banner_overlay_mediator.mm
index e6100e1..383b1e05 100644
--- a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/password_infobar_banner_overlay_mediator.mm
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/password_infobar_banner_overlay_mediator.mm
@@ -65,7 +65,9 @@
   NSString* title = config->title();
   NSString* subtitle = config->subtitle();
   NSString* bannerAccessibilityLabel = config->customAccessibilityLabel();
-  [self.consumer setBannerAccessibilityLabel:bannerAccessibilityLabel];
+  if (bannerAccessibilityLabel) {
+    [self.consumer setBannerAccessibilityLabel:bannerAccessibilityLabel];
+  }
   [self.consumer setButtonText:config->button_text()];
   [self.consumer setIconImage:[self iconImageWithConfig:config]];
   [self.consumer setPresentsModal:YES];
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/password_infobar_banner_overlay_mediator_unittest.mm b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/password_infobar_banner_overlay_mediator_unittest.mm
index fb9eba25..f6a1f3c 100644
--- a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/password_infobar_banner_overlay_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/password_infobar_banner_overlay_mediator_unittest.mm
@@ -11,6 +11,7 @@
 #import "base/strings/utf_string_conversions.h"
 #import "base/test/scoped_feature_list.h"
 #import "components/infobars/core/infobar.h"
+#import "components/password_manager/core/common/password_manager_features.h"
 #import "ios/chrome/browser/infobars/infobar_ios.h"
 #import "ios/chrome/browser/overlays/public/infobar_banner/password_infobar_banner_overlay.h"
 #import "ios/chrome/browser/overlays/public/overlay_request.h"
@@ -24,6 +25,7 @@
 #import "testing/gtest_mac.h"
 #import "testing/platform_test.h"
 #import "ui/base/l10n/l10n_util.h"
+#import "url/gurl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -33,6 +35,7 @@
 // Constants used in tests.
 NSString* const kUsername = @"username";
 NSString* const kPassword = @"12345";
+const char kAccount[] = "foobar@gmail.com";
 }  // namespace
 
 // Test fixture for PasswordInfobarBannerOverlayMediator.
@@ -41,6 +44,10 @@
 // Tests that a PasswordInfobarBannerOverlayMediator correctly sets up its
 // consumer.
 TEST_F(PasswordInfobarBannerOverlayMediatorTest, SetUpConsumer) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndDisableFeature(
+      password_manager::features::kIOSShowPasswordStorageInSaveInfobar);
+
   // Create an InfoBarIOS with a IOSChromeSavePasswordInfoBarDelegate.
   std::unique_ptr<IOSChromeSavePasswordInfoBarDelegate> passed_delegate =
       MockIOSChromeSavePasswordInfoBarDelegate::Create(kUsername, kPassword);
@@ -133,3 +140,69 @@
       CustomSymbolWithPointSize(kPasswordSymbol, kInfobarSymbolPointSize),
       consumer.iconImage);
 }
+
+TEST_F(PasswordInfobarBannerOverlayMediatorTest,
+       SetUpConsumerWithLocalStorage) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(
+      password_manager::features::kIOSShowPasswordStorageInSaveInfobar);
+
+  // Create an InfoBarIOS with a IOSChromeSavePasswordInfoBarDelegate.
+  InfoBarIOS infobar(InfobarType::kInfobarTypePasswordSave,
+                     MockIOSChromeSavePasswordInfoBarDelegate::Create(
+                         kUsername, kPassword, GURL::EmptyGURL(),
+                         /*account_store_password=*/absl::nullopt));
+  // Package the infobar into an OverlayRequest, then create a mediator that
+  // uses this request in order to set up a fake consumer.
+  std::unique_ptr<OverlayRequest> request = OverlayRequest::CreateWithConfig<
+      PasswordInfobarBannerOverlayRequestConfig>(&infobar);
+  PasswordInfobarBannerOverlayMediator* mediator =
+      [[PasswordInfobarBannerOverlayMediator alloc]
+          initWithRequest:request.get()];
+  FakeInfobarBannerConsumer* consumer =
+      [[FakeInfobarBannerConsumer alloc] init];
+  mediator.consumer = consumer;
+
+  // Verify that the infobar was set up properly.
+  EXPECT_NSEQ(l10n_util::GetNSString(IDS_IOS_PASSWORD_MANAGER_SAVE_BUTTON),
+              consumer.buttonText);
+  EXPECT_NSEQ(
+      l10n_util::GetNSString(IDS_IOS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT),
+      consumer.titleText);
+  EXPECT_NSEQ(
+      l10n_util::GetNSString(IDS_IOS_PASSWORD_MANAGER_LOCAL_SAVE_SUBTITLE),
+      consumer.subtitleText);
+}
+
+TEST_F(PasswordInfobarBannerOverlayMediatorTest,
+       SetUpConsumerWithAccountStorage) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(
+      password_manager::features::kIOSShowPasswordStorageInSaveInfobar);
+
+  // Create an InfoBarIOS with a IOSChromeSavePasswordInfoBarDelegate.
+  InfoBarIOS infobar(InfobarType::kInfobarTypePasswordSave,
+                     MockIOSChromeSavePasswordInfoBarDelegate::Create(
+                         kUsername, kPassword, GURL::EmptyGURL(), kAccount));
+  // Package the infobar into an OverlayRequest, then create a mediator that
+  // uses this request in order to set up a fake consumer.
+  std::unique_ptr<OverlayRequest> request = OverlayRequest::CreateWithConfig<
+      PasswordInfobarBannerOverlayRequestConfig>(&infobar);
+  PasswordInfobarBannerOverlayMediator* mediator =
+      [[PasswordInfobarBannerOverlayMediator alloc]
+          initWithRequest:request.get()];
+  FakeInfobarBannerConsumer* consumer =
+      [[FakeInfobarBannerConsumer alloc] init];
+  mediator.consumer = consumer;
+
+  // Verify that the infobar was set up properly.
+  EXPECT_NSEQ(l10n_util::GetNSString(IDS_IOS_PASSWORD_MANAGER_SAVE_BUTTON),
+              consumer.buttonText);
+  EXPECT_NSEQ(
+      l10n_util::GetNSString(IDS_IOS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT),
+      consumer.titleText);
+  EXPECT_NSEQ(
+      l10n_util::GetNSStringF(IDS_IOS_PASSWORD_MANAGER_ON_ACCOUNT_SAVE_SUBTITLE,
+                              base::UTF8ToUTF16(std::string(kAccount))),
+      consumer.subtitleText);
+}
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/BUILD.gn b/ios/chrome/browser/ui/popup_menu/overflow_menu/BUILD.gn
index c4fc07ca..43cbbe5 100644
--- a/ios/chrome/browser/ui/popup_menu/overflow_menu/BUILD.gn
+++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/BUILD.gn
@@ -5,13 +5,11 @@
 import("//build/config/ios/swift_source_set.gni")
 
 source_set("overflow_menu_constants") {
-  configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
+    "overflow_menu_constants.cc",
     "overflow_menu_constants.h",
-    "overflow_menu_constants.mm",
   ]
   deps = [ "//base" ]
-  frameworks = [ "UIKit.framework" ]
 }
 
 source_set("overflow_menu") {
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/BUILD.gn b/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/BUILD.gn
index 7357ec8..1aa82a8 100644
--- a/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/BUILD.gn
+++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/BUILD.gn
@@ -9,7 +9,6 @@
     "//base",
     "//components/prefs",
     "//ios/chrome/browser/prefs:pref_names",
-    "//ios/chrome/browser/ui/popup_menu/overflow_menu:feature_flags",
     "//ios/chrome/browser/ui/popup_menu/overflow_menu:overflow_menu_constants",
     "//ios/chrome/browser/ui/popup_menu/overflow_menu:overflow_menu_swift",
   ]
@@ -21,13 +20,10 @@
   deps = [
     ":destination_usage_history",
     "//base",
-    "//base/test:test_support",
     "//components/prefs",
     "//components/prefs:test_support",
     "//ios/chrome/browser/prefs:pref_names",
-    "//ios/chrome/browser/ui/popup_menu/overflow_menu:feature_flags",
     "//ios/chrome/browser/ui/popup_menu/overflow_menu:overflow_menu_constants",
-    "//ios/chrome/browser/ui/popup_menu/overflow_menu:overflow_menu_swift",
     "//testing/gmock",
     "//testing/gtest",
   ]
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history.h b/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history.h
index ab3854f9..cb0dedd3 100644
--- a/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history.h
+++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history.h
@@ -41,10 +41,6 @@
         (std::vector<overflow_menu::Destination>&)previousRanking
          numAboveFoldDestinations:(int)numAboveFoldDestinations;
 
-// [Publicly exposed for testing purposes only]
-// Fetches the current ranking saved in prefs and returns it.
-- (const base::Value::List*)fetchCurrentRanking;
-
 // Designated initializer. Initializes with `prefService`.
 - (instancetype)initWithPrefService:(PrefService*)prefService
     NS_DESIGNATED_INITIALIZER;
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history.mm b/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history.mm
index f2a2416..996392a 100644
--- a/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history.mm
+++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history.mm
@@ -4,9 +4,7 @@
 
 #import "ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history.h"
 
-#import <algorithm>
 #import <ostream>
-#import <set>
 
 #import "base/ranges/algorithm.h"
 #import "base/strings/string_number_conversions.h"
@@ -15,9 +13,7 @@
 #import "components/prefs/pref_service.h"
 #import "components/prefs/scoped_user_pref_update.h"
 #import "ios/chrome/browser/prefs/pref_names.h"
-#import "ios/chrome/browser/ui/popup_menu/overflow_menu/feature_flags.h"
 #import "ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_constants.h"
-#import "ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_swift.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -29,11 +25,6 @@
 // during the presentation of the overflow menu.
 constexpr int kDataExpirationWindow = 365;  // days (inclusive)
 
-// kNewDestinationsInsertionIndex represents the index new destinations are
-// inserted into the current ranking. Assumes the overflow menu carousel always
-// has at least four items in it.
-constexpr int kNewDestinationsInsertionIndex = 3;
-
 // kRecencyWindow represents the number of days before the present where usage
 // is considered recent.
 constexpr int kRecencyWindow = 7;  // days (inclusive)
@@ -49,9 +40,6 @@
 // The dictionary key used for storing rankings.
 const char kRankingKey[] = "ranking";
 
-// TODO(crbug.com/989694): Remove `kDefaultRanking` below after feature
-// `kSmartSortingPriceTrackingDestination` fully launches.
-
 // The default destinations ranking, based on statistical usage of the old
 // overflow menu.
 const overflow_menu::Destination kDefaultRanking[] = {
@@ -164,21 +152,6 @@
   return vec;
 }
 
-// Converts base::Value::List ranking into std::set ranking.
-std::set<overflow_menu::Destination> Set(const base::Value::List& ranking) {
-  std::set<overflow_menu::Destination> set;
-
-  for (auto&& rank : ranking) {
-    if (!rank.is_string()) {
-      NOTREACHED();
-    }
-
-    set.insert(overflow_menu::DestinationForStringName(rank.GetString()));
-  }
-
-  return set;
-}
-
 // Converts iterable of overflow_menu::Destination `ranking` into
 // base::Value::List ranking.
 template <typename Range>
@@ -192,21 +165,6 @@
   return list;
 }
 
-// Returns the difference between two vectors. Given vectors `x` and `y`,
-// returns all elements present in `x`, but not in `y`.
-template <typename T>
-std::vector<T> FindDiff(std::vector<T> x, std::vector<T> y) {
-  std::vector<T> diff;
-
-  std::sort(x.begin(), x.end());
-  std::sort(y.begin(), y.end());
-
-  std::set_difference(x.begin(), x.end(), y.begin(), y.end(),
-                      std::back_inserter(diff));
-
-  return diff;
-}
-
 }  // namespace
 
 // Tracks destination usage from the new overflow menu and implements a frecency
@@ -297,7 +255,6 @@
 
   const base::Value::Dict& history =
       self.prefService->GetDict(prefs::kOverflowMenuDestinationUsageHistory);
-
   const std::string path = base::NumberToString(TodaysDay()) + "." +
                            overflow_menu::StringNameForDestination(destination);
 
@@ -305,24 +262,11 @@
 
   ScopedDictPrefUpdate update(self.prefService,
                               prefs::kOverflowMenuDestinationUsageHistory);
-
   update->SetByDottedPath(path, numClicks);
 
-  if (IsSmartSortingPriceTrackingDestinationEnabled()) {
-    ScopedListPrefUpdate newDestinationsUpdate(
-        self.prefService, prefs::kOverflowMenuNewDestinations);
-
-    newDestinationsUpdate->EraseValue(
-        base::Value(overflow_menu::StringNameForDestination(destination)));
-  } else {
-    // TODO(crbug.com/989694): Remove this code and surrounding else-check after
-    // feature `kSmartSortingPriceTrackingDestination` fully launches.
-
-    // User's very first time using Smart Sorting.
-    if (history.size() == 0) {
-      [self injectDefaultNumClicksForAllDestinations];
-    }
-  }
+  // User's very first time using Smart Sorting.
+  if (history.size() == 0)
+    [self injectDefaultNumClicksForAllDestinations];
 
   // Calculate new ranking and store to prefs; Calculate the new ranking
   // ahead of time so overflow menu presentation needn't run ranking algorithm
@@ -336,9 +280,6 @@
 
 #pragma mark - Private
 
-// TODO(crbug.com/989694): Remove `injectDefaultNumClicksForAllDestinations`
-// below after feature `kSmartSortingPriceTrackingDestination` fully launches.
-
 // Injects a default number of clicks for all destinations in the history
 // dictonary.
 - (void)injectDefaultNumClicksForAllDestinations {
@@ -366,67 +307,6 @@
   }
 }
 
-// Adds `destinations` to the locally-stored usage history with a
-// calculated number of initial clicks.
-//
-// NOTE: This method skips seeding history for destinations that already exist
-// in the usage history.
-- (void)seedHistoryWithDestinations:
-    (std::vector<overflow_menu::Destination>&)destinations {
-  // Exit early if there's no pref service. May happen during the application
-  // shutdown.
-  if (!self.prefService) {
-    return;
-  }
-
-  DCHECK_GT(kDampening, 1.0);
-  DCHECK_GT(kInitialBufferNumClicks, 1);
-
-  int defaultNumClicks =
-      (kInitialBufferNumClicks - 1) * (kDampening - 1.0) * 100.0;
-
-  std::string today = base::NumberToString(TodaysDay());
-
-  ScopedDictPrefUpdate update(self.prefService,
-                              prefs::kOverflowMenuDestinationUsageHistory);
-
-  const base::Value::Dict& history =
-      self.prefService->GetDict(prefs::kOverflowMenuDestinationUsageHistory);
-
-  const base::Value::Dict flattenedHistory =
-      [self flattenedHistoryWithinWindow:kDataExpirationWindow];
-
-  for (overflow_menu::Destination destination : destinations) {
-    std::string destinationName =
-        overflow_menu::StringNameForDestination(destination);
-
-    // Does not seed history for destinations that already exist in the usage
-    // history.
-    if (!flattenedHistory.Find(destinationName)) {
-      const std::string path = today + "." + destinationName;
-      update->SetByDottedPath(
-          path,
-          history.FindIntByDottedPath(path).value_or(0) + defaultNumClicks);
-    }
-  }
-}
-
-// Updates the locally-stored ranking to `ranking`.
-- (void)updateStoredRanking:(std::vector<overflow_menu::Destination>&)ranking {
-  // Exit early if there's no pref service. May happen during the application
-  // shutdown.
-  if (!self.prefService) {
-    return;
-  }
-
-  ScopedDictPrefUpdate update(self.prefService,
-                              prefs::kOverflowMenuDestinationUsageHistory);
-
-  base::Value::List newRanking = List(ranking);
-
-  update->Set(kRankingKey, std::move(newRanking));
-}
-
 // Delete expired usage data (data older than `kDataExpirationWindow` days) and
 // saves back to prefs. Returns true if expired usage data was found/removed,
 // false otherwise.
@@ -446,9 +326,8 @@
     if (day == kRankingKey)
       continue;
 
-    if (!ValidDay(day, kDataExpirationWindow)) {
+    if (!ValidDay(day, kDataExpirationWindow))
       prunedHistory.Remove(day);
-    }
   }
 
   self.prefService->SetDict(prefs::kOverflowMenuDestinationUsageHistory,
@@ -468,122 +347,12 @@
   return history.FindList(kRankingKey);
 }
 
-// Compares the current list of carousel items to the current ranking.
-//
-// When the carousel has destinations not found in the current ranking, those
-// destinations are considered new. New destinations are inserted into the
-// current ranking starting at `kNewDestinationsInsertionIndex` and seeded with
-// usage history.
-//
-// When the current ranking has destinations not found in carousel, those
-// destinations are considered removed. Removed destinations are removed from
-// the current ranking.
-//
-// This method tracks new and removed destinations via Pref lists.
-- (void)runHistoryDiagnostic:
-    (std::vector<overflow_menu::Destination>&)currentDestinations {
-  // Exit early if there's no pref service. May happen during the application
-  // shutdown.
-  if (!self.prefService) {
-    return;
-  }
-  const base::Value::List* storedRanking = [self fetchCurrentRanking];
-
-  // If `currentRanking` is invalid, this is the user's first time using Smart
-  // Sorting. This means no ranking or usage history exist on the device, yet,
-  // so a ranking and usage history must be created and seeded.
-  if (!storedRanking) {
-    [self updateStoredRanking:currentDestinations];
-    [self seedHistoryWithDestinations:currentDestinations];
-
-    return;
-  }
-
-  std::vector<overflow_menu::Destination> currentRanking =
-      Vector(storedRanking);
-
-  std::vector<overflow_menu::Destination> newDestinations =
-      FindDiff(currentDestinations, currentRanking);
-
-  [self seedHistoryWithDestinations:newDestinations];
-
-  ScopedListPrefUpdate newDestinationsUpdate(
-      self.prefService, prefs::kOverflowMenuNewDestinations);
-
-  // Make other parts of Smart Sorting infrastructure aware of the newly added
-  // destinations. Newly added destinations are those that exist in the
-  // carousel, but don't exist in the current ranking.
-  for (overflow_menu::Destination newDestination : newDestinations) {
-    newDestinationsUpdate->EraseValue(
-        base::Value(overflow_menu::StringNameForDestination(newDestination)));
-    newDestinationsUpdate->Append(
-        base::Value(overflow_menu::StringNameForDestination(newDestination)));
-  }
-
-  std::vector<overflow_menu::Destination> removedDestinations =
-      FindDiff(currentRanking, currentDestinations);
-
-  std::set<overflow_menu::Destination> removed(removedDestinations.begin(),
-                                               removedDestinations.end());
-
-  // Newly-added and newly-removed destinations need to be added to, and removed
-  // from, the current ranking, respectively. This ensures the logic for
-  // detecting returning destinations works in future evaluations.
-  std::vector<overflow_menu::Destination> updatedRanking;
-
-  for (overflow_menu::Destination destination : currentRanking) {
-    if (!removed.count(destination)) {
-      updatedRanking.push_back(destination);
-    }
-  }
-
-  DCHECK_GE(currentDestinations.size(), size_t(4));
-
-  auto pos =
-      updatedRanking.begin() +
-      std::max(0, std::min(kNewDestinationsInsertionIndex,
-                           static_cast<int>(currentDestinations.size()) - 1));
-  updatedRanking.insert(pos, newDestinations.begin(), newDestinations.end());
-
-  [self updateStoredRanking:updatedRanking];
-}
-
 // Fetches the current ranking stored in Chrome Prefs and returns a sorted list
 // of OverflowMenuDestination* which match the ranking.
 - (NSArray<OverflowMenuDestination*>*)generateDestinationsList:
     (NSArray<OverflowMenuDestination*>*)unrankedDestinations {
-  if (IsSmartSortingPriceTrackingDestinationEnabled()) {
-    std::vector<overflow_menu::Destination> destinations;
-
-    for (OverflowMenuDestination* destination : unrankedDestinations) {
-      overflow_menu::Destination currDestination =
-          overflow_menu::DestinationForNSStringName(
-              destination.destinationName);
-
-      destinations.push_back(currDestination);
-    }
-
-    [self runHistoryDiagnostic:destinations];
-
-    NSMutableArray<OverflowMenuDestination*>* carouselItems =
-        [[self destinationList:[self fetchCurrentRanking]
-                       options:unrankedDestinations] mutableCopy];
-
-    std::set<overflow_menu::Destination> newDestinations =
-        Set(self.prefService->GetList(prefs::kOverflowMenuNewDestinations));
-
-    for (OverflowMenuDestination* carouselItem : carouselItems) {
-      if (newDestinations.count(overflow_menu::DestinationForNSStringName(
-              carouselItem.destinationName))) {
-        carouselItem.badge = BadgeTypeNewLabel;
-      }
-    }
-
-    return carouselItems;
-  } else {
-    return [self destinationList:[self fetchCurrentRanking]
-                         options:unrankedDestinations];
-  }
+  return [self destinationList:[self fetchCurrentRanking]
+                       options:unrankedDestinations];
 }
 
 // Runs the ranking algorithm given a `previousRanking`. If `previousRanking` is
@@ -592,13 +361,7 @@
 - (const base::Value::List)calculateNewRanking:
                                (const base::Value::List*)previousRanking
                       numAboveFoldDestinations:(int)numAboveFoldDestinations {
-  if (IsSmartSortingPriceTrackingDestinationEnabled()) {
-    DCHECK_NE(previousRanking, nullptr);
-  }
-
-  // TODO(crbug.com/1405245): Remove if-else check below after feature
-  // `kSmartSortingPriceTrackingDestination` fully launches.
-  if (!IsSmartSortingPriceTrackingDestinationEnabled() && !previousRanking) {
+  if (!previousRanking) {
     return List(kDefaultRanking);
   }
 
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history_unittest.mm b/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history_unittest.mm
index 7508485..7dc7d62 100644
--- a/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history_unittest.mm
+++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history_unittest.mm
@@ -4,16 +4,12 @@
 
 #import "ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history.h"
 #import "base/strings/string_number_conversions.h"
-#import "base/strings/sys_string_conversions.h"
-#import "base/test/scoped_feature_list.h"
 #import "base/time/time.h"
 #import "base/values.h"
 #import "components/prefs/pref_registry_simple.h"
 #import "components/prefs/testing_pref_service.h"
 #import "ios/chrome/browser/prefs/pref_names.h"
-#import "ios/chrome/browser/ui/popup_menu/overflow_menu/feature_flags.h"
 #import "ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_constants.h"
-#import "ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_swift.h"
 #import "testing/platform_test.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -28,42 +24,6 @@
   return (base::Time::Now() - base::Time::UnixEpoch()).InDays();
 }
 
-// Converts base::Value::List* ranking into
-// std::vector<overflow_menu::Destination> ranking.
-std::vector<overflow_menu::Destination> Vector(
-    const base::Value::List* ranking) {
-  std::vector<overflow_menu::Destination> vec;
-
-  if (!ranking) {
-    return vec;
-  }
-
-  for (auto&& rank : *ranking) {
-    if (!rank.is_string()) {
-      NOTREACHED();
-    }
-
-    vec.push_back(overflow_menu::DestinationForStringName(rank.GetString()));
-  }
-
-  return vec;
-}
-
-// Converts NSArray<OverflowMenuDestination*>* list of overflow menu
-// destinations into their std::vector<overflow_menu::Destination> list of
-// destination IDs.
-std::vector<overflow_menu::Destination> Vector(
-    NSArray<OverflowMenuDestination*>* destinations) {
-  std::vector<overflow_menu::Destination> vec;
-
-  for (OverflowMenuDestination* destination in destinations) {
-    vec.push_back(
-        overflow_menu::DestinationForNSStringName(destination.destinationName));
-  }
-
-  return vec;
-}
-
 }  // namespace
 
 class DestinationUsageHistoryTest : public PlatformTest {
@@ -77,26 +37,19 @@
   }
 
   // Creates CreateDestinationUsageHistory with empty pref data.
-  DestinationUsageHistory* CreateDestinationUsageHistory(
-      NSArray<OverflowMenuDestination*>* default_destinations) {
+  DestinationUsageHistory* CreateDestinationUsageHistory() {
     CreatePrefs();
 
     destination_usage_history_ =
         [[DestinationUsageHistory alloc] initWithPrefService:prefs_.get()];
 
-    if (IsSmartSortingPriceTrackingDestinationEnabled()) {
-      [destination_usage_history_
-          generateDestinationsList:default_destinations];
-    }
-
     return destination_usage_history_;
   }
 
   // Creates CreateDestinationUsageHistory with past data and `ranking`.
   DestinationUsageHistory* CreateDestinationUsageHistoryWithData(
       std::vector<overflow_menu::Destination>& ranking,
-      base::Value::Dict& history,
-      NSArray<OverflowMenuDestination*>* default_destinations) {
+      base::Value::Dict& history) {
     base::Value::List prevRanking = RankingAsListValue(ranking);
 
     CreatePrefsWithData(prevRanking, history);
@@ -104,11 +57,6 @@
     destination_usage_history_ =
         [[DestinationUsageHistory alloc] initWithPrefService:prefs_.get()];
 
-    if (IsSmartSortingPriceTrackingDestinationEnabled()) {
-      [destination_usage_history_
-          generateDestinationsList:default_destinations];
-    }
-
     return destination_usage_history_;
   }
 
@@ -117,8 +65,6 @@
     prefs_ = std::make_unique<TestingPrefServiceSimple>();
     prefs_->registry()->RegisterDictionaryPref(
         prefs::kOverflowMenuDestinationUsageHistory, PrefRegistry::LOSSY_PREF);
-    prefs_->registry()->RegisterListPref(prefs::kOverflowMenuNewDestinations,
-                                         PrefRegistry::LOSSY_PREF);
   }
 
   // Helper for CreateDestinationUsageHistoryWithData(), inserts day history
@@ -167,57 +113,6 @@
                          // return here.
   }
 
-  OverflowMenuDestination* CreateOverflowMenuDestination(
-      overflow_menu::Destination destination) {
-    OverflowMenuDestination* result = [[OverflowMenuDestination alloc]
-                   initWithName:@"Foobar"
-                          image:[UIImage
-                                    imageNamed:
-                                        @"overflow_menu_destination_settings"]
-        accessibilityIdentifier:@"Foobar"
-             enterpriseDisabled:NO
-                        handler:^{
-                            // Do nothing
-                        }];
-
-    result.destinationName = base::SysUTF8ToNSString(
-        overflow_menu::StringNameForDestination(destination));
-
-    return result;
-  }
-
-  NSArray<OverflowMenuDestination*>* SampleDestinations() {
-    OverflowMenuDestination* bookmarksDestination =
-        CreateOverflowMenuDestination(overflow_menu::Destination::Bookmarks);
-    OverflowMenuDestination* historyDestination =
-        CreateOverflowMenuDestination(overflow_menu::Destination::History);
-    OverflowMenuDestination* readingListDestination =
-        CreateOverflowMenuDestination(overflow_menu::Destination::ReadingList);
-    OverflowMenuDestination* passwordsDestination =
-        CreateOverflowMenuDestination(overflow_menu::Destination::Passwords);
-    OverflowMenuDestination* downloadsDestination =
-        CreateOverflowMenuDestination(overflow_menu::Destination::Downloads);
-    OverflowMenuDestination* recentTabsDestination =
-        CreateOverflowMenuDestination(overflow_menu::Destination::RecentTabs);
-    OverflowMenuDestination* siteInfoDestination =
-        CreateOverflowMenuDestination(overflow_menu::Destination::SiteInfo);
-    OverflowMenuDestination* settingsDestination =
-        CreateOverflowMenuDestination(overflow_menu::Destination::Settings);
-
-    NSArray<OverflowMenuDestination*>* destinations = @[
-      bookmarksDestination,
-      historyDestination,
-      readingListDestination,
-      passwordsDestination,
-      downloadsDestination,
-      recentTabsDestination,
-      siteInfoDestination,
-      settingsDestination,
-    ];
-
-    return destinations;
-  }
-
   std::unique_ptr<TestingPrefServiceSimple> prefs_;
   DestinationUsageHistory* destination_usage_history_;
   static constexpr int numAboveFoldDestinations = 5;
@@ -227,7 +122,7 @@
 // specified Pref service.
 TEST_F(DestinationUsageHistoryTest, InitWithPrefService) {
   DestinationUsageHistory* destination_usage_history =
-      CreateDestinationUsageHistory(SampleDestinations());
+      CreateDestinationUsageHistory();
 
   PrefService* pref_service = destination_usage_history.prefService;
 
@@ -261,8 +156,7 @@
 
   // Create DestinationUsageHistory.
   DestinationUsageHistory* destination_usage_history =
-      CreateDestinationUsageHistoryWithData(ranking, history,
-                                            SampleDestinations());
+      CreateDestinationUsageHistoryWithData(ranking, history);
 
   // Grab its pref service.
   PrefService* pref_service = destination_usage_history.prefService;
@@ -278,7 +172,7 @@
 // prefService.
 TEST_F(DestinationUsageHistoryTest, DestroysPrefServiceOnDisconnect) {
   DestinationUsageHistory* destination_usage_history =
-      CreateDestinationUsageHistory(SampleDestinations());
+      CreateDestinationUsageHistory();
 
   [destination_usage_history disconnect];
 
@@ -289,7 +183,7 @@
 // Prefs.
 TEST_F(DestinationUsageHistoryTest, HandlesNewDestinationClickAndAddToPrefs) {
   DestinationUsageHistory* destination_usage_history =
-      CreateDestinationUsageHistory(SampleDestinations());
+      CreateDestinationUsageHistory();
 
   // Click bookmarks destination.
   [destination_usage_history
@@ -316,7 +210,7 @@
 // of clicks.
 TEST_F(DestinationUsageHistoryTest, InjectsDefaultNumClicksForAllDestinations) {
   DestinationUsageHistory* destination_usage_history =
-      CreateDestinationUsageHistory(SampleDestinations());
+      CreateDestinationUsageHistory();
 
   // Click bookmarks destination.
   [destination_usage_history
@@ -378,8 +272,7 @@
 
   // Create DestinationUsageHistory.
   DestinationUsageHistory* destination_usage_history =
-      CreateDestinationUsageHistoryWithData(ranking, prefHistory,
-                                            SampleDestinations());
+      CreateDestinationUsageHistoryWithData(ranking, prefHistory);
 
   // Click bookmarks destination.
   [destination_usage_history
@@ -416,8 +309,7 @@
   base::Value::Dict history;
 
   DestinationUsageHistory* destination_usage_history =
-      CreateDestinationUsageHistoryWithData(ranking, history,
-                                            SampleDestinations());
+      CreateDestinationUsageHistoryWithData(ranking, history);
 
   // Click bookmarks Reading List (currently in ranking position 3) five times.
   [destination_usage_history
@@ -477,8 +369,7 @@
   history.Set(base::NumberToString(TodaysDay()), std::move(dayHistory));
 
   DestinationUsageHistory* destination_usage_history =
-      CreateDestinationUsageHistoryWithData(ranking, history,
-                                            SampleDestinations());
+      CreateDestinationUsageHistoryWithData(ranking, history);
 
   // Click Recent Tabs (currently in ranking position 6) once.
   [destination_usage_history
@@ -541,8 +432,7 @@
               std::move(expired_day_history));
 
   DestinationUsageHistory* destination_usage_history =
-      CreateDestinationUsageHistoryWithData(ranking, history,
-                                            SampleDestinations());
+      CreateDestinationUsageHistoryWithData(ranking, history);
 
   // Click destination to trigger ranking algorithm which removes expired data.
   [destination_usage_history
@@ -562,155 +452,3 @@
                                          base::NumberToString(TodaysDay())};
   ASSERT_EQ(expected_keys, seen_keys);
 }
-
-TEST_F(DestinationUsageHistoryTest, InsertsNewDestinationInMiddleOfRanking) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(
-      kSmartSortingPriceTrackingDestination);
-
-  NSArray<OverflowMenuDestination*>* allDestinations = SampleDestinations();
-  NSArray<OverflowMenuDestination*>* currentDestinations = @[
-    allDestinations[0],
-    allDestinations[1],
-    allDestinations[2],
-    allDestinations[3],
-    allDestinations[4],
-    allDestinations[5],
-    allDestinations[6],
-  ];
-
-  // Creates `DestinationUsageHistory` with initial ranking
-  // `currentDestinations`.
-  DestinationUsageHistory* destinationUsageHistory =
-      CreateDestinationUsageHistory(currentDestinations);
-
-  std::vector<overflow_menu::Destination> currentRanking =
-      Vector(currentDestinations);
-  std::vector<overflow_menu::Destination> storedRanking =
-      Vector([destinationUsageHistory fetchCurrentRanking]);
-
-  ASSERT_EQ(currentRanking, storedRanking);
-
-  // Same as `currentDestinations`, but has a new element, `allDestinations[7]`,
-  // inserted starting at position 4 in the carousel (this is the expected
-  // behavior defined by product).
-  NSArray<OverflowMenuDestination*>* updatedDestinations = @[
-    allDestinations[0],
-    allDestinations[1],
-    allDestinations[2],
-    // New destination
-    allDestinations[7],
-    allDestinations[3],
-    allDestinations[4],
-    allDestinations[5],
-    allDestinations[6],
-  ];
-
-  [destinationUsageHistory generateDestinationsList:updatedDestinations];
-
-  std::vector<overflow_menu::Destination> updatedRanking =
-      Vector(updatedDestinations);
-  std::vector<overflow_menu::Destination> updatedStoredRanking =
-      Vector([destinationUsageHistory fetchCurrentRanking]);
-
-  ASSERT_EQ(updatedRanking, updatedStoredRanking);
-}
-
-TEST_F(DestinationUsageHistoryTest, InsertsNewDestinationsInMiddleOfRanking) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(
-      kSmartSortingPriceTrackingDestination);
-
-  NSArray<OverflowMenuDestination*>* allDestinations = SampleDestinations();
-  NSArray<OverflowMenuDestination*>* currentDestinations = @[
-    allDestinations[0],
-    allDestinations[1],
-    allDestinations[2],
-    allDestinations[3],
-    allDestinations[4],
-    allDestinations[5],
-  ];
-
-  // Creates `DestinationUsageHistory` with initial ranking
-  // `currentDestinations`.
-  DestinationUsageHistory* destinationUsageHistory =
-      CreateDestinationUsageHistory(currentDestinations);
-
-  std::vector<overflow_menu::Destination> currentRanking =
-      Vector([destinationUsageHistory fetchCurrentRanking]);
-  std::vector<overflow_menu::Destination> storedRanking =
-      Vector([destinationUsageHistory fetchCurrentRanking]);
-
-  ASSERT_EQ(currentRanking, storedRanking);
-
-  // Same as `currentDestinations`, but has new elements (`allDestinations[6]`
-  // and `allDestinations[7]`) inserted starting at position 4 in the carousel
-  // (this is the expected behavior defined by product).
-  NSArray<OverflowMenuDestination*>* updatedDestinations = @[
-    allDestinations[0],
-    allDestinations[1],
-    allDestinations[2],
-    // New destinations (start)
-    allDestinations[6],
-    allDestinations[7],
-    // New destinations (end)
-    allDestinations[3],
-    allDestinations[4],
-    allDestinations[5],
-  ];
-
-  [destinationUsageHistory generateDestinationsList:updatedDestinations];
-
-  std::vector<overflow_menu::Destination> updatedRanking =
-      Vector(updatedDestinations);
-  std::vector<overflow_menu::Destination> updatedStoredRanking =
-      Vector([destinationUsageHistory fetchCurrentRanking]);
-
-  ASSERT_EQ(updatedRanking, updatedStoredRanking);
-}
-
-TEST_F(DestinationUsageHistoryTest, InsertsAndRemovesNewDestinationsInRanking) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(
-      kSmartSortingPriceTrackingDestination);
-
-  NSArray<OverflowMenuDestination*>* allDestinations = SampleDestinations();
-  NSArray<OverflowMenuDestination*>* currentDestinations = @[
-    allDestinations[0],
-    allDestinations[1],
-    allDestinations[2],
-    allDestinations[3],
-    allDestinations[4],
-    allDestinations[5],
-  ];
-
-  DestinationUsageHistory* destinationUsageHistory =
-      CreateDestinationUsageHistory(currentDestinations);
-
-  std::vector<overflow_menu::Destination> currentRanking =
-      Vector(currentDestinations);
-  std::vector<overflow_menu::Destination> storedRanking =
-      Vector([destinationUsageHistory fetchCurrentRanking]);
-
-  ASSERT_EQ(currentRanking, storedRanking);
-
-  NSArray<OverflowMenuDestination*>* updatedDestinations = @[
-    allDestinations[2],
-    allDestinations[3],
-    allDestinations[4],
-    // New destinations (start)
-    allDestinations[6],
-    allDestinations[7],
-    // New destinations (end)
-    allDestinations[5],
-  ];
-
-  [destinationUsageHistory generateDestinationsList:updatedDestinations];
-
-  std::vector<overflow_menu::Destination> updatedRanking =
-      Vector(updatedDestinations);
-  std::vector<overflow_menu::Destination> updatedStoredRanking =
-      Vector([destinationUsageHistory fetchCurrentRanking]);
-
-  ASSERT_EQ(updatedRanking, updatedStoredRanking);
-}
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_constants.mm b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_constants.cc
similarity index 87%
rename from ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_constants.mm
rename to ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_constants.cc
index 7916c17..d5f5db7 100644
--- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_constants.mm
+++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_constants.cc
@@ -4,14 +4,9 @@
 
 #import "ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_constants.h"
 
-#import "base/metrics/user_metrics.h"
-#import "base/metrics/user_metrics_action.h"
-#import "base/notreached.h"
-#import "base/strings/sys_string_conversions.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
+#include "base/notreached.h"
 
 namespace overflow_menu {
 // WARNING - PLEASE READ: Sadly, we cannot switch over strings in C++, so be
@@ -43,12 +38,6 @@
   }
 }
 
-Destination DestinationForNSStringName(NSString* destination) {
-  std::string name = base::SysNSStringToUTF8(destination);
-
-  return DestinationForStringName(name);
-}
-
 std::string StringNameForDestination(Destination destination) {
   switch (destination) {
     case overflow_menu::Destination::Bookmarks:
@@ -74,12 +63,6 @@
   }
 }
 
-NSString* NSStringNameForDestination(Destination destination) {
-  std::string name = StringNameForDestination(destination);
-
-  return base::SysUTF8ToNSString(name);
-}
-
 void RecordUmaActionForDestination(Destination destination) {
   switch (destination) {
     case Destination::Bookmarks:
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_constants.h b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_constants.h
index 087fbac..2cdf8c7 100644
--- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_constants.h
+++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_constants.h
@@ -5,9 +5,7 @@
 #ifndef IOS_CHROME_BROWSER_UI_POPUP_MENU_OVERFLOW_MENU_OVERFLOW_MENU_CONSTANTS_H_
 #define IOS_CHROME_BROWSER_UI_POPUP_MENU_OVERFLOW_MENU_OVERFLOW_MENU_CONSTANTS_H_
 
-#import <UIKit/UIKit.h>
-
-#import <string>
+#include <string>
 
 namespace overflow_menu {
 enum class Destination {
@@ -27,18 +25,10 @@
 // overflow_menu::Destination enum.
 Destination DestinationForStringName(std::string destination);
 
-// Ingests `destination` NSString* representation and returns corresponding
-// overflow_menu::Destination enum.
-Destination DestinationForNSStringName(NSString* destination);
-
 // Ingests overflow_menu::Destination `destination` and returns its string
 // representation.
 std::string StringNameForDestination(Destination destination);
 
-// Ingests overflow_menu::Destination `destination` and returns its NSString*
-// representation.
-NSString* NSStringNameForDestination(Destination destination);
-
 // Ingests overflow_menu::Destination `destination` and records the
 // corresponding UMA action.
 void RecordUmaActionForDestination(Destination destination);
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
index 67faae2..9f8f828d0 100644
--- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-0f1c42f176fb75b89b2da17565f32ce04b48e263
\ No newline at end of file
+433bbdcb6e8ad36edbad84d7cf378f36b224ac66
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
index c648188..e091d8f 100644
--- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-e95e104c589468bd5fbf5df9a6bbe2e4b9ab5aa5
\ No newline at end of file
+3b2c16e941b0da1422d0d1edecd712205041725f
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
index c5fad13bb..65261cd 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-56df40838bb634bc4cc77cebada2754d27f4a5f6
\ No newline at end of file
+5a2613f87fc4c485f5941ea997b24aa6555583e1
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
index 9e9a6da..60cc475 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-e2011bd4e0b623366b01c02495e407567641865a
\ No newline at end of file
+575e453b23f7fcce7d88516255a36e90ee1392e2
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
index ef615f77..cd97a07 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-afbf6380bc061e332870754123fbe32f89ac7944
\ No newline at end of file
+c45a76390a7b602267589642bd8317a5be2cc547
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
index b76704d..a744be7 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-fdbfe542408ba32e3e60868667712c6ea737cb23
\ No newline at end of file
+873fab19d708247dd2795b23be99e54f9950a611
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
index 15fd9ed..f3645a8 100644
--- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-d871ed1d89df49b056fc10c699a7a07465b73856
\ No newline at end of file
+87b37c52e322fcf9df3fd5faaead971561900347
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
index 3ad84332..ba63ee9 100644
--- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-5e3934544cd1860e3395b69f571c9b05378cd12e
\ No newline at end of file
+97dcfe42d24269e7ed5f86a70bd5a41018cd3f91
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
index 32a7024..ee14aea7 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-3555be02fcdb202b237d051de9202b56aae5b689
\ No newline at end of file
+3a735ddce7381c348019c6f2af542b7216a278e7
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
index 9018c46d8..af2e555 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-486fe6c6e2955fecd4ff175ef827876c494255f3
\ No newline at end of file
+0fb3c47a03a1a103ce468ff31cfb47d57b3151b3
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
index cbb6257e..2491735 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-063209f110cecdc5b6eed0ce2dac41622ca3d5ca
\ No newline at end of file
+1d15129900e04674ffc45fc53c3d52c3c63e963f
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
index a54e4d7a..6dfa96b 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-7152c26ab01d09e1b7fc1f917df0c023229cf64b
\ No newline at end of file
+41a41111d290da339305fe09cb464cdda41d85d2
\ No newline at end of file
diff --git a/media/gpu/android/codec_image_unittest.cc b/media/gpu/android/codec_image_unittest.cc
index 2b7430d0..9ad9c55 100644
--- a/media/gpu/android/codec_image_unittest.cc
+++ b/media/gpu/android/codec_image_unittest.cc
@@ -58,7 +58,7 @@
         /*fallback_to_software_gl=*/false,
         /*disable_gl_drawing=*/false,
         /*init_extensions=*/false,
-        /*system_device_id=*/0);
+        /*gpu_preference=*/gl::GpuPreference::kDefault);
 
     surface_ = new gl::PbufferGLSurfaceEGL(gl::GLSurfaceEGL::GetGLDisplayEGL(),
                                            gfx::Size(320, 240));
diff --git a/media/remoting/BUILD.gn b/media/remoting/BUILD.gn
index c20dcc25..50671ee3 100644
--- a/media/remoting/BUILD.gn
+++ b/media/remoting/BUILD.gn
@@ -17,6 +17,7 @@
   ]
 
   deps = [
+    ":remoting_constants",
     "//base",
     "//media",
     "//media/mojo/common",
diff --git a/media/remoting/remoting_constants.h b/media/remoting/remoting_constants.h
index 42e92bf1..7379001 100644
--- a/media/remoting/remoting_constants.h
+++ b/media/remoting/remoting_constants.h
@@ -12,6 +12,11 @@
 // The URL format is "media-remoting:<id>", e.g. "media-remoting:test".
 constexpr char kRemotingScheme[] = "media-remoting";
 
+// The minimum media element duration that is allowed for media remoting.
+// Frequent switching into and out of media remoting for short-duration media
+// can feel "janky" to the user.
+constexpr double kMinRemotingMediaDurationInSec = 60;
+
 }  // namespace remoting
 }  // namespace media
 
diff --git a/media/remoting/renderer_controller.cc b/media/remoting/renderer_controller.cc
index b2310fe..d2d4b07 100644
--- a/media/remoting/renderer_controller.cc
+++ b/media/remoting/renderer_controller.cc
@@ -12,6 +12,7 @@
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "media/remoting/metrics.h"
+#include "media/remoting/remoting_constants.h"
 
 #if BUILDFLAG(IS_ANDROID)
 #include "media/base/android/media_codec_util.h"
@@ -33,11 +34,6 @@
 constexpr int kPixelsPerSec4k = 3840 * 2160 * 30;  // 4k 30fps.
 constexpr int kPixelsPerSec2k = 1920 * 1080 * 30;  // 1080p 30fps.
 
-// The minimum media element duration that is allowed for media remoting.
-// Frequent switching into and out of media remoting for short-duration media
-// can feel "janky" to the user.
-constexpr double kMinRemotingMediaDurationInSec = 60;
-
 StopTrigger GetStopTrigger(mojom::RemotingStopReason reason) {
   switch (reason) {
     case mojom::RemotingStopReason::ROUTE_TERMINATED:
@@ -574,6 +570,10 @@
   DCHECK(thread_checker_.CalledOnValidThread());
 
   client_ = client;
+  // Reset `encountered_renderer_fatal_error_` when the media element changes so
+  // that the previous renderer fatal error won't prevent Remoting the new
+  // content.
+  encountered_renderer_fatal_error_ = false;
   if (!client_) {
     pixel_rate_timer_.Stop();
     if (remote_rendering_started_) {
diff --git a/media/renderers/paint_canvas_video_renderer.cc b/media/renderers/paint_canvas_video_renderer.cc
index 670a61a..ddb2d19 100644
--- a/media/renderers/paint_canvas_video_renderer.cc
+++ b/media/renderers/paint_canvas_video_renderer.cc
@@ -1010,7 +1010,7 @@
         video_frame->format() == PIXEL_FORMAT_XBGR ||
         video_frame->HasTextures())) {
     cc::PaintFlags black_with_alpha_flags;
-    black_with_alpha_flags.setAlpha(flags.getAlpha());
+    black_with_alpha_flags.setAlphaf(flags.getAlphaf());
     canvas->drawRect(dest, black_with_alpha_flags);
     canvas->flush();
     return;
@@ -1027,7 +1027,7 @@
   DCHECK(image);
 
   cc::PaintFlags video_flags;
-  video_flags.setAlpha(flags.getAlpha());
+  video_flags.setAlphaf(flags.getAlphaf());
   video_flags.setBlendMode(flags.getBlendMode());
 
   const bool need_rotation = video_transformation.rotation != VIDEO_ROTATION_0;
diff --git a/mojo/public/java/system/BUILD.gn b/mojo/public/java/system/BUILD.gn
index f8f93e09a..dbfbf731 100644
--- a/mojo/public/java/system/BUILD.gn
+++ b/mojo/public/java/system/BUILD.gn
@@ -70,8 +70,8 @@
 # Targets should also depend on :test_support for the native side.
 android_library("test_support_java") {
   testonly = true
-  sources = [ "javatests/src/org/chromium/mojo/MojoTestRule.java" ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
+  sources = [ "javatests/src/org/chromium/mojo/MojoTestRule.java" ]
   deps = [
     "//base:base_java",
     "//base:jni_java",
diff --git a/mojo/public/java/system/javatests/mojo_test_rule.cc b/mojo/public/java/system/javatests/mojo_test_rule.cc
index da925286..9e4b58e 100644
--- a/mojo/public/java/system/javatests/mojo_test_rule.cc
+++ b/mojo/public/java/system/javatests/mojo_test_rule.cc
@@ -34,27 +34,20 @@
   mojo::core::Init();
 }
 
-static void JNI_MojoTestRule_Init(JNIEnv* env,
-                                  const JavaParamRef<jobject>& jcaller) {
+static void JNI_MojoTestRule_Init(JNIEnv* env) {
   base::InitAndroidTestMessageLoop();
 }
 
-static jlong JNI_MojoTestRule_SetupTestEnvironment(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& jcaller) {
+static jlong JNI_MojoTestRule_SetupTestEnvironment(JNIEnv* env) {
   return reinterpret_cast<intptr_t>(new TestEnvironment());
 }
 
-static void JNI_MojoTestRule_TearDownTestEnvironment(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& jcaller,
-    jlong test_environment) {
+static void JNI_MojoTestRule_TearDownTestEnvironment(JNIEnv* env,
+                                                     jlong test_environment) {
   delete reinterpret_cast<TestEnvironment*>(test_environment);
 }
 
-static void JNI_MojoTestRule_RunLoop(JNIEnv* env,
-                                     const JavaParamRef<jobject>& jcaller,
-                                     jlong timeout_ms) {
+static void JNI_MojoTestRule_RunLoop(JNIEnv* env, jlong timeout_ms) {
   base::RunLoop run_loop;
   if (timeout_ms) {
     base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
diff --git a/mojo/public/java/system/javatests/src/org/chromium/mojo/MojoTestRule.java b/mojo/public/java/system/javatests/src/org/chromium/mojo/MojoTestRule.java
index 6021cd1a..6a2d2d90e 100644
--- a/mojo/public/java/system/javatests/src/org/chromium/mojo/MojoTestRule.java
+++ b/mojo/public/java/system/javatests/src/org/chromium/mojo/MojoTestRule.java
@@ -48,39 +48,35 @@
             MojoTestRuleJni.get().initCore();
             sIsCoreInitialized = true;
         }
-        nativeInit();
-        mTestEnvironmentPointer = nativeSetupTestEnvironment();
+        MojoTestRuleJni.get().init();
+        mTestEnvironmentPointer = MojoTestRuleJni.get().setupTestEnvironment();
     }
 
     @Override
     protected void after() {
-        nativeTearDownTestEnvironment(mTestEnvironmentPointer);
+        MojoTestRuleJni.get().tearDownTestEnvironment(mTestEnvironmentPointer);
     }
 
     /**
      * Runs the run loop for the given time.
      */
     public void runLoop(long timeoutMS) {
-        nativeRunLoop(timeoutMS);
+        MojoTestRuleJni.get().runLoop(timeoutMS);
     }
 
     /**
      * Runs the run loop until no handle or task are immediately available.
      */
     public void runLoopUntilIdle() {
-        nativeRunLoop(0);
+        MojoTestRuleJni.get().runLoop(0);
     }
 
-    private native void nativeInit();
-
-    private native long nativeSetupTestEnvironment();
-
-    private native void nativeTearDownTestEnvironment(long testEnvironment);
-
-    private native void nativeRunLoop(long timeoutMS);
-
     @NativeMethods
     interface Natives {
+        void init();
+        long setupTestEnvironment();
+        void tearDownTestEnvironment(long testEnvironment);
+        void runLoop(long timeoutMS);
         void initCore();
     }
 }
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 2ad35b6..d00ab54 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1457,6 +1457,8 @@
     public_deps +=
         [ "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.net.interfaces" ]
     sources += [
+      "base/fuchsia/network_interface_cache.cc",
+      "base/fuchsia/network_interface_cache.h",
       "base/network_change_notifier_fuchsia.cc",
       "base/network_change_notifier_fuchsia.h",
       "base/network_interfaces_fuchsia.cc",
@@ -4890,7 +4892,10 @@
       "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.net.interfaces",
       "//third_party/fuchsia-sdk/sdk/pkg/fidl_cpp",
     ]
-    sources += [ "base/network_change_notifier_fuchsia_unittest.cc" ]
+    sources += [
+      "base/fuchsia/network_interface_cache_unittest.cc",
+      "base/network_change_notifier_fuchsia_unittest.cc",
+    ]
     additional_manifest_fragments =
         [ "//build/config/fuchsia/test/network.shard.test-cml" ]
   }
diff --git a/net/android/BUILD.gn b/net/android/BUILD.gn
index be6add58..dd0e4585 100644
--- a/net/android/BUILD.gn
+++ b/net/android/BUILD.gn
@@ -92,6 +92,7 @@
 
 android_library("net_java_test_support_provider") {
   testonly = true
+  annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
   sources = [
     "../test/android/javatests/src/org/chromium/net/test/DummySpnegoAuthenticator.java",
     "../test/android/javatests/src/org/chromium/net/test/DummySpnegoAuthenticatorService.java",
diff --git a/net/android/dummy_spnego_authenticator.cc b/net/android/dummy_spnego_authenticator.cc
index 3ddea3f..5ffe6d2 100644
--- a/net/android/dummy_spnego_authenticator.cc
+++ b/net/android/dummy_spnego_authenticator.cc
@@ -137,20 +137,15 @@
     default;
 
 base::android::ScopedJavaLocalRef<jstring>
-DummySpnegoAuthenticator::SecurityContextQuery::GetTokenToReturn(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& /*obj*/) {
+DummySpnegoAuthenticator::SecurityContextQuery::GetTokenToReturn(JNIEnv* env) {
   return base::android::ConvertUTF8ToJavaString(env, output_token.c_str());
 }
-int DummySpnegoAuthenticator::SecurityContextQuery::GetResult(
-    JNIEnv* /*env*/,
-    const JavaParamRef<jobject>& /*obj*/) {
+int DummySpnegoAuthenticator::SecurityContextQuery::GetResult(JNIEnv* /*env*/) {
   return response_code;
 }
 
 void DummySpnegoAuthenticator::SecurityContextQuery::CheckGetTokenArguments(
     JNIEnv* env,
-    const JavaParamRef<jobject>& /*obj*/,
     const JavaParamRef<jstring>& j_incoming_token) {
   std::string incoming_token =
       base::android::ConvertJavaStringToUTF8(env, j_incoming_token);
@@ -187,9 +182,7 @@
       base::android::AttachCurrentThread(), reinterpret_cast<intptr_t>(this));
 }
 
-long DummySpnegoAuthenticator::GetNextQuery(
-    JNIEnv* /*env*/,
-    const JavaParamRef<jobject>& /* obj */) {
+long DummySpnegoAuthenticator::GetNextQuery(JNIEnv* /*env*/) {
   CheckQueueNotEmpty();
   current_query_ = expected_security_queries_.front();
   expected_security_queries_.pop_front();
diff --git a/net/android/dummy_spnego_authenticator.h b/net/android/dummy_spnego_authenticator.h
index 9b1740e..f2f22f6 100644
--- a/net/android/dummy_spnego_authenticator.h
+++ b/net/android/dummy_spnego_authenticator.h
@@ -93,17 +93,14 @@
     std::string output_token;
 
     // Java callable members
-    base::android::ScopedJavaLocalRef<jstring> GetTokenToReturn(
-        JNIEnv* env,
-        const base::android::JavaParamRef<jobject>& obj);
-    int GetResult(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+    base::android::ScopedJavaLocalRef<jstring> GetTokenToReturn(JNIEnv* env);
+    int GetResult(JNIEnv* env);
 
     // Called from Java to check the arguments passed to the GetToken. Has to
     // be in C++ since these tests are driven by googletest, and can only report
     // failures through the googletest C++ API.
     void CheckGetTokenArguments(
         JNIEnv* env,
-        const base::android::JavaParamRef<jobject>& obj,
         const base::android::JavaParamRef<jstring>& incoming_token);
   };
 
@@ -121,8 +118,7 @@
   static void EnsureTestAccountExists();
   static void RemoveTestAccounts();
 
-  long GetNextQuery(JNIEnv* env,
-                    const base::android::JavaParamRef<jobject>& obj);
+  long GetNextQuery(JNIEnv* env);
 
  private:
   // Abandon the test if the query queue is empty. Has to be a void function to
diff --git a/net/base/features.cc b/net/base/features.cc
index 211f2599..fe21624e 100644
--- a/net/base/features.cc
+++ b/net/base/features.cc
@@ -123,7 +123,7 @@
 
 BASE_FEATURE(kPermuteTLSExtensions,
              "PermuteTLSExtensions",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 BASE_FEATURE(kPostQuantumCECPQ2,
              "PostQuantumCECPQ2",
@@ -182,7 +182,7 @@
 #endif /* BUILDFLAG(IS_MAC) */
 #endif /* BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) */
 
-#if BUILDFLAG(IS_MAC)
+#if BUILDFLAG(IS_MAC) || BUILDFLAG(USE_NSS_CERTS)
 BASE_FEATURE(kTrustStoreTrustedLeafSupport,
              "TrustStoreTrustedLeafSupport",
              base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/net/base/features.h b/net/base/features.h
index a40964b..2887689 100644
--- a/net/base/features.h
+++ b/net/base/features.h
@@ -12,6 +12,7 @@
 #include "base/strings/string_piece.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "crypto/crypto_buildflags.h"
 #include "net/base/net_export.h"
 #include "net/net_buildflags.h"
 
@@ -221,7 +222,7 @@
 // TrustStore implementation will only use TRUSTED_ANCHOR.
 // TODO(https://crbug.com/1403034): remove this a few milestones after the
 // trusted leaf support has been launched on all relevant platforms.
-#if BUILDFLAG(IS_MAC)
+#if BUILDFLAG(IS_MAC) || BUILDFLAG(USE_NSS_CERTS)
 NET_EXPORT BASE_DECLARE_FEATURE(kTrustStoreTrustedLeafSupport);
 #endif
 
diff --git a/net/base/fuchsia/network_interface_cache.cc b/net/base/fuchsia/network_interface_cache.cc
new file mode 100644
index 0000000..01207df
--- /dev/null
+++ b/net/base/fuchsia/network_interface_cache.cc
@@ -0,0 +1,245 @@
+// 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 "net/base/fuchsia/network_interface_cache.h"
+
+#include <fuchsia/net/interfaces/cpp/fidl.h>
+
+#include <utility>
+
+#include "base/containers/flat_map.h"
+#include "base/logging.h"
+#include "base/sequence_checker.h"
+#include "base/synchronization/lock.h"
+#include "net/base/network_change_notifier.h"
+#include "net/base/network_interfaces.h"
+#include "net/base/network_interfaces_fuchsia.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace net::internal {
+namespace {
+
+// Returns a ConnectionType derived from the supplied InterfaceProperties:
+// - CONNECTION_NONE if the interface is not publicly routable.
+// - Otherwise, returns a type derived from the interface's device_class.
+NetworkChangeNotifier::ConnectionType GetEffectiveConnectionType(
+    const InterfaceProperties& properties,
+    bool require_wlan) {
+  if (!properties.IsPubliclyRoutable()) {
+    return NetworkChangeNotifier::CONNECTION_NONE;
+  }
+
+  NetworkChangeNotifier::ConnectionType connection_type =
+      ConvertConnectionType(properties.device_class());
+  if (require_wlan &&
+      connection_type != NetworkChangeNotifier::CONNECTION_WIFI) {
+    return NetworkChangeNotifier::CONNECTION_NONE;
+  }
+  return connection_type;
+}
+
+bool CanReachExternalNetwork(const InterfaceProperties& interface,
+                             bool require_wlan) {
+  return GetEffectiveConnectionType(interface, require_wlan) !=
+         NetworkChangeNotifier::CONNECTION_NONE;
+}
+
+}  // namespace
+
+NetworkInterfaceCache::NetworkInterfaceCache(bool require_wlan)
+    : require_wlan_(require_wlan) {}
+
+NetworkInterfaceCache::~NetworkInterfaceCache() = default;
+
+absl::optional<NetworkInterfaceCache::ChangeBits>
+NetworkInterfaceCache::AddInterfaces(
+    std::vector<fuchsia::net::interfaces::Properties> interfaces) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  base::AutoLock auto_lock(lock_);
+
+  ChangeBits combined_changes = kNoChange;
+  for (auto& interface : interfaces) {
+    auto change_bits = AddInterfaceWhileLocked(std::move(interface));
+    if (!change_bits.has_value()) {
+      return absl::nullopt;
+    }
+    combined_changes |= change_bits.value();
+  }
+  return combined_changes;
+}
+
+absl::optional<NetworkInterfaceCache::ChangeBits>
+NetworkInterfaceCache::AddInterface(
+    fuchsia::net::interfaces::Properties properties) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  base::AutoLock auto_lock(lock_);
+
+  return AddInterfaceWhileLocked(std::move(properties));
+}
+
+absl::optional<NetworkInterfaceCache::ChangeBits>
+NetworkInterfaceCache::AddInterfaceWhileLocked(
+    fuchsia::net::interfaces::Properties properties)
+    EXCLUSIVE_LOCKS_REQUIRED(lock_) VALID_CONTEXT_REQUIRED(sequence_checker_) {
+  if (error_state_) {
+    return absl::nullopt;
+  }
+
+  auto interface = InterfaceProperties::VerifyAndCreate(std::move(properties));
+  if (!interface) {
+    LOG(ERROR) << "Incomplete interface properties.";
+    SetErrorWhileLocked();
+    return absl::nullopt;
+  }
+
+  if (interfaces_.find(interface->id()) != interfaces_.end()) {
+    LOG(ERROR) << "Unexpected duplicate interface ID " << interface->id();
+    SetErrorWhileLocked();
+    return absl::nullopt;
+  }
+
+  ChangeBits change_bits = kNoChange;
+  if (CanReachExternalNetwork(*interface, require_wlan_)) {
+    change_bits |= kIpAddressChanged;
+  }
+  interfaces_.emplace(interface->id(), std::move(*interface));
+  if (UpdateConnectionTypeWhileLocked()) {
+    change_bits |= kConnectionTypeChanged;
+  }
+  return change_bits;
+}
+
+absl::optional<NetworkInterfaceCache::ChangeBits>
+NetworkInterfaceCache::ChangeInterface(
+    fuchsia::net::interfaces::Properties properties) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  base::AutoLock auto_lock(lock_);
+  if (error_state_) {
+    return absl::nullopt;
+  }
+
+  auto cache_entry = interfaces_.find(properties.id());
+  if (cache_entry == interfaces_.end()) {
+    LOG(ERROR) << "Unknown interface ID " << properties.id();
+    SetErrorWhileLocked();
+    return absl::nullopt;
+  }
+
+  const bool old_can_reach =
+      CanReachExternalNetwork(cache_entry->second, require_wlan_);
+  const bool has_addresses = properties.has_addresses();
+
+  if (!cache_entry->second.Update(std::move(properties))) {
+    LOG(ERROR) << "Update failed";
+    SetErrorWhileLocked();
+    return absl::nullopt;
+  }
+
+  const bool new_can_reach =
+      CanReachExternalNetwork(cache_entry->second, require_wlan_);
+
+  ChangeBits change_bits = kNoChange;
+  if (has_addresses || old_can_reach != new_can_reach) {
+    change_bits |= kIpAddressChanged;
+  }
+  if (UpdateConnectionTypeWhileLocked()) {
+    change_bits |= kConnectionTypeChanged;
+  }
+  return change_bits;
+}
+
+absl::optional<NetworkInterfaceCache::ChangeBits>
+NetworkInterfaceCache::RemoveInterface(
+    InterfaceProperties::InterfaceId interface_id) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  base::AutoLock auto_lock(lock_);
+  if (error_state_) {
+    return absl::nullopt;
+  }
+
+  auto cache_entry = interfaces_.find(interface_id);
+  if (cache_entry == interfaces_.end()) {
+    LOG(ERROR) << "Unknown interface ID " << interface_id;
+    SetErrorWhileLocked();
+    return absl::nullopt;
+  }
+
+  ChangeBits change_bits = kNoChange;
+  if (CanReachExternalNetwork(cache_entry->second, require_wlan_)) {
+    change_bits |= kIpAddressChanged;
+  }
+  interfaces_.erase(cache_entry);
+  if (UpdateConnectionTypeWhileLocked()) {
+    change_bits |= kConnectionTypeChanged;
+  }
+  return change_bits;
+}
+
+bool NetworkInterfaceCache::GetOnlineInterfaces(
+    NetworkInterfaceList* networks) const {
+  DCHECK(networks);
+
+  base::AutoLock auto_lock(lock_);
+  if (error_state_) {
+    return false;
+  }
+
+  for (const auto& [_, interface] : interfaces_) {
+    if (!interface.online()) {
+      continue;
+    }
+    if (interface.device_class().is_loopback()) {
+      continue;
+    }
+    interface.AppendNetworkInterfaces(networks);
+  }
+  return true;
+}
+
+NetworkChangeNotifier::ConnectionType NetworkInterfaceCache::GetConnectionType()
+    const {
+  base::AutoLock auto_lock(lock_);
+  if (error_state_) {
+    return NetworkChangeNotifier::CONNECTION_UNKNOWN;
+  }
+
+  return connection_type_;
+}
+
+void NetworkInterfaceCache::SetError() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  base::AutoLock auto_lock(lock_);
+  SetErrorWhileLocked();
+}
+
+bool NetworkInterfaceCache::UpdateConnectionTypeWhileLocked()
+    EXCLUSIVE_LOCKS_REQUIRED(lock_) VALID_CONTEXT_REQUIRED(sequence_checker_) {
+  NetworkChangeNotifier::ConnectionType connection_type =
+      NetworkChangeNotifier::ConnectionType::CONNECTION_NONE;
+  for (const auto& [_, interface] : interfaces_) {
+    connection_type = GetEffectiveConnectionType(interface, require_wlan_);
+    if (connection_type != NetworkChangeNotifier::CONNECTION_NONE) {
+      break;
+    }
+  }
+  if (connection_type != connection_type_) {
+    connection_type_ = connection_type;
+    return true;
+  }
+  return false;
+}
+
+void NetworkInterfaceCache::SetErrorWhileLocked()
+    EXCLUSIVE_LOCKS_REQUIRED(lock_) VALID_CONTEXT_REQUIRED(sequence_checker_) {
+  error_state_ = true;
+  interfaces_.clear();
+  interfaces_.shrink_to_fit();
+}
+
+}  // namespace net::internal
diff --git a/net/base/fuchsia/network_interface_cache.h b/net/base/fuchsia/network_interface_cache.h
new file mode 100644
index 0000000..6853079
--- /dev/null
+++ b/net/base/fuchsia/network_interface_cache.h
@@ -0,0 +1,123 @@
+// 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 NET_BASE_FUCHSIA_NETWORK_INTERFACE_CACHE_H_
+#define NET_BASE_FUCHSIA_NETWORK_INTERFACE_CACHE_H_
+
+#include <fuchsia/net/interfaces/cpp/fidl.h>
+#include <stdint.h>
+#include <zircon/errors.h>
+
+#include "base/containers/flat_map.h"
+#include "base/sequence_checker.h"
+#include "base/thread_annotations.h"
+#include "net/base/net_export.h"
+#include "net/base/network_change_notifier.h"
+#include "net/base/network_interfaces.h"
+#include "net/base/network_interfaces_fuchsia.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace net::internal {
+
+// Cache of network interfaces, keyed by unique interface IDs, kept up-to-date
+// by NetworkChangeNotifierFuchsia.
+//
+// If `require_wlan` is `true`, only WLAN interfaces are observed.
+//
+// Can be accessed via `NetworkChangeNotifier::GetNetworkInterfaceCache()` to
+// get the current list of networks. Methods that read the cache are
+// thread-safe, but methods that modify the cache must be in sequence.
+//
+// NetworkInterfaceCache expects valid write operations only, and can go into
+// unrecoverable error state if `SetError()` is called, or attempted to
+// - Add an interface twice.
+// - Add/Change an interface with incomplete properties.
+// - Change/Remove an interface unknown to the cache.
+//
+// After entering error state, all subsequent write operations return
+// `absl::nullopt`, and subsequent read operations will not return a result
+// (specifically, `GetOnlineInterfaces` returns `false`, and `GetConnectionType`
+// returns `CONNECTION_UNKNOWN`).
+class NET_EXPORT_PRIVATE NetworkInterfaceCache {
+ public:
+  using ChangeBits = uint32_t;
+  enum : ChangeBits {
+    kNoChange = 0,
+    kIpAddressChanged = 1 << 0,
+    kConnectionTypeChanged = 1 << 1,
+  };
+
+  explicit NetworkInterfaceCache(bool require_wlan);
+  ~NetworkInterfaceCache();
+
+  NetworkInterfaceCache(const NetworkInterfaceCache&) = delete;
+  NetworkInterfaceCache& operator=(const NetworkInterfaceCache&) = delete;
+
+  // Returns `absl::nullopt` if any of the interfaces fail to be added. See
+  // `AddInterface`.
+  absl::optional<ChangeBits> AddInterfaces(
+      std::vector<fuchsia::net::interfaces::Properties> interfaces);
+
+  // Returns `absl::nullopt` if `properties` is invalid or incomplete, or if the
+  // interface already exists in the cache.
+  absl::optional<ChangeBits> AddInterface(
+      fuchsia::net::interfaces::Properties properties);
+
+  // Returns `absl::nullopt` if `properties` is invalid or does not contain an
+  // `id`, or if the interface does not exist in the cache.
+  absl::optional<ChangeBits> ChangeInterface(
+      fuchsia::net::interfaces::Properties properties);
+
+  // Returns `absl::nullopt` if `interface_id` does not exist in the cache.
+  absl::optional<ChangeBits> RemoveInterface(
+      InterfaceProperties::InterfaceId interface_id);
+
+  // Set cache to unrecoverable error state and clears the cache.
+  // Should be called when contents of the cache can no longer be updated to
+  // reflect the state of the system.
+  void SetError();
+
+  // Thread-safe method that populates a list of online network interfaces.
+  // Ignores loopback interface. Returns `false` if in error state.
+  bool GetOnlineInterfaces(NetworkInterfaceList* networks) const;
+
+  // Thread-safe method that returns the current connection type.
+  // Returns `CONNECTION_UNKNOWN` if in error state.
+  NetworkChangeNotifier::ConnectionType GetConnectionType() const;
+
+ private:
+  // Updates `connection_type_` from `interfaces_` and returns `true` if
+  // the connection type changed.
+  bool UpdateConnectionTypeWhileLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_)
+      VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  absl::optional<ChangeBits> AddInterfaceWhileLocked(
+      fuchsia::net::interfaces::Properties properties)
+      EXCLUSIVE_LOCKS_REQUIRED(lock_) VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  void SetErrorWhileLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_)
+      VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  // Whether only WLAN interfaces should be taken into account.
+  const bool require_wlan_;
+
+  mutable base::Lock lock_;
+
+  base::flat_map<InterfaceProperties::InterfaceId, InterfaceProperties>
+      interfaces_ GUARDED_BY(lock_);
+
+  // The ConnectionType of the default network interface.
+  NetworkChangeNotifier::ConnectionType connection_type_ GUARDED_BY(lock_) =
+      NetworkChangeNotifier::CONNECTION_NONE;
+
+  // Set to true if any update is inconsistent with the network interfaces state
+  // that is currently cached.
+  bool error_state_ GUARDED_BY(lock_) = false;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+};
+
+}  // namespace net::internal
+
+#endif  // NET_BASE_FUCHSIA_NETWORK_INTERFACE_CACHE_H_
diff --git a/net/base/fuchsia/network_interface_cache_unittest.cc b/net/base/fuchsia/network_interface_cache_unittest.cc
new file mode 100644
index 0000000..faffb71d
--- /dev/null
+++ b/net/base/fuchsia/network_interface_cache_unittest.cc
@@ -0,0 +1,143 @@
+// 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 "net/base/fuchsia/network_interface_cache.h"
+
+#include <fuchsia/net/interfaces/cpp/fidl.h>
+#include <fuchsia/net/interfaces/cpp/fidl_test_base.h>
+
+#include "net/base/network_change_notifier.h"
+#include "net/base/network_interfaces.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net::internal {
+namespace {
+
+enum : InterfaceProperties::InterfaceId {
+  kDefaultInterfaceId = 1,
+  kSecondaryInterfaceId = 2
+};
+
+using IPv4Octets = std::array<uint8_t, 4>;
+
+constexpr IPv4Octets kDefaultIPv4Address = {192, 168, 0, 2};
+constexpr uint8_t kDefaultIPv4Prefix = 16;
+
+constexpr const char kDefaultInterfaceName[] = "net1";
+
+fuchsia::net::IpAddress IpAddressFrom(IPv4Octets octets) {
+  fuchsia::net::IpAddress output;
+  output.ipv4().addr = octets;
+  return output;
+}
+
+template <typename T>
+fuchsia::net::Subnet SubnetFrom(T octets, uint8_t prefix) {
+  fuchsia::net::Subnet output;
+  output.addr = IpAddressFrom(octets);
+  output.prefix_len = prefix;
+  return output;
+}
+
+template <typename T>
+fuchsia::net::interfaces::Address InterfaceAddressFrom(T octets,
+                                                       uint8_t prefix) {
+  fuchsia::net::interfaces::Address addr;
+  addr.set_addr(SubnetFrom(octets, prefix));
+  return addr;
+}
+
+template <typename T>
+std::vector<T> MakeSingleItemVec(T item) {
+  std::vector<T> vec;
+  vec.push_back(std::move(item));
+  return vec;
+}
+
+fuchsia::net::interfaces::Properties DefaultInterfaceProperties(
+    fuchsia::hardware::network::DeviceClass device_class =
+        fuchsia::hardware::network::DeviceClass::ETHERNET) {
+  // For most tests a live interface with an IPv4 address and ethernet class is
+  // sufficient.
+  fuchsia::net::interfaces::Properties properties;
+  properties.set_id(kDefaultInterfaceId);
+  properties.set_name(kDefaultInterfaceName);
+  properties.set_online(true);
+  properties.set_has_default_ipv4_route(true);
+  properties.set_has_default_ipv6_route(false);
+  properties.set_device_class(fuchsia::net::interfaces::DeviceClass::WithDevice(
+      std::move(device_class)));
+  properties.set_addresses(MakeSingleItemVec(
+      InterfaceAddressFrom(kDefaultIPv4Address, kDefaultIPv4Prefix)));
+  return properties;
+}
+
+}  // namespace
+
+class NetworkInterfaceCacheTest : public testing::Test {};
+
+TEST_F(NetworkInterfaceCacheTest, AddInterface) {
+  NetworkInterfaceCache cache(false);
+
+  auto change_bits = cache.AddInterface(DefaultInterfaceProperties());
+
+  ASSERT_TRUE(change_bits.has_value());
+  EXPECT_EQ(change_bits.value(),
+            NetworkInterfaceCache::kIpAddressChanged |
+                NetworkInterfaceCache::kConnectionTypeChanged);
+
+  NetworkInterfaceList networks;
+  EXPECT_TRUE(cache.GetOnlineInterfaces(&networks));
+  EXPECT_EQ(networks.size(), 1u);
+
+  EXPECT_EQ(cache.GetConnectionType(),
+            NetworkChangeNotifier::CONNECTION_ETHERNET);
+}
+
+TEST_F(NetworkInterfaceCacheTest, RemoveInterface) {
+  NetworkInterfaceCache cache(false);
+  cache.AddInterface(DefaultInterfaceProperties());
+
+  auto change_bits = cache.RemoveInterface(kDefaultInterfaceId);
+
+  ASSERT_TRUE(change_bits.has_value());
+  EXPECT_EQ(change_bits.value(),
+            NetworkInterfaceCache::kIpAddressChanged |
+                NetworkInterfaceCache::kConnectionTypeChanged);
+
+  NetworkInterfaceList networks;
+  EXPECT_TRUE(cache.GetOnlineInterfaces(&networks));
+  EXPECT_EQ(networks.size(), 0u);
+
+  EXPECT_EQ(cache.GetConnectionType(), NetworkChangeNotifier::CONNECTION_NONE);
+}
+
+TEST_F(NetworkInterfaceCacheTest, ChangeInterface) {
+  NetworkInterfaceCache cache(false);
+  cache.AddInterface(DefaultInterfaceProperties());
+
+  fuchsia::net::interfaces::Properties properties;
+  properties.set_id(kDefaultInterfaceId);
+  properties.set_device_class(
+      fuchsia::net::interfaces::DeviceClass::WithLoopback(
+          fuchsia::net::interfaces::Empty()));
+  properties.set_addresses({});
+
+  auto change_bits = cache.ChangeInterface(std::move(properties));
+
+  ASSERT_TRUE(change_bits.has_value());
+  EXPECT_EQ(change_bits.value(),
+            NetworkInterfaceCache::kIpAddressChanged |
+                NetworkInterfaceCache::kConnectionTypeChanged);
+
+  NetworkInterfaceList networks;
+  EXPECT_TRUE(cache.GetOnlineInterfaces(&networks));
+  EXPECT_EQ(networks.size(), 0u);
+
+  EXPECT_EQ(cache.GetConnectionType(), NetworkChangeNotifier::CONNECTION_NONE);
+}
+
+// TODO(crbug.com/1131238): Add more tests that exercise different error states.
+
+}  // namespace net::internal
diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc
index 77f4dac..4398b17 100644
--- a/net/base/network_change_notifier.cc
+++ b/net/base/network_change_notifier.cc
@@ -526,7 +526,17 @@
              ? g_network_change_notifier->GetAddressTrackerInternal()
              : nullptr;
 }
-#endif
+#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
+
+#if BUILDFLAG(IS_FUCHSIA)
+// static
+const internal::NetworkInterfaceCache*
+NetworkChangeNotifier::GetNetworkInterfaceCache() {
+  return g_network_change_notifier
+             ? g_network_change_notifier->GetNetworkInterfaceCacheInternal()
+             : nullptr;
+}
+#endif  // BUILDFLAG(IS_FUCHSIA)
 
 // static
 bool NetworkChangeNotifier::IsOffline() {
@@ -870,6 +880,13 @@
 }
 #endif
 
+#if BUILDFLAG(IS_FUCHSIA)
+const internal::NetworkInterfaceCache*
+NetworkChangeNotifier::GetNetworkInterfaceCacheInternal() const {
+  return nullptr;
+}
+#endif
+
 NetworkChangeNotifier::ConnectionCost
 NetworkChangeNotifier::GetCurrentConnectionCost() {
   // This is the default non-platform specific implementation and assumes that
diff --git a/net/base/network_change_notifier.h b/net/base/network_change_notifier.h
index 5a790cc..0bdc9ae 100644
--- a/net/base/network_change_notifier.h
+++ b/net/base/network_change_notifier.h
@@ -25,12 +25,16 @@
 class SystemDnsConfigChangeNotifier;
 typedef std::vector<NetworkInterface> NetworkInterfaceList;
 
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
 namespace internal {
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
 class AddressTrackerLinux;
-}
 #endif
 
+#if BUILDFLAG(IS_FUCHSIA)
+class NetworkInterfaceCache;
+#endif
+}  // namespace internal
+
 // NetworkChangeNotifier monitors the system for network changes, and notifies
 // registered observers of those events.  Observers may register on any thread,
 // and will be called back on the thread from which they registered.
@@ -457,6 +461,11 @@
   static const internal::AddressTrackerLinux* GetAddressTracker();
 #endif
 
+#if BUILDFLAG(IS_FUCHSIA)
+  // Returns the NetworkInterfaceCache if present.
+  static const internal::NetworkInterfaceCache* GetNetworkInterfaceCache();
+#endif
+
   // Convenience method to determine if the user is offline.
   // Returns true if there is currently no internet connection.
   //
@@ -624,6 +633,11 @@
       GetAddressTrackerInternal() const;
 #endif
 
+#if BUILDFLAG(IS_FUCHSIA)
+  virtual const internal::NetworkInterfaceCache*
+  GetNetworkInterfaceCacheInternal() const;
+#endif
+
   // These are the actual implementations of the static queryable APIs.
   // See the description of the corresponding functions named without "Current".
   // Implementations must be thread-safe. Implementations must also be
diff --git a/net/base/network_change_notifier_fuchsia.cc b/net/base/network_change_notifier_fuchsia.cc
index e03fdab..1cdc0cd 100644
--- a/net/base/network_change_notifier_fuchsia.cc
+++ b/net/base/network_change_notifier_fuchsia.cc
@@ -4,57 +4,50 @@
 
 #include "net/base/network_change_notifier_fuchsia.h"
 
+#include <fuchsia/net/interfaces/cpp/fidl.h>
+#include <lib/sys/cpp/component_context.h>
+
 #include <algorithm>
-#include <iterator>
-#include <string>
 #include <utility>
 #include <vector>
 
 #include "base/fuchsia/fuchsia_logging.h"
-#include "base/functional/bind.h"
-#include "base/strings/stringprintf.h"
+#include "base/fuchsia/process_context.h"
+#include "base/logging.h"
+#include "base/threading/thread_checker.h"
+#include "base/types/expected.h"
+#include "net/base/fuchsia/network_interface_cache.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace net {
 
 NetworkChangeNotifierFuchsia::NetworkChangeNotifierFuchsia(bool require_wlan)
     : NetworkChangeNotifierFuchsia(internal::ConnectInterfacesWatcher(),
-                                   require_wlan) {}
+                                   require_wlan,
+                                   /*system_dns_config_notifier=*/nullptr) {}
 
 NetworkChangeNotifierFuchsia::NetworkChangeNotifierFuchsia(
-    fidl::InterfaceHandle<fuchsia::net::interfaces::Watcher> handle,
+    fuchsia::net::interfaces::WatcherHandle watcher_handle,
     bool require_wlan,
     SystemDnsConfigChangeNotifier* system_dns_config_notifier)
     : NetworkChangeNotifier(NetworkChangeCalculatorParams(),
                             system_dns_config_notifier),
-      require_wlan_(require_wlan) {
-  DCHECK(handle);
+      cache_(require_wlan) {
+  DCHECK(watcher_handle);
+
+  std::vector<fuchsia::net::interfaces::Properties> interfaces;
+  auto handle_or_status = internal::ReadExistingNetworkInterfacesFromNewWatcher(
+      std::move(watcher_handle), interfaces);
+  if (!handle_or_status.has_value()) {
+    return;
+  }
+
+  HandleCacheStatus(cache_.AddInterfaces(std::move(interfaces)));
 
   watcher_.set_error_handler(base::LogFidlErrorAndExitProcess(
       FROM_HERE, "fuchsia.net.interfaces.Watcher"));
-
-  fuchsia::net::interfaces::WatcherSyncPtr watcher = handle.BindSync();
-  absl::optional<internal::ExistingInterfaceProperties> interfaces =
-      internal::GetExistingInterfaces(watcher);
-  if (!interfaces)
-    return;
-
-  handle = watcher.Unbind();
-  bool notify_ip_address_changed = false;
-  for (const auto& interface_entry : *interfaces) {
-    notify_ip_address_changed |=
-        CanReachExternalNetwork(interface_entry.second);
-  }
-  interface_cache_ = InterfacePropertiesMap(std::move(*interfaces));
-
-  UpdateConnectionType();
-  if (notify_ip_address_changed) {
-    NotifyObserversOfIPAddressChange();
-  }
-
-  // Bind to the dispatcher for the thread's MessagePump.
-  zx_status_t status = watcher_.Bind(std::move(handle));
-  ZX_CHECK(status == ZX_OK, status) << "Bind()";
+  zx_status_t bind_status = watcher_.Bind(std::move(handle_or_status.value()));
+  ZX_CHECK(bind_status == ZX_OK, bind_status) << "Bind()";
   watcher_->Watch(
       fit::bind_member(this, &NetworkChangeNotifierFuchsia::OnInterfacesEvent));
 }
@@ -66,13 +59,18 @@
 
 NetworkChangeNotifier::ConnectionType
 NetworkChangeNotifierFuchsia::GetCurrentConnectionType() const {
-  ConnectionType type = static_cast<ConnectionType>(
-      base::subtle::Acquire_Load(&cached_connection_type_));
-  return type;
+  return cache_.GetConnectionType();
+}
+
+const internal::NetworkInterfaceCache*
+NetworkChangeNotifierFuchsia::GetNetworkInterfaceCacheInternal() const {
+  return &cache_;
 }
 
 void NetworkChangeNotifierFuchsia::OnInterfacesEvent(
     fuchsia::net::interfaces::Event event) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
   // Immediately trigger the next watch, which will happen asynchronously. If
   // event processing encounters an error it'll close the watcher channel which
   // will cancel any pending callbacks.
@@ -81,136 +79,83 @@
 
   switch (event.Which()) {
     case fuchsia::net::interfaces::Event::kAdded:
-      OnInterfaceAdded(std::move(event.added()));
+      HandleCacheStatus(cache_.AddInterface(std::move(event.added())));
       break;
     case fuchsia::net::interfaces::Event::kRemoved:
-      OnInterfaceRemoved(event.removed());
+      HandleCacheStatus(cache_.RemoveInterface(event.removed()));
       break;
     case fuchsia::net::interfaces::Event::kChanged:
-      OnInterfaceChanged(std::move(event.changed()));
+      HandleCacheStatus(cache_.ChangeInterface(std::move(event.changed())));
       break;
-    case fuchsia::net::interfaces::Event::kExisting:
-    case fuchsia::net::interfaces::Event::kIdle:
-      OnWatcherError(base::StringPrintf(
-          "OnInterfaceEvent: unexpected event %lu.", event.Which()));
-      break;
-    case fuchsia::net::interfaces::Event::Invalid:
-      LOG(WARNING)
-          << "Invalid event received from fuchsia.net.interfaces/Watcher";
+    default:
+      LOG(ERROR) << "Unexpected event: " << event.Which();
+      watcher_.Unbind();
+      cache_.SetError();
       break;
   }
 }
 
-void NetworkChangeNotifierFuchsia::OnInterfaceAdded(
-    fuchsia::net::interfaces::Properties properties) {
-  uint64_t id = properties.id();
-  absl::optional<internal::InterfaceProperties> cache_entry =
-      internal::InterfaceProperties::VerifyAndCreate(std::move(properties));
-  if (!cache_entry) {
-    OnWatcherError("OnInterfaceAdded: incomplete interface properties.");
+void NetworkChangeNotifierFuchsia::HandleCacheStatus(
+    absl::optional<internal::NetworkInterfaceCache::ChangeBits> change_bits) {
+  if (!change_bits.has_value()) {
+    watcher_.Unbind();
     return;
   }
-  if (interface_cache_.find(id) != interface_cache_.end()) {
-    OnWatcherError(base::StringPrintf(
-        "OnInterfaceAdded: duplicate interface ID %lu.", id));
-    return;
-  }
-  const bool can_reach = CanReachExternalNetwork(*cache_entry);
-  interface_cache_.emplace(id, std::move(*cache_entry));
-  UpdateConnectionType();
-  if (can_reach) {
+
+  if (change_bits.value() &
+      internal::NetworkInterfaceCache::kIpAddressChanged) {
     NotifyObserversOfIPAddressChange();
   }
-}
-
-void NetworkChangeNotifierFuchsia::OnInterfaceRemoved(uint64_t interface_id) {
-  InterfacePropertiesMap::iterator cache_entry =
-      interface_cache_.find(interface_id);
-  if (cache_entry == interface_cache_.end()) {
-    OnWatcherError(base::StringPrintf(
-        "OnInterfaceRemoved: unknown interface ID %lu.", interface_id));
-    return;
-  }
-  const bool can_reach = CanReachExternalNetwork(cache_entry->second);
-  interface_cache_.erase(cache_entry);
-  UpdateConnectionType();
-  if (can_reach) {
-    NotifyObserversOfIPAddressChange();
-  }
-}
-
-void NetworkChangeNotifierFuchsia::OnInterfaceChanged(
-    fuchsia::net::interfaces::Properties properties) {
-  if (!properties.has_id()) {
-    OnWatcherError("OnInterfaceChanged: no interface ID.");
-    return;
-  }
-  const uint64_t id = properties.id();
-  InterfacePropertiesMap::iterator cache_entry = interface_cache_.find(id);
-  if (cache_entry == interface_cache_.end()) {
-    OnWatcherError(base::StringPrintf(
-        "OnInterfaceChanged: unknown interface ID %lu.", id));
-    return;
-  }
-  const bool old_can_reach = CanReachExternalNetwork(cache_entry->second);
-  const bool has_addresses = properties.has_addresses();
-  if (!cache_entry->second.Update(std::move(properties))) {
-    OnWatcherError("OnInterfaceChanged: update failed.");
-    return;
-  }
-
-  UpdateConnectionType();
-  const bool can_reach = CanReachExternalNetwork(cache_entry->second);
-  if (has_addresses || old_can_reach != can_reach) {
-    NotifyObserversOfIPAddressChange();
-  }
-}
-
-void NetworkChangeNotifierFuchsia::OnWatcherError(
-    base::StringPiece error_message) {
-  LOG(ERROR) << error_message;
-  watcher_.Unbind();
-  ResetConnectionType();
-}
-
-void NetworkChangeNotifierFuchsia::UpdateConnectionType() {
-  ConnectionType connection_type = ConnectionType::CONNECTION_NONE;
-  for (const auto& interface : interface_cache_) {
-    if (CanReachExternalNetwork(interface.second)) {
-      connection_type = GetEffectiveConnectionType(interface.second);
-      break;
-    }
-  }
-  if (connection_type != GetCurrentConnectionType()) {
-    base::subtle::Release_Store(&cached_connection_type_, connection_type);
+  if (change_bits.value() &
+      internal::NetworkInterfaceCache::kConnectionTypeChanged) {
     NotifyObserversOfConnectionTypeChange();
   }
 }
 
-void NetworkChangeNotifierFuchsia::ResetConnectionType() {
-  base::subtle::Release_Store(&cached_connection_type_,
-                              ConnectionType::CONNECTION_UNKNOWN);
+namespace internal {
+
+fuchsia::net::interfaces::WatcherHandle ConnectInterfacesWatcher() {
+  fuchsia::net::interfaces::StateSyncPtr state;
+  zx_status_t status =
+      base::ComponentContextForProcess()->svc()->Connect(state.NewRequest());
+  ZX_CHECK(status == ZX_OK, status) << "Connect()";
+
+  fuchsia::net::interfaces::WatcherHandle watcher;
+  status = state->GetWatcher(/*options=*/{}, watcher.NewRequest());
+  ZX_CHECK(status == ZX_OK, status) << "GetWatcher()";
+
+  return watcher;
 }
 
-NetworkChangeNotifier::ConnectionType
-NetworkChangeNotifierFuchsia::GetEffectiveConnectionType(
-    const internal::InterfaceProperties& properties) {
-  if (!properties.IsPubliclyRoutable())
-    return NetworkChangeNotifier::CONNECTION_NONE;
+base::expected<fuchsia::net::interfaces::WatcherHandle, zx_status_t>
+ReadExistingNetworkInterfacesFromNewWatcher(
+    fuchsia::net::interfaces::WatcherHandle watcher_handle,
+    std::vector<fuchsia::net::interfaces::Properties>& interfaces) {
+  DCHECK(watcher_handle);
 
-  NetworkChangeNotifier::ConnectionType connection_type =
-      internal::ConvertConnectionType(properties.device_class());
-  if (require_wlan_ &&
-      connection_type != NetworkChangeNotifier::CONNECTION_WIFI) {
-    return NetworkChangeNotifier::CONNECTION_NONE;
+  fuchsia::net::interfaces::WatcherSyncPtr watcher = watcher_handle.BindSync();
+
+  while (true) {
+    fuchsia::net::interfaces::Event event;
+    if (auto watch_status = watcher->Watch(&event); watch_status != ZX_OK) {
+      ZX_LOG(ERROR, watch_status) << "Watch() failed";
+      return base::unexpected(watch_status);
+    }
+
+    switch (event.Which()) {
+      case fuchsia::net::interfaces::Event::Tag::kExisting:
+        interfaces.push_back(std::move(event.existing()));
+        break;
+      case fuchsia::net::interfaces::Event::Tag::kIdle:
+        // Idle means we've listed all the existing interfaces. We can stop
+        // fetching events.
+        return base::ok(watcher.Unbind());
+      default:
+        LOG(ERROR) << "Unexpected event " << event.Which();
+        return base::unexpected(ZX_ERR_NOT_SUPPORTED);
+    }
   }
-  return connection_type;
 }
 
-bool NetworkChangeNotifierFuchsia::CanReachExternalNetwork(
-    const internal::InterfaceProperties& properties) {
-  return GetEffectiveConnectionType(properties) !=
-         NetworkChangeNotifier::CONNECTION_NONE;
-}
-
+}  // namespace internal
 }  // namespace net
diff --git a/net/base/network_change_notifier_fuchsia.h b/net/base/network_change_notifier_fuchsia.h
index 75379c7..ba010db 100644
--- a/net/base/network_change_notifier_fuchsia.h
+++ b/net/base/network_change_notifier_fuchsia.h
@@ -6,21 +6,20 @@
 #define NET_BASE_NETWORK_CHANGE_NOTIFIER_FUCHSIA_H_
 
 #include <fuchsia/net/interfaces/cpp/fidl.h>
-#include <lib/fidl/cpp/binding.h>
 
-#include "base/atomicops.h"
-#include "base/containers/flat_map.h"
-#include "base/functional/callback.h"
-#include "base/gtest_prod_util.h"
-#include "base/strings/string_piece.h"
+#include <vector>
+
 #include "base/threading/thread_checker.h"
+#include "base/types/expected.h"
+#include "net/base/fuchsia/network_interface_cache.h"
 #include "net/base/net_export.h"
 #include "net/base/network_change_notifier.h"
-#include "net/base/network_interfaces.h"
-#include "net/base/network_interfaces_fuchsia.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace net {
 
+class SystemDnsConfigChangeNotifier;
+
 class NET_EXPORT_PRIVATE NetworkChangeNotifierFuchsia
     : public NetworkChangeNotifier {
  public:
@@ -36,59 +35,51 @@
   ConnectionType GetCurrentConnectionType() const override;
 
  private:
-  using InterfacePropertiesMap =
-      base::flat_map<uint64_t, internal::InterfaceProperties>;
   friend class NetworkChangeNotifierFuchsiaTest;
 
+  const internal::NetworkInterfaceCache* GetNetworkInterfaceCacheInternal()
+      const override;
+
   NetworkChangeNotifierFuchsia(
-      fidl::InterfaceHandle<fuchsia::net::interfaces::Watcher> watcher,
+      fuchsia::net::interfaces::WatcherHandle watcher,
       bool require_wlan,
-      SystemDnsConfigChangeNotifier* system_dns_config_notifier = nullptr);
+      SystemDnsConfigChangeNotifier* system_dns_config_notifier);
 
   // Processes events from the watcher for interface addition, change, or
-  // removal.
+  // removal. Listeners are notified of changes that affect them. `watcher_` is
+  // unbound if an event is malformed in some way.
   void OnInterfacesEvent(fuchsia::net::interfaces::Event event);
 
-  // Handlers for the interface change events. Listeners are notified of changes
-  // that affect them. |watcher_| is closed if an event is malformed in some
-  // way.
-  void OnInterfaceAdded(fuchsia::net::interfaces::Properties properties);
-  void OnInterfaceRemoved(uint64_t interface_id);
-  void OnInterfaceChanged(fuchsia::net::interfaces::Properties properties);
-
-  // Unbinds the watcher, reset the connection type and logs |error_message|.
-  void OnWatcherError(base::StringPiece error_message);
-
-  // Updates the connection type from |interface_cache_| and notifies observers
-  // of changes.
-  void UpdateConnectionType();
-
-  // Resets the connection type to CONNECTION_UNKNOWN.
-  void ResetConnectionType();
-
-  // Returns the ConnectionType converted from |properties|' device_class.
-  // Returns CONNECTION_NONE if the interface is not publicly routable, taking
-  // into account the |requires_wlan_| setting.
-  ConnectionType GetEffectiveConnectionType(
-      const internal::InterfaceProperties& properties);
-
-  // Returns true if the effective connection type is not CONNECTION_NONE.
-  bool CanReachExternalNetwork(const internal::InterfaceProperties& properties);
-
-  // Whether only WLAN interfaces should be taken into account.
-  const bool require_wlan_;
+  // Notifies observers of changes. Unbinds `watcher_` if there was an error.
+  void HandleCacheStatus(
+      absl::optional<internal::NetworkInterfaceCache::ChangeBits> change_bits);
 
   fuchsia::net::interfaces::WatcherPtr watcher_;
 
-  // The ConnectionType of the default network interface, stored as an atomic
-  // 32-bit int for safe concurrent access.
-  base::subtle::Atomic32 cached_connection_type_ = CONNECTION_UNKNOWN;
-
-  InterfacePropertiesMap interface_cache_;
+  // Keeps an updated cache of network interfaces and connection type.
+  internal::NetworkInterfaceCache cache_;
 
   THREAD_CHECKER(thread_checker_);
 };
 
+namespace internal {
+
+// Connects to the service via the process' ComponentContext, and connects the
+// Watcher to the service.
+fuchsia::net::interfaces::WatcherHandle ConnectInterfacesWatcher();
+
+// Reads existing network interfaces from `watcher_handle`, appending them to
+// `interfaces`. If successful, returns an unbound WatcherHandle that can be
+// used to watch for subsequent changes.
+//
+// `watcher_handle` must be a newly created fuchsia.net.interfaces.Watcher. Can
+// be used as the first part of the hanging-get pattern.
+base::expected<fuchsia::net::interfaces::WatcherHandle, zx_status_t>
+ReadExistingNetworkInterfacesFromNewWatcher(
+    fuchsia::net::interfaces::WatcherHandle watcher_handle,
+    std::vector<fuchsia::net::interfaces::Properties>& interfaces);
+
+}  // namespace internal
 }  // namespace net
 
 #endif  // NET_BASE_NETWORK_CHANGE_NOTIFIER_FUCHSIA_H_
diff --git a/net/base/network_change_notifier_fuchsia_unittest.cc b/net/base/network_change_notifier_fuchsia_unittest.cc
index 23bb3dec..9464e56 100644
--- a/net/base/network_change_notifier_fuchsia_unittest.cc
+++ b/net/base/network_change_notifier_fuchsia_unittest.cc
@@ -5,6 +5,8 @@
 #include "net/base/network_change_notifier_fuchsia.h"
 
 #include <fuchsia/net/interfaces/cpp/fidl_test_base.h>
+#include <lib/fidl/cpp/binding.h>
+
 #include <memory>
 #include <string>
 #include <utility>
@@ -18,6 +20,7 @@
 #include "base/threading/sequence_bound.h"
 #include "base/threading/thread.h"
 #include "net/base/ip_address.h"
+#include "net/base/network_change_notifier.h"
 #include "net/dns/dns_config_service.h"
 #include "net/dns/system_dns_config_change_notifier.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -41,6 +44,9 @@
 constexpr IPv6Octets kSecondaryIPv6Address = {0x20, 0x01, 0x02};
 constexpr uint8_t kSecondaryIPv6Prefix = 16;
 
+constexpr const char kDefaultInterfaceName[] = "net1";
+constexpr const char kSecondaryInterfaceName[] = "net2";
+
 fuchsia::net::IpAddress IpAddressFrom(IPv4Octets octets) {
   fuchsia::net::IpAddress output;
   output.ipv4().addr = octets;
@@ -83,6 +89,7 @@
   // sufficient.
   fuchsia::net::interfaces::Properties interface;
   interface.set_id(kDefaultInterfaceId);
+  interface.set_name(kDefaultInterfaceName);
   interface.set_online(true);
   interface.set_has_default_ipv4_route(true);
   interface.set_has_default_ipv6_route(true);
@@ -98,6 +105,7 @@
   // sufficient.
   fuchsia::net::interfaces::Properties interface;
   interface.set_id(kSecondaryInterfaceId);
+  interface.set_name(kSecondaryInterfaceName);
   interface.set_online(true);
   interface.set_has_default_ipv4_route(false);
   interface.set_has_default_ipv6_route(false);
@@ -119,7 +127,7 @@
 // Partial fake implementation of a fuchsia.net.interfaces/Watcher.
 class FakeWatcher : public fuchsia::net::interfaces::testing::Watcher_TestBase {
  public:
-  explicit FakeWatcher() : binding_(this) {
+  FakeWatcher() : binding_(this) {
     // Always create the watcher with an empty set of interfaces.
     // Callers can override the initial set of events with SetInitial.
     pending_.push(fuchsia::net::interfaces::Event::WithIdle(
@@ -177,7 +185,7 @@
 
 class FakeWatcherAsync {
  public:
-  explicit FakeWatcherAsync() {
+  FakeWatcherAsync() {
     base::Thread::Options options(base::MessagePumpType::IO, 0);
     CHECK(thread_.StartWithOptions(std::move(options)));
     watcher_ = base::SequenceBound<FakeWatcher>(thread_.task_runner());
@@ -339,7 +347,7 @@
   // Creates a NetworkChangeNotifier that binds to |watcher_|.
   // |observer_| is registered last, so that tests need only express
   // expectations on changes they make themselves.
-  void CreateNotifier(bool requires_wlan = false) {
+  void CreateNotifier(bool require_wlan = false) {
     // Ensure that internal state is up-to-date before the
     // notifier queries it.
     watcher_.FlushThread();
@@ -351,7 +359,7 @@
     dns_config_notifier_ = std::make_unique<SystemDnsConfigChangeNotifier>(
         nullptr /* task_runner */, nullptr /* dns_config_service */);
     notifier_ = base::WrapUnique(new NetworkChangeNotifierFuchsia(
-        std::move(watcher_handle_), requires_wlan, dns_config_notifier_.get()));
+        std::move(watcher_handle_), require_wlan, dns_config_notifier_.get()));
 
     type_observer_ = std::make_unique<FakeConnectionTypeObserver>();
     ip_observer_ = std::make_unique<FakeIPAddressObserver>();
diff --git a/net/base/network_interfaces_fuchsia.cc b/net/base/network_interfaces_fuchsia.cc
index 84ed06e..facc96bf 100644
--- a/net/base/network_interfaces_fuchsia.cc
+++ b/net/base/network_interfaces_fuchsia.cc
@@ -4,15 +4,18 @@
 
 #include "net/base/network_interfaces_fuchsia.h"
 
-#include <lib/sys/cpp/component_context.h>
+#include <fuchsia/net/interfaces/cpp/fidl.h>
+#include <zircon/types.h>
 
 #include <string>
 #include <utility>
 
-#include "base/format_macros.h"
-#include "base/fuchsia/fuchsia_logging.h"
-#include "base/fuchsia/process_context.h"
+#include "base/logging.h"
+#include "net/base/fuchsia/network_interface_cache.h"
+#include "net/base/network_change_notifier.h"
+#include "net/base/network_change_notifier_fuchsia.h"
 #include "net/base/network_interfaces.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace net {
 namespace internal {
@@ -54,14 +57,14 @@
 bool InterfaceProperties::Update(
     fuchsia::net::interfaces::Properties properties) {
   if (!properties.has_id() || properties_.id() != properties.id()) {
-    LOG(WARNING) << "Update failed: invalid properties.";
+    LOG(ERROR) << "Update failed: invalid properties.";
     return false;
   }
 
   if (properties.has_addresses()) {
     for (const auto& fidl_address : properties.addresses()) {
       if (!fidl_address.has_addr()) {
-        LOG(WARNING) << "Update failed: invalid properties.";
+        LOG(ERROR) << "Update failed: invalid properties.";
         return false;
       }
     }
@@ -88,8 +91,6 @@
       continue;
     }
 
-    // TODO(crbug.com/1131220): Set correct attributes once available in
-    // fuchsia::net::interfaces::Properties.
     const int kAttributes = 0;
     interfaces->emplace_back(
         properties_.name(), properties_.name(), properties_.id(),
@@ -136,17 +137,6 @@
   }
 }
 
-fuchsia::net::interfaces::WatcherHandle ConnectInterfacesWatcher() {
-  fuchsia::net::interfaces::StateSyncPtr state;
-  zx_status_t status =
-      base::ComponentContextForProcess()->svc()->Connect(state.NewRequest());
-  ZX_CHECK(status == ZX_OK, status) << "Connect()";
-
-  fuchsia::net::interfaces::WatcherHandle watcher;
-  state->GetWatcher({} /*options*/, watcher.NewRequest());
-  return watcher;
-}
-
 bool VerifyCompleteInterfaceProperties(
     const fuchsia::net::interfaces::Properties& properties) {
   if (!properties.has_id())
@@ -165,70 +155,40 @@
     return false;
   if (!properties.has_has_default_ipv6_route())
     return false;
-  return true;
-}
-
-absl::optional<ExistingInterfaceProperties> GetExistingInterfaces(
-    const fuchsia::net::interfaces::WatcherSyncPtr& watcher) {
-  ExistingInterfaceProperties existing_interfaces;
-  for (;;) {
-    fuchsia::net::interfaces::Event event;
-    zx_status_t status = watcher->Watch(&event);
-    if (status != ZX_OK) {
-      ZX_LOG(ERROR, status) << "GetExistingInterfaces: Watch() failed";
-      return absl::nullopt;
-    }
-
-    switch (event.Which()) {
-      case fuchsia::net::interfaces::Event::Tag::kExisting: {
-        absl::optional<InterfaceProperties> interface =
-            InterfaceProperties::VerifyAndCreate(std::move(event.existing()));
-        if (!interface) {
-          LOG(ERROR) << "GetExistingInterfaces: Invalid kExisting event.";
-          return absl::nullopt;
-        }
-        uint64_t id = interface->id();
-        existing_interfaces.emplace_back(id, std::move(*interface));
-        break;
-      }
-      case fuchsia::net::interfaces::Event::Tag::kIdle:
-        // Idle means we've listed all the existing interfaces. We can stop
-        // fetching events.
-        return existing_interfaces;
-      default:
-        LOG(ERROR) << "GetExistingInterfaces: Unexpected event received.";
-        return absl::nullopt;
-    }
+  if (!properties.has_name()) {
+    return false;
   }
+  return true;
 }
 
 }  // namespace internal
 
 bool GetNetworkList(NetworkInterfaceList* networks, int policy) {
   DCHECK(networks);
-  fuchsia::net::interfaces::WatcherHandle handle =
-      internal::ConnectInterfacesWatcher();
-  fuchsia::net::interfaces::WatcherSyncPtr watcher = handle.BindSync();
 
-  // TODO(crbug.com/1131238): Use NetworkChangeNotifier's cached interface
-  // list.
-  absl::optional<internal::ExistingInterfaceProperties> existing_interfaces =
-      internal::GetExistingInterfaces(watcher);
-  if (!existing_interfaces)
-    return false;
-  handle = watcher.Unbind();
-  for (const auto& interface_entry : *existing_interfaces) {
-    if (!interface_entry.second.online()) {
-      // GetNetworkList() only returns online interfaces.
-      continue;
-    }
-    if (interface_entry.second.device_class().is_loopback()) {
-      // GetNetworkList() returns all interfaces except loopback.
-      continue;
-    }
-    interface_entry.second.AppendNetworkInterfaces(networks);
+  const internal::NetworkInterfaceCache* cache_ptr =
+      NetworkChangeNotifier::GetNetworkInterfaceCache();
+  if (cache_ptr) {
+    return cache_ptr->GetOnlineInterfaces(networks);
   }
-  return true;
+
+  fuchsia::net::interfaces::WatcherHandle watcher_handle =
+      internal::ConnectInterfacesWatcher();
+  std::vector<fuchsia::net::interfaces::Properties> interfaces;
+
+  auto handle_or_status = internal::ReadExistingNetworkInterfacesFromNewWatcher(
+      std::move(watcher_handle), interfaces);
+  if (!handle_or_status.has_value()) {
+    return false;
+  }
+
+  internal::NetworkInterfaceCache temp_cache(/*require_wlan=*/false);
+  auto change_bits = temp_cache.AddInterfaces(std::move(interfaces));
+  if (!change_bits.has_value()) {
+    return false;
+  }
+
+  return temp_cache.GetOnlineInterfaces(networks);
 }
 
 std::string GetWifiSSID() {
diff --git a/net/base/network_interfaces_fuchsia.h b/net/base/network_interfaces_fuchsia.h
index 6ecc25d2..c758687 100644
--- a/net/base/network_interfaces_fuchsia.h
+++ b/net/base/network_interfaces_fuchsia.h
@@ -6,21 +6,21 @@
 #define NET_BASE_NETWORK_INTERFACES_FUCHSIA_H_
 
 #include <fuchsia/net/interfaces/cpp/fidl.h>
-
-#include <vector>
+#include <stdint.h>
 
 #include "net/base/network_change_notifier.h"
 #include "net/base/network_interfaces.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
-namespace net {
-namespace internal {
+namespace net::internal {
 
 // Move-only wrapper for fuchsia::net::interface::Properties that guarantees
 // that its inner |properties_| are valid and complete properties as reported by
 // |VerifyCompleteInterfaceProperties|.
 class InterfaceProperties final {
  public:
+  using InterfaceId = uint64_t;
+
   // Creates an |InterfaceProperties| if |properties| are valid complete
   // properties as reported by |VerifyCompleteInterfaceProperties|.
   static absl::optional<InterfaceProperties> VerifyAndCreate(
@@ -45,7 +45,7 @@
   bool IsPubliclyRoutable() const;
 
   bool HasAddresses() const { return !properties_.addresses().empty(); }
-  uint64_t id() const { return properties_.id(); }
+  InterfaceId id() const { return properties_.id(); }
   bool online() const { return properties_.online(); }
   const fuchsia::net::interfaces::DeviceClass& device_class() const {
     return properties_.device_class();
@@ -57,32 +57,16 @@
   fuchsia::net::interfaces::Properties properties_;
 };
 
-using ExistingInterfaceProperties =
-    std::vector<std::pair<uint64_t, InterfaceProperties>>;
-
 // Returns the //net ConnectionType for the supplied netstack interface
 // description. Returns CONNECTION_NONE for loopback interfaces.
 NetworkChangeNotifier::ConnectionType ConvertConnectionType(
     const fuchsia::net::interfaces::DeviceClass& device_class);
 
-// Connects to the service via the process' ComponentContext, and connects the
-// Watcher to the service.
-fuchsia::net::interfaces::WatcherHandle ConnectInterfacesWatcher();
-
 // Validates that |properties| contains all the required fields, returning
 // |true| if so.
 bool VerifyCompleteInterfaceProperties(
     const fuchsia::net::interfaces::Properties& properties);
 
-// Consumes events describing existing interfaces from |watcher| and
-// returns a vector of interface Id & properties pairs.  |watcher| must
-// be a newly-connected Watcher channel.
-// Returns absl::nullopt if any protocol error is encountered, e.g.
-// |watcher| supplies an invalid event, or disconnects.
-absl::optional<internal::ExistingInterfaceProperties> GetExistingInterfaces(
-    const fuchsia::net::interfaces::WatcherSyncPtr& watcher);
-
-}  // namespace internal
-}  // namespace net
+}  // namespace net::internal
 
 #endif  // NET_BASE_NETWORK_INTERFACES_FUCHSIA_H_
diff --git a/net/cert/internal/trust_store_nss.cc b/net/cert/internal/trust_store_nss.cc
index afe88375..4cf9659 100644
--- a/net/cert/internal/trust_store_nss.cc
+++ b/net/cert/internal/trust_store_nss.cc
@@ -9,6 +9,7 @@
 
 #include "base/logging.h"
 #include "crypto/nss_util.h"
+#include "net/base/features.h"
 #include "net/cert/known_roots_nss.h"
 #include "net/cert/pki/cert_errors.h"
 #include "net/cert/pki/parsed_certificate.h"
@@ -97,7 +98,7 @@
     return CertificateTrust::ForUnspecified();
   }
 
-  int trust_flags = SEC_GET_TRUST_FLAGS(&trust, trust_type_);
+  unsigned int trust_flags = SEC_GET_TRUST_FLAGS(&trust, trust_type_);
 
   // Determine if the certificate is distrusted.
   if ((trust_flags & (CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED_CA |
@@ -105,6 +106,9 @@
     return CertificateTrust::ForDistrusted();
   }
 
+  bool is_trusted_ca = false;
+  bool is_trusted_leaf = false;
+
   // Determine if the certificate is a trust anchor.
   //
   // We may not use the result of this if it is a known root and we're ignoring
@@ -120,12 +124,25 @@
     // handling this may require iterating all the slots and manually computing
     // the trust settings directly, rather than CERT_GetCertTrust.
     if (!ignore_system_trust_settings_ || !IsKnownRoot(nss_cert.get())) {
-      return CertificateTrust::ForTrustAnchor();
+      is_trusted_ca = true;
     }
   }
 
-  // Trusted server certs (CERTDB_TERMINAL_RECORD + CERTDB_TRUSTED) are
-  // intentionally treated as unspecified. See https://crbug.com/814994.
+  if (base::FeatureList::IsEnabled(features::kTrustStoreTrustedLeafSupport)) {
+    constexpr unsigned int kTrustedPeerBits =
+        CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
+    if ((trust_flags & kTrustedPeerBits) == kTrustedPeerBits) {
+      is_trusted_leaf = true;
+    }
+  }
+
+  if (is_trusted_ca && is_trusted_leaf) {
+    return CertificateTrust::ForTrustAnchorOrLeaf();
+  } else if (is_trusted_ca) {
+    return CertificateTrust::ForTrustAnchor();
+  } else if (is_trusted_leaf) {
+    return CertificateTrust::ForTrustedLeaf();
+  }
 
   return CertificateTrust::ForUnspecified();
 }
diff --git a/net/cert/internal/trust_store_nss_unittest.cc b/net/cert/internal/trust_store_nss_unittest.cc
index bac1e93..6df62e4 100644
--- a/net/cert/internal/trust_store_nss_unittest.cc
+++ b/net/cert/internal/trust_store_nss_unittest.cc
@@ -11,8 +11,10 @@
 #include <memory>
 
 #include "base/strings/string_number_conversions.h"
+#include "base/test/scoped_feature_list.h"
 #include "crypto/nss_util_internal.h"
 #include "crypto/scoped_test_nss_db.h"
+#include "net/base/features.h"
 #include "net/cert/known_roots_nss.h"
 #include "net/cert/pki/cert_issuer_source_sync_unittest.h"
 #include "net/cert/pki/parsed_certificate.h"
@@ -103,6 +105,37 @@
 
 class TrustStoreNSSTestBase : public ::testing::Test {
  public:
+  explicit TrustStoreNSSTestBase(bool trusted_leaf_support)
+      : trusted_leaf_support_(trusted_leaf_support) {
+    if (trusted_leaf_support) {
+      feature_list_.InitAndEnableFeature(
+          features::kTrustStoreTrustedLeafSupport);
+    } else {
+      feature_list_.InitAndDisableFeature(
+          features::kTrustStoreTrustedLeafSupport);
+    }
+  }
+
+  TrustStoreNSSTestBase() : TrustStoreNSSTestBase(true) {}
+
+  bool IsTrustedLeafSupportEnabled() const { return trusted_leaf_support_; }
+
+  CertificateTrust ExpectedTrustForAnchorOrLeaf() const {
+    if (IsTrustedLeafSupportEnabled()) {
+      return CertificateTrust::ForTrustAnchorOrLeaf();
+    } else {
+      return CertificateTrust::ForTrustAnchor();
+    }
+  }
+
+  CertificateTrust ExpectedTrustForLeaf() const {
+    if (IsTrustedLeafSupportEnabled()) {
+      return CertificateTrust::ForTrustedLeaf();
+    } else {
+      return CertificateTrust::ForUnspecified();
+    }
+  }
+
   void SetUp() override {
     ASSERT_TRUE(test_nssdb_.is_open());
     ASSERT_TRUE(other_test_nssdb_.is_open());
@@ -189,6 +222,13 @@
     ChangeCertTrust(cert, CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED);
   }
 
+  // Trusts |cert| as both a server and as a CA. Assumes the cert was already
+  // imported into NSS.
+  void TrustCaAndServerCert(const ParsedCertificate* cert) {
+    ChangeCertTrust(cert, CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED |
+                              CERTDB_TRUSTED_CA | CERTDB_VALID_CA);
+  }
+
   // Distrusts |cert|. Assumes the cert was already imported into NSS.
   void DistrustCert(const ParsedCertificate* cert) {
     ChangeCertTrust(cert, CERTDB_TERMINAL_RECORD);
@@ -271,6 +311,9 @@
     return success;
   }
 
+  base::test::ScopedFeatureList feature_list_;
+  const bool trusted_leaf_support_;
+
   std::shared_ptr<const ParsedCertificate> oldroot_;
   std::shared_ptr<const ParsedCertificate> newroot_;
 
@@ -354,9 +397,11 @@
                       SlotFilterType::kAllowSpecifiedUserSlot));
 
 // Tests a TrustStoreNSS that ignores system root certs.
-class TrustStoreNSSTestIgnoreSystemCerts : public TrustStoreNSSTestBase {
+class TrustStoreNSSTestIgnoreSystemCerts
+    : public TrustStoreNSSTestBase,
+      public testing::WithParamInterface<bool> {
  public:
-  TrustStoreNSSTestIgnoreSystemCerts() = default;
+  TrustStoreNSSTestIgnoreSystemCerts() : TrustStoreNSSTestBase(GetParam()) {}
   ~TrustStoreNSSTestIgnoreSystemCerts() override = default;
 
   std::unique_ptr<TrustStoreNSS> CreateTrustStoreNSS() override {
@@ -366,29 +411,53 @@
   }
 };
 
-TEST_F(TrustStoreNSSTestIgnoreSystemCerts, UserRootTrusted) {
+TEST_P(TrustStoreNSSTestIgnoreSystemCerts, UserRootTrusted) {
   AddCertsToNSS();
   TrustCert(newroot_.get());
   EXPECT_TRUE(HasTrust({newroot_}, ExpectedTrustForAnchor()));
 }
 
-TEST_F(TrustStoreNSSTestIgnoreSystemCerts, UserRootDistrusted) {
+TEST_P(TrustStoreNSSTestIgnoreSystemCerts, UserRootDistrusted) {
   AddCertsToNSS();
   DistrustCert(newroot_.get());
   EXPECT_TRUE(HasTrust({newroot_}, CertificateTrust::ForDistrusted()));
 }
 
-TEST_F(TrustStoreNSSTestIgnoreSystemCerts, SystemRootCertsIgnored) {
+TEST_P(TrustStoreNSSTestIgnoreSystemCerts, SystemRootCertsIgnored) {
   std::shared_ptr<const ParsedCertificate> system_root =
       GetASSLTrustedBuiltinRoot();
   ASSERT_TRUE(system_root);
   EXPECT_TRUE(HasTrust({system_root}, CertificateTrust::ForUnspecified()));
 }
 
+TEST_P(TrustStoreNSSTestIgnoreSystemCerts, UserTrustedServer) {
+  AddCertsToNSS();
+  TrustServerCert(target_.get());
+  EXPECT_TRUE(HasTrust({target_}, ExpectedTrustForLeaf()));
+}
+
+TEST_P(TrustStoreNSSTestIgnoreSystemCerts, UserTrustedCaAndServer) {
+  AddCertsToNSS();
+  TrustCaAndServerCert(target_.get());
+  EXPECT_TRUE(HasTrust({target_}, ExpectedTrustForAnchorOrLeaf()));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    TrustStoreNSSTestIgnoreSystemCerts,
+    testing::Values(true, false),
+    [](const testing::TestParamInfo<
+        TrustStoreNSSTestIgnoreSystemCerts::ParamType>& info) {
+      return info.param ? "TrustedLeafSupported" : "TrustAnchorOnly";
+    });
+
 // Tests a TrustStoreNSS that does not filter which certificates
-class TrustStoreNSSTestWithoutSlotFilter : public TrustStoreNSSTestBase {
+class TrustStoreNSSTestWithoutSlotFilter
+    : public TrustStoreNSSTestBase,
+      public testing::WithParamInterface<bool> {
  public:
-  TrustStoreNSSTestWithoutSlotFilter() = default;
+  TrustStoreNSSTestWithoutSlotFilter() : TrustStoreNSSTestBase(GetParam()) {}
+
   ~TrustStoreNSSTestWithoutSlotFilter() override = default;
 
   std::unique_ptr<TrustStoreNSS> CreateTrustStoreNSS() override {
@@ -400,7 +469,7 @@
 
 // If certs are present in NSS DB but aren't marked as trusted, should get no
 // anchor results for any of the test certs.
-TEST_F(TrustStoreNSSTestWithoutSlotFilter, CertsPresentButNotTrusted) {
+TEST_P(TrustStoreNSSTestWithoutSlotFilter, CertsPresentButNotTrusted) {
   AddCertsToNSS();
 
   // None of the certificates are trusted.
@@ -410,7 +479,7 @@
 }
 
 // Trust a single self-signed CA certificate.
-TEST_F(TrustStoreNSSTestWithoutSlotFilter, TrustedCA) {
+TEST_P(TrustStoreNSSTestWithoutSlotFilter, TrustedCA) {
   AddCertsToNSS();
   TrustCert(newroot_.get());
 
@@ -423,7 +492,7 @@
 }
 
 // Distrust a single self-signed CA certificate.
-TEST_F(TrustStoreNSSTestWithoutSlotFilter, DistrustedCA) {
+TEST_P(TrustStoreNSSTestWithoutSlotFilter, DistrustedCA) {
   AddCertsToNSS();
   DistrustCert(newroot_.get());
 
@@ -436,7 +505,7 @@
 }
 
 // Trust a single intermediate certificate.
-TEST_F(TrustStoreNSSTestWithoutSlotFilter, TrustedIntermediate) {
+TEST_P(TrustStoreNSSTestWithoutSlotFilter, TrustedIntermediate) {
   AddCertsToNSS();
   TrustCert(newintermediate_.get());
 
@@ -447,7 +516,7 @@
 }
 
 // Distrust a single intermediate certificate.
-TEST_F(TrustStoreNSSTestWithoutSlotFilter, DistrustedIntermediate) {
+TEST_P(TrustStoreNSSTestWithoutSlotFilter, DistrustedIntermediate) {
   AddCertsToNSS();
   DistrustCert(newintermediate_.get());
 
@@ -458,20 +527,29 @@
 }
 
 // Trust a single server certificate.
-TEST_F(TrustStoreNSSTestWithoutSlotFilter, TrustedServer) {
+TEST_P(TrustStoreNSSTestWithoutSlotFilter, TrustedServer) {
   AddCertsToNSS();
   TrustServerCert(target_.get());
 
-  // Server-trusted certificates are handled as UNSPECIFIED since we don't
-  // support the notion of explictly trusted server certs. See
-  // https://crbug.com/814994.
-  EXPECT_TRUE(HasTrust({oldroot_, newroot_, target_, oldintermediate_,
-                        newintermediate_, newrootrollover_},
+  EXPECT_TRUE(HasTrust({oldroot_, newroot_, oldintermediate_, newintermediate_,
+                        newrootrollover_},
                        CertificateTrust::ForUnspecified()));
+  EXPECT_TRUE(HasTrust({target_}, ExpectedTrustForLeaf()));
+}
+
+// Trust a single certificate with both CA and server trust bits.
+TEST_P(TrustStoreNSSTestWithoutSlotFilter, TrustedCaAndServer) {
+  AddCertsToNSS();
+  TrustCaAndServerCert(target_.get());
+
+  EXPECT_TRUE(HasTrust({oldroot_, newroot_, oldintermediate_, newintermediate_,
+                        newrootrollover_},
+                       CertificateTrust::ForUnspecified()));
+  EXPECT_TRUE(HasTrust({target_}, ExpectedTrustForAnchorOrLeaf()));
 }
 
 // Trust multiple self-signed CA certificates with the same name.
-TEST_F(TrustStoreNSSTestWithoutSlotFilter, MultipleTrustedCAWithSameSubject) {
+TEST_P(TrustStoreNSSTestWithoutSlotFilter, MultipleTrustedCAWithSameSubject) {
   AddCertsToNSS();
   TrustCert(oldroot_.get());
   TrustCert(newroot_.get());
@@ -484,7 +562,7 @@
 
 // Different trust settings for multiple self-signed CA certificates with the
 // same name.
-TEST_F(TrustStoreNSSTestWithoutSlotFilter, DifferingTrustCAWithSameSubject) {
+TEST_P(TrustStoreNSSTestWithoutSlotFilter, DifferingTrustCAWithSameSubject) {
   AddCertsToNSS();
   DistrustCert(oldroot_.get());
   TrustCert(newroot_.get());
@@ -496,6 +574,15 @@
   EXPECT_TRUE(HasTrust({newroot_}, ExpectedTrustForAnchor()));
 }
 
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    TrustStoreNSSTestWithoutSlotFilter,
+    testing::Values(true, false),
+    [](const testing::TestParamInfo<
+        TrustStoreNSSTestWithoutSlotFilter::ParamType>& info) {
+      return info.param ? "TrustedLeafSupported" : "TrustAnchorOnly";
+    });
+
 // Tests for a TrustStoreNSS which does not allow certificates on user slots
 // to be trusted.
 class TrustStoreNSSTestDoNotAllowUserSlots : public TrustStoreNSSTestBase {
diff --git a/net/cert/nss_cert_database_unittest.cc b/net/cert/nss_cert_database_unittest.cc
index 0aed43c..7227e1b 100644
--- a/net/cert/nss_cert_database_unittest.cc
+++ b/net/cert/nss_cert_database_unittest.cc
@@ -22,6 +22,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "crypto/scoped_nss_types.h"
 #include "crypto/scoped_test_nss_db.h"
+#include "net/base/features.h"
 #include "net/base/hash_value.h"
 #include "net/base/net_errors.h"
 #include "net/cert/cert_net_fetcher.h"
@@ -655,9 +656,13 @@
       x509_puny_cert.get(), "xn--wgv71a119e.com",
       /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags,
       crl_set_.get(), empty_cert_list_, &verify_result, NetLogWithSource());
-  // New verifier does not support server cert trust records.
-  EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
-  EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result.cert_status);
+  if (base::FeatureList::IsEnabled(features::kTrustStoreTrustedLeafSupport)) {
+    EXPECT_THAT(error, IsOk());
+    EXPECT_EQ(0U, verify_result.cert_status);
+  } else {
+    EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
+    EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result.cert_status);
+  }
 }
 
 TEST_F(CertDatabaseNSSTest, ImportCaAndServerCert) {
diff --git a/net/disk_cache/simple/simple_index_unittest.cc b/net/disk_cache/simple/simple_index_unittest.cc
index 03d744c8..1af3249 100644
--- a/net/disk_cache/simple/simple_index_unittest.cc
+++ b/net/disk_cache/simple/simple_index_unittest.cc
@@ -90,7 +90,11 @@
     entry_set->swap(disk_write_entry_set_);
   }
 
-  base::OnceClosure TakeLoadCallback() { return std::move(load_callback_); }
+  void RunLoadCallback() {
+    // Clear dangling reference since callback may destroy `load_result_`.
+    load_result_ = nullptr;
+    std::move(load_callback_).Run();
+  }
   SimpleIndexLoadResult* load_result() const { return load_result_; }
   int load_index_entries_calls() const { return load_index_entries_calls_; }
   int disk_writes() const { return disk_writes_; }
@@ -159,7 +163,7 @@
 
   void ReturnIndexFile() {
     index_file_->load_result()->did_load = true;
-    index_file_->TakeLoadCallback().Run();
+    index_file_->RunLoadCallback();
   }
 
   // Non-const for timer manipulation.
diff --git a/net/http/http_auth_cache_unittest.cc b/net/http/http_auth_cache_unittest.cc
index 42bc72e..5218639 100644
--- a/net/http/http_auth_cache_unittest.cc
+++ b/net/http/http_auth_cache_unittest.cc
@@ -1135,6 +1135,8 @@
     CheckRealmExistence(i + 3, true);
     test_clock.Advance(base::Seconds(1));
   }
+
+  cache_.set_tick_clock_for_testing(nullptr);
 }
 
 // Add the maximum number of paths to a single realm entry. Each of these
diff --git a/net/test/android/javatests/src/org/chromium/net/test/DummySpnegoAuthenticator.java b/net/test/android/javatests/src/org/chromium/net/test/DummySpnegoAuthenticator.java
index 52c4822..1a82357 100644
--- a/net/test/android/javatests/src/org/chromium/net/test/DummySpnegoAuthenticator.java
+++ b/net/test/android/javatests/src/org/chromium/net/test/DummySpnegoAuthenticator.java
@@ -18,6 +18,7 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.base.annotations.NativeClassQualifiedName;
+import org.chromium.base.annotations.NativeMethods;
 import org.chromium.net.HttpNegotiateConstants;
 
 import java.io.IOException;
@@ -69,20 +70,22 @@
     @Override
     public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
             String authTokenType, Bundle options) {
-        long nativeQuery = nativeGetNextQuery(sNativeDummySpnegoAuthenticator);
+        long nativeQuery =
+                DummySpnegoAuthenticatorJni.get().getNextQuery(sNativeDummySpnegoAuthenticator);
         String incomingToken = options.getString(HttpNegotiateConstants.KEY_INCOMING_AUTH_TOKEN);
-        nativeCheckGetTokenArguments(nativeQuery, incomingToken);
+        DummySpnegoAuthenticatorJni.get().checkGetTokenArguments(nativeQuery, incomingToken);
         Bundle result = new Bundle();
         result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
         result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
-        result.putString(AccountManager.KEY_AUTHTOKEN, nativeGetTokenToReturn(nativeQuery));
+        result.putString(AccountManager.KEY_AUTHTOKEN,
+                DummySpnegoAuthenticatorJni.get().getTokenToReturn(nativeQuery));
         result.putInt(HttpNegotiateConstants.KEY_SPNEGO_RESULT,
-                decodeResult(nativeGetResult(nativeQuery)));
+                decodeResult(DummySpnegoAuthenticatorJni.get().getResult(nativeQuery)));
         return result;
     }
 
     /**
-     * @param nativeGetResult
+     * @param DummySpnegoAuthenticatorJni.get().getResult
      * @return
      */
     private int decodeResult(int gssApiResult) {
@@ -162,22 +165,25 @@
         sNativeDummySpnegoAuthenticator = nativeDummySpnegoAuthenticator;
     }
 
-    /**
-     * Send the relevant decoded arguments of getAuthToken to C++ for checking by googletest checks
-     * If the checks fail then the C++ unit test using this authenticator will fail.
-     *
-     * @param authTokenType
-     * @param spn
-     * @param incomingToken
-     */
-    @NativeClassQualifiedName("DummySpnegoAuthenticator::SecurityContextQuery")
-    private native void nativeCheckGetTokenArguments(long nativeQuery, String incomingToken);
+    @NativeMethods
+    interface Natives {
+        /**
+         * Send the relevant decoded arguments of getAuthToken to C++ for checking by googletest
+         * checks If the checks fail then the C++ unit test using this authenticator will fail.
+         *
+         * @param authTokenType
+         * @param spn
+         * @param incomingToken
+         */
+        @NativeClassQualifiedName("DummySpnegoAuthenticator::SecurityContextQuery")
+        void checkGetTokenArguments(long nativeQuery, String incomingToken);
 
-    @NativeClassQualifiedName("DummySpnegoAuthenticator::SecurityContextQuery")
-    private native String nativeGetTokenToReturn(long nativeQuery);
+        @NativeClassQualifiedName("DummySpnegoAuthenticator::SecurityContextQuery")
+        String getTokenToReturn(long nativeQuery);
 
-    @NativeClassQualifiedName("DummySpnegoAuthenticator::SecurityContextQuery")
-    private native int nativeGetResult(long nativeQuery);
+        @NativeClassQualifiedName("DummySpnegoAuthenticator::SecurityContextQuery")
+        int getResult(long nativeQuery);
 
-    private native long nativeGetNextQuery(long nativeDummySpnegoAuthenticator);
+        long getNextQuery(long nativeDummySpnegoAuthenticator);
+    }
 }
diff --git a/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerImpl.java b/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerImpl.java
index af78d789..6c818e3 100644
--- a/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerImpl.java
+++ b/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerImpl.java
@@ -14,6 +14,7 @@
 import org.chromium.base.Log;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.library_loader.LibraryProcessType;
 import org.chromium.base.test.util.UrlUtils;
@@ -79,7 +80,8 @@
             @Override
             public Void call() {
                 if (mNativeEmbeddedTestServer == 0) {
-                    nativeInit(UrlUtils.getIsolatedTestRoot(), https);
+                    EmbeddedTestServerImplJni.get().init(
+                            EmbeddedTestServerImpl.this, UrlUtils.getIsolatedTestRoot(), https);
                 }
                 assert mNativeEmbeddedTestServer != 0;
                 return null;
@@ -102,7 +104,7 @@
         return runOnHandlerThread(new Callable<Boolean>() {
             @Override
             public Boolean call() {
-                return nativeStart(mNativeEmbeddedTestServer, port);
+                return EmbeddedTestServerImplJni.get().start(mNativeEmbeddedTestServer, port);
             }
         });
     }
@@ -116,7 +118,8 @@
         return runOnHandlerThread(new Callable<String>() {
             @Override
             public String call() {
-                return nativeGetRootCertPemPath(mNativeEmbeddedTestServer);
+                return EmbeddedTestServerImplJni.get().getRootCertPemPath(
+                        mNativeEmbeddedTestServer);
             }
         });
     }
@@ -132,7 +135,8 @@
         runOnHandlerThread(new Callable<Void>() {
             @Override
             public Void call() {
-                nativeAddDefaultHandlers(mNativeEmbeddedTestServer, directoryPath);
+                EmbeddedTestServerImplJni.get().addDefaultHandlers(
+                        mNativeEmbeddedTestServer, directoryPath);
                 return null;
             }
         });
@@ -147,7 +151,8 @@
         runOnHandlerThread(new Callable<Void>() {
             @Override
             public Void call() {
-                nativeSetSSLConfig(mNativeEmbeddedTestServer, serverCertificate);
+                EmbeddedTestServerImplJni.get().setSSLConfig(
+                        mNativeEmbeddedTestServer, serverCertificate);
                 return null;
             }
         });
@@ -162,7 +167,8 @@
         runOnHandlerThread(new Callable<Void>() {
             @Override
             public Void call() {
-                nativeRegisterRequestHandler(mNativeEmbeddedTestServer, handler);
+                EmbeddedTestServerImplJni.get().registerRequestHandler(
+                        mNativeEmbeddedTestServer, handler);
                 return null;
             }
         });
@@ -177,7 +183,8 @@
         runOnHandlerThread(new Callable<Void>() {
             @Override
             public Void call() {
-                nativeServeFilesFromDirectory(mNativeEmbeddedTestServer, directoryPath);
+                EmbeddedTestServerImplJni.get().serveFilesFromDirectory(
+                        mNativeEmbeddedTestServer, directoryPath);
                 return null;
             }
         });
@@ -210,7 +217,8 @@
         return runOnHandlerThread(new Callable<String>() {
             @Override
             public String call() {
-                return nativeGetURL(mNativeEmbeddedTestServer, relativeUrl);
+                return EmbeddedTestServerImplJni.get().getURL(
+                        mNativeEmbeddedTestServer, relativeUrl);
             }
         });
     }
@@ -227,7 +235,8 @@
         return runOnHandlerThread(new Callable<String>() {
             @Override
             public String call() {
-                return nativeGetURLWithHostName(mNativeEmbeddedTestServer, hostName, relativeUrl);
+                return EmbeddedTestServerImplJni.get().getURLWithHostName(
+                        mNativeEmbeddedTestServer, hostName, relativeUrl);
             }
         });
     }
@@ -241,7 +250,8 @@
         return runOnHandlerThread(new Callable<Boolean>() {
             @Override
             public Boolean call() {
-                return nativeShutdownAndWaitUntilComplete(mNativeEmbeddedTestServer);
+                return EmbeddedTestServerImplJni.get().shutdownAndWaitUntilComplete(
+                        mNativeEmbeddedTestServer);
             }
         });
     }
@@ -253,7 +263,7 @@
             @Override
             public Void call() {
                 assert mNativeEmbeddedTestServer != 0;
-                nativeDestroy(mNativeEmbeddedTestServer);
+                EmbeddedTestServerImplJni.get().destroy(mNativeEmbeddedTestServer);
                 assert mNativeEmbeddedTestServer == 0;
                 return null;
             }
@@ -309,20 +319,19 @@
         mNativeEmbeddedTestServer = 0;
     }
 
-    private native void nativeInit(String testDataDir, boolean https);
-    private native void nativeDestroy(long nativeEmbeddedTestServerAndroid);
-    private native boolean nativeStart(long nativeEmbeddedTestServerAndroid, int port);
-    private native String nativeGetRootCertPemPath(long nativeEmbeddedTestServerAndroid);
-    private native boolean nativeShutdownAndWaitUntilComplete(long nativeEmbeddedTestServerAndroid);
-    private native void nativeAddDefaultHandlers(
-            long nativeEmbeddedTestServerAndroid, String directoryPath);
-    private native void nativeSetSSLConfig(
-            long nativeEmbeddedTestServerAndroid, int serverCertificate);
-    private native void nativeRegisterRequestHandler(
-            long nativeEmbeddedTestServerAndroid, long handler);
-    private native String nativeGetURL(long nativeEmbeddedTestServerAndroid, String relativeUrl);
-    private native String nativeGetURLWithHostName(
-            long nativeEmbeddedTestServerAndroid, String hostName, String relativeUrl);
-    private native void nativeServeFilesFromDirectory(
-            long nativeEmbeddedTestServerAndroid, String directoryPath);
+    @NativeMethods
+    interface Natives {
+        void init(EmbeddedTestServerImpl obj, String testDataDir, boolean https);
+        void destroy(long nativeEmbeddedTestServerAndroid);
+        boolean start(long nativeEmbeddedTestServerAndroid, int port);
+        String getRootCertPemPath(long nativeEmbeddedTestServerAndroid);
+        boolean shutdownAndWaitUntilComplete(long nativeEmbeddedTestServerAndroid);
+        void addDefaultHandlers(long nativeEmbeddedTestServerAndroid, String directoryPath);
+        void setSSLConfig(long nativeEmbeddedTestServerAndroid, int serverCertificate);
+        void registerRequestHandler(long nativeEmbeddedTestServerAndroid, long handler);
+        String getURL(long nativeEmbeddedTestServerAndroid, String relativeUrl);
+        String getURLWithHostName(
+                long nativeEmbeddedTestServerAndroid, String hostName, String relativeUrl);
+        void serveFilesFromDirectory(long nativeEmbeddedTestServerAndroid, String directoryPath);
+    }
 }
diff --git a/net/test/embedded_test_server/android/embedded_test_server_android.cc b/net/test/embedded_test_server/android/embedded_test_server_android.cc
index 2637e1a7..aaa6323e 100644
--- a/net/test/embedded_test_server/android/embedded_test_server_android.cc
+++ b/net/test/embedded_test_server/android/embedded_test_server_android.cc
@@ -59,28 +59,22 @@
   Java_EmbeddedTestServerImpl_clearNativePtr(env, weak_java_server_.get(env));
 }
 
-jboolean EmbeddedTestServerAndroid::Start(JNIEnv* env,
-                                          const JavaParamRef<jobject>& jobj,
-                                          jint port) {
+jboolean EmbeddedTestServerAndroid::Start(JNIEnv* env, jint port) {
   return test_server_.Start(static_cast<int>(port));
 }
 
 ScopedJavaLocalRef<jstring> EmbeddedTestServerAndroid::GetRootCertPemPath(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& jobj) const {
+    JNIEnv* env) const {
   return base::android::ConvertUTF8ToJavaString(
       env, test_server_.GetRootCertPemPath().value());
 }
 
-jboolean EmbeddedTestServerAndroid::ShutdownAndWaitUntilComplete(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& jobj) {
+jboolean EmbeddedTestServerAndroid::ShutdownAndWaitUntilComplete(JNIEnv* env) {
   return test_server_.ShutdownAndWaitUntilComplete();
 }
 
 ScopedJavaLocalRef<jstring> EmbeddedTestServerAndroid::GetURL(
     JNIEnv* env,
-    const JavaParamRef<jobject>& jobj,
     const JavaParamRef<jstring>& jrelative_url) const {
   const GURL gurl(test_server_.GetURL(
       base::android::ConvertJavaStringToUTF8(env, jrelative_url)));
@@ -89,7 +83,6 @@
 
 ScopedJavaLocalRef<jstring> EmbeddedTestServerAndroid::GetURLWithHostName(
     JNIEnv* env,
-    const JavaParamRef<jobject>& jobj,
     const JavaParamRef<jstring>& jhostname,
     const JavaParamRef<jstring>& jrelative_url) const {
   const GURL gurl(test_server_.GetURL(
@@ -100,7 +93,6 @@
 
 void EmbeddedTestServerAndroid::AddDefaultHandlers(
     JNIEnv* env,
-    const JavaParamRef<jobject>& jobj,
     const JavaParamRef<jstring>& jdirectory_path) {
   const base::FilePath directory(
       base::android::ConvertJavaStringToUTF8(env, jdirectory_path));
@@ -108,7 +100,6 @@
 }
 
 void EmbeddedTestServerAndroid::SetSSLConfig(JNIEnv* jenv,
-                                             const JavaParamRef<jobject>& jobj,
                                              jint jserver_certificate) {
   test_server_.SetSSLConfig(
       static_cast<EmbeddedTestServer::ServerCertificate>(jserver_certificate));
@@ -117,17 +108,14 @@
 typedef std::unique_ptr<HttpResponse> (*HandleRequestPtr)(
     const HttpRequest& request);
 
-void EmbeddedTestServerAndroid::RegisterRequestHandler(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& jobj,
-    jlong handler) {
+void EmbeddedTestServerAndroid::RegisterRequestHandler(JNIEnv* env,
+                                                       jlong handler) {
   HandleRequestPtr handler_ptr = reinterpret_cast<HandleRequestPtr>(handler);
   test_server_.RegisterRequestHandler(base::BindRepeating(handler_ptr));
 }
 
 void EmbeddedTestServerAndroid::ServeFilesFromDirectory(
     JNIEnv* env,
-    const JavaParamRef<jobject>& jobj,
     const JavaParamRef<jstring>& jdirectory_path) {
   const base::FilePath directory(
       base::android::ConvertJavaStringToUTF8(env, jdirectory_path));
@@ -146,8 +134,7 @@
       env, weak_java_server_.get(env), reinterpret_cast<intptr_t>(socket_id));
 }
 
-void EmbeddedTestServerAndroid::Destroy(JNIEnv* env,
-                                        const JavaParamRef<jobject>& jobj) {
+void EmbeddedTestServerAndroid::Destroy(JNIEnv* env) {
   delete this;
 }
 
diff --git a/net/test/embedded_test_server/android/embedded_test_server_android.h b/net/test/embedded_test_server/android/embedded_test_server_android.h
index 58a91ac..d0f2825f 100644
--- a/net/test/embedded_test_server/android/embedded_test_server_android.h
+++ b/net/test/embedded_test_server/android/embedded_test_server_android.h
@@ -30,47 +30,34 @@
 
   ~EmbeddedTestServerAndroid();
 
-  void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void Destroy(JNIEnv* env);
 
-  jboolean Start(JNIEnv* env,
-                 const base::android::JavaParamRef<jobject>& jobj,
-                 jint port);
+  jboolean Start(JNIEnv* env, jint port);
 
   base::android::ScopedJavaLocalRef<jstring> GetRootCertPemPath(
-      JNIEnv* jenv,
-      const base::android::JavaParamRef<jobject>& jobj) const;
+      JNIEnv* jenv) const;
 
-  jboolean ShutdownAndWaitUntilComplete(
-      JNIEnv* env,
-      const base::android::JavaParamRef<jobject>& jobj);
+  jboolean ShutdownAndWaitUntilComplete(JNIEnv* env);
 
   base::android::ScopedJavaLocalRef<jstring> GetURL(
       JNIEnv* jenv,
-      const base::android::JavaParamRef<jobject>& jobj,
       const base::android::JavaParamRef<jstring>& jrelative_url) const;
 
   base::android::ScopedJavaLocalRef<jstring> GetURLWithHostName(
       JNIEnv* jenv,
-      const base::android::JavaParamRef<jobject>& jobj,
       const base::android::JavaParamRef<jstring>& jhostname,
       const base::android::JavaParamRef<jstring>& jrelative_url) const;
 
   void AddDefaultHandlers(
       JNIEnv* jenv,
-      const base::android::JavaParamRef<jobject>& jobj,
       const base::android::JavaParamRef<jstring>& jdirectory_path);
 
-  void SetSSLConfig(JNIEnv* jenv,
-                    const base::android::JavaParamRef<jobject>& jobj,
-                    jint jserver_certificate);
+  void SetSSLConfig(JNIEnv* jenv, jint jserver_certificate);
 
-  void RegisterRequestHandler(JNIEnv* jenv,
-                              const base::android::JavaParamRef<jobject>& jobj,
-                              jlong handler);
+  void RegisterRequestHandler(JNIEnv* jenv, jlong handler);
 
   void ServeFilesFromDirectory(
       JNIEnv* env,
-      const base::android::JavaParamRef<jobject>& jobj,
       const base::android::JavaParamRef<jstring>& jdirectory_path);
 
  private:
diff --git a/remoting/host/linux/linux_me2me_host.py b/remoting/host/linux/linux_me2me_host.py
index 153df79..a9f7b37 100755
--- a/remoting/host/linux/linux_me2me_host.py
+++ b/remoting/host/linux/linux_me2me_host.py
@@ -765,7 +765,7 @@
   """Manage a single virtual wayland based desktop"""
 
   WL_SOCKET_CHECK_DELAY_SECONDS = 1
-  WL_SOCKET_CHECK_TIMEOUT_SECONDS = 30
+  WL_SOCKET_CHECK_TIMEOUT_SECONDS = 5
   WL_SERVER_REPLY_TIMEOUT_SECONDS = 1
   # We scan for the unused socket starting from number 1. If we are not able to
   # find anything between 1 and 100 then we error out since there could be a
@@ -875,11 +875,15 @@
     """
     full_socket_path = os.path.join(self.runtime_dir, self._wayland_socket)
     start_time = time.time()
-    while not (os.path.exists(full_socket_path) and
-               time.time() - start_time < self.WL_SOCKET_CHECK_TIMEOUT_SECONDS):
+    while not os.path.exists(full_socket_path):
+      time_passed = time.time() - start_time
+      if time_passed >= self.WL_SOCKET_CHECK_TIMEOUT_SECONDS:
+        break
       logging.info("Wayland socket not yet present. Will wait for %s seconds "
-                   "for compositor to create it" %
-                   self.WL_SOCKET_CHECK_DELAY_SECONDS)
+                   "for compositor to create it (remaining wait time: %s "
+                   "seconds)" %
+                   (self.WL_SOCKET_CHECK_DELAY_SECONDS,
+                    int(self.WL_SOCKET_CHECK_TIMEOUT_SECONDS - time_passed)))
       time.sleep(self.WL_SOCKET_CHECK_DELAY_SECONDS)
     if not os.path.exists(full_socket_path):
       logging.error("Waited for wayland compositor to create wayland "
@@ -898,7 +902,7 @@
     """
     if not self._wait_for_wayland_compositor_running():
       logging.error("Aborting wayland session since compositor isn't running")
-      return
+      sys.exit(1)
     logging.info("Wayland compositor is running, restarting the portal "
                  "services now")
     try:
diff --git a/sandbox/win/BUILD.gn b/sandbox/win/BUILD.gn
index bae80a31..174200e 100644
--- a/sandbox/win/BUILD.gn
+++ b/sandbox/win/BUILD.gn
@@ -171,7 +171,10 @@
     "//base:base_static",
   ]
 
-  libs = [ "userenv.lib" ]
+  libs = [
+    "ntdll.lib",
+    "userenv.lib",
+  ]
 }
 
 test("sbox_integration_tests") {
diff --git a/sandbox/win/src/file_policy_test.cc b/sandbox/win/src/file_policy_test.cc
index d1ec2e3..a28f5bd 100644
--- a/sandbox/win/src/file_policy_test.cc
+++ b/sandbox/win/src/file_policy_test.cc
@@ -8,6 +8,7 @@
 #include <ntstatus.h>
 #include <windows.h>
 #include <winioctl.h>
+#include <winternl.h>
 
 #include "base/win/scoped_handle.h"
 #include "sandbox/win/src/filesystem_policy.h"
@@ -101,9 +102,9 @@
 // call succeeded or not.
 SBOX_TESTS_COMMAND int File_CreateSys32(int argc, wchar_t** argv) {
   BINDNTDLL(NtCreateFile);
-  BINDNTDLL(RtlInitUnicodeString);
-  if (!NtCreateFile || !RtlInitUnicodeString)
+  if (!NtCreateFile) {
     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+  }
 
   if (argc != 1)
     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
@@ -113,7 +114,7 @@
     file = MakePathToSys(argv[0], true);
 
   UNICODE_STRING object_name;
-  RtlInitUnicodeString(&object_name, file.c_str());
+  ::RtlInitUnicodeString(&object_name, file.c_str());
 
   OBJECT_ATTRIBUTES obj_attributes = {};
   InitializeObjectAttributes(&obj_attributes, &object_name,
@@ -139,16 +140,16 @@
 // call succeeded or not.
 SBOX_TESTS_COMMAND int File_OpenSys32(int argc, wchar_t** argv) {
   BINDNTDLL(NtOpenFile);
-  BINDNTDLL(RtlInitUnicodeString);
-  if (!NtOpenFile || !RtlInitUnicodeString)
+  if (!NtOpenFile) {
     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+  }
 
   if (argc != 1)
     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
 
   std::wstring file = MakePathToSys(argv[0], true);
   UNICODE_STRING object_name;
-  RtlInitUnicodeString(&object_name, file.c_str());
+  ::RtlInitUnicodeString(&object_name, file.c_str());
 
   OBJECT_ATTRIBUTES obj_attributes = {};
   InitializeObjectAttributes(&obj_attributes, &object_name,
@@ -215,10 +216,9 @@
 SBOX_TESTS_COMMAND int File_QueryAttributes(int argc, wchar_t** argv) {
   BINDNTDLL(NtQueryAttributesFile);
   BINDNTDLL(NtQueryFullAttributesFile);
-  BINDNTDLL(RtlInitUnicodeString);
-  if (!NtQueryAttributesFile || !NtQueryFullAttributesFile ||
-      !RtlInitUnicodeString)
+  if (!NtQueryAttributesFile || !NtQueryFullAttributesFile) {
     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+  }
 
   if (argc != 2)
     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
@@ -227,7 +227,7 @@
 
   UNICODE_STRING object_name;
   std::wstring file = MakePathToSys(argv[0], true);
-  RtlInitUnicodeString(&object_name, file.c_str());
+  ::RtlInitUnicodeString(&object_name, file.c_str());
 
   OBJECT_ATTRIBUTES obj_attributes = {};
   InitializeObjectAttributes(&obj_attributes, &object_name,
diff --git a/sandbox/win/src/ipc_leak_test.cc b/sandbox/win/src/ipc_leak_test.cc
index 696f001..44db9aa 100644
--- a/sandbox/win/src/ipc_leak_test.cc
+++ b/sandbox/win/src/ipc_leak_test.cc
@@ -5,6 +5,7 @@
 #include <ntstatus.h>
 #include <stdlib.h>
 #include <windows.h>
+#include <winternl.h>
 
 #include <memory>
 
@@ -24,10 +25,6 @@
 #include "sandbox/win/tests/common/controller.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#define BINDNTDLL(name)                                   \
-  name##Function name = reinterpret_cast<name##Function>( \
-      ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), #name));
-
 namespace sandbox {
 
 namespace {
@@ -95,7 +92,6 @@
   OBJECT_ATTRIBUTES attr;
   IO_STATUS_BLOCK iosb;
   HANDLE handle = INVALID_HANDLE_VALUE;
-  BINDNTDLL(RtlInitUnicodeString);
   RtlInitUnicodeString(&path_str, L"\\??\\leak");
   InitializeObjectAttributes(&attr, &path_str, OBJ_CASE_INSENSITIVE, nullptr,
                              nullptr);
@@ -123,7 +119,6 @@
   OBJECT_ATTRIBUTES attr;
   IO_STATUS_BLOCK iosb;
   HANDLE handle = INVALID_HANDLE_VALUE;
-  BINDNTDLL(RtlInitUnicodeString);
   RtlInitUnicodeString(&path_str, L"\\??\\leak");
   InitializeObjectAttributes(&attr, &path_str, OBJ_CASE_INSENSITIVE, nullptr,
                              nullptr);
diff --git a/sandbox/win/src/nt_internals.h b/sandbox/win/src/nt_internals.h
index d14282d..b7ac166 100644
--- a/sandbox/win/src/nt_internals.h
+++ b/sandbox/win/src/nt_internals.h
@@ -171,10 +171,7 @@
 constexpr auto ProcessInformationAccessToken = static_cast<PROCESSINFOCLASS>(9);
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wenum-constexpr-conversion"
-// constexpr auto ProcessExecuteFlags = static_cast<PROCESSINFOCLASS>(34);
 constexpr auto ProcessHandleTable = static_cast<PROCESSINFOCLASS>(58);
-constexpr auto ProcessCommandLineInformation =
-    static_cast<PROCESSINFOCLASS>(60);
 #pragma clang diagnostic pop
 
 // Partial definition only adding fields not in winternl.h, from
@@ -244,108 +241,6 @@
     OUT PHANDLE Thread,
     OUT PCLIENT_ID ClientId);
 
-typedef VOID(WINAPI* RtlFreeUnicodeStringFunction)(
-    IN OUT PUNICODE_STRING UnicodeString);
-
-// -----------------------------------------------------------------------
-// Registry
-
-typedef enum _KEY_INFORMATION_CLASS {
-  KeyBasicInformation = 0,
-  KeyFullInformation = 2
-} KEY_INFORMATION_CLASS,
-    *PKEY_INFORMATION_CLASS;
-
-typedef struct _KEY_BASIC_INFORMATION {
-  LARGE_INTEGER LastWriteTime;
-  ULONG TitleIndex;
-  ULONG NameLength;
-  WCHAR Name[1];
-} KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION;
-
-typedef struct _KEY_FULL_INFORMATION {
-  LARGE_INTEGER LastWriteTime;
-  ULONG TitleIndex;
-  ULONG ClassOffset;
-  ULONG ClassLength;
-  ULONG SubKeys;
-  ULONG MaxNameLen;
-  ULONG MaxClassLen;
-  ULONG Values;
-  ULONG MaxValueNameLen;
-  ULONG MaxValueDataLen;
-  WCHAR Class[1];
-} KEY_FULL_INFORMATION, *PKEY_FULL_INFORMATION;
-
-typedef enum _KEY_VALUE_INFORMATION_CLASS {
-  KeyValueFullInformation = 1
-} KEY_VALUE_INFORMATION_CLASS,
-    *PKEY_VALUE_INFORMATION_CLASS;
-
-typedef struct _KEY_VALUE_FULL_INFORMATION {
-  ULONG TitleIndex;
-  ULONG Type;
-  ULONG DataOffset;
-  ULONG DataLength;
-  ULONG NameLength;
-  WCHAR Name[1];
-} KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION;
-
-typedef NTSTATUS(WINAPI* NtCreateKeyFunction)(OUT PHANDLE KeyHandle,
-                                              IN ACCESS_MASK DesiredAccess,
-                                              IN POBJECT_ATTRIBUTES
-                                                  ObjectAttributes,
-                                              IN ULONG TitleIndex,
-                                              IN PUNICODE_STRING Class OPTIONAL,
-                                              IN ULONG CreateOptions,
-                                              OUT PULONG Disposition OPTIONAL);
-
-typedef NTSTATUS(WINAPI* NtOpenKeyFunction)(OUT PHANDLE KeyHandle,
-                                            IN ACCESS_MASK DesiredAccess,
-                                            IN POBJECT_ATTRIBUTES
-                                                ObjectAttributes);
-
-typedef NTSTATUS(WINAPI* NtOpenKeyExFunction)(OUT PHANDLE KeyHandle,
-                                              IN ACCESS_MASK DesiredAccess,
-                                              IN POBJECT_ATTRIBUTES
-                                                  ObjectAttributes,
-                                              IN DWORD open_options);
-
-typedef NTSTATUS(WINAPI* NtDeleteKeyFunction)(IN HANDLE KeyHandle);
-
-typedef NTSTATUS(WINAPI* RtlFormatCurrentUserKeyPathFunction)(
-    OUT PUNICODE_STRING RegistryPath);
-
-typedef NTSTATUS(WINAPI* NtQueryKeyFunction)(IN HANDLE KeyHandle,
-                                             IN KEY_INFORMATION_CLASS
-                                                 KeyInformationClass,
-                                             OUT PVOID KeyInformation,
-                                             IN ULONG Length,
-                                             OUT PULONG ResultLength);
-
-typedef NTSTATUS(WINAPI* NtEnumerateKeyFunction)(IN HANDLE KeyHandle,
-                                                 IN ULONG Index,
-                                                 IN KEY_INFORMATION_CLASS
-                                                     KeyInformationClass,
-                                                 OUT PVOID KeyInformation,
-                                                 IN ULONG Length,
-                                                 OUT PULONG ResultLength);
-
-typedef NTSTATUS(WINAPI* NtQueryValueKeyFunction)(IN HANDLE KeyHandle,
-                                                  IN PUNICODE_STRING ValueName,
-                                                  IN KEY_VALUE_INFORMATION_CLASS
-                                                      KeyValueInformationClass,
-                                                  OUT PVOID KeyValueInformation,
-                                                  IN ULONG Length,
-                                                  OUT PULONG ResultLength);
-
-typedef NTSTATUS(WINAPI* NtSetValueKeyFunction)(IN HANDLE KeyHandle,
-                                                IN PUNICODE_STRING ValueName,
-                                                IN ULONG TitleIndex OPTIONAL,
-                                                IN ULONG Type,
-                                                IN PVOID Data,
-                                                IN ULONG DataSize);
-
 // -----------------------------------------------------------------------
 // Memory
 
@@ -520,10 +415,6 @@
     IN PCUNICODE_STRING String2,
     IN BOOLEAN CaseInSensitive);
 
-typedef VOID(WINAPI* RtlInitUnicodeStringFunction)(IN OUT PUNICODE_STRING
-                                                       DestinationString,
-                                                   IN PCWSTR SourceString);
-
 typedef ULONG(WINAPI* RtlNtStatusToDosErrorFunction)(NTSTATUS status);
 
 #endif  // SANDBOX_WIN_SRC_NT_INTERNALS_H__
diff --git a/sandbox/win/src/sandbox_nt_util_unittest.cc b/sandbox/win/src/sandbox_nt_util_unittest.cc
index 749a6753..cd06021 100644
--- a/sandbox/win/src/sandbox_nt_util_unittest.cc
+++ b/sandbox/win/src/sandbox_nt_util_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <ntstatus.h>
 #include <windows.h>
+#include <winternl.h>
 
 #include <memory>
 #include <vector>
@@ -24,15 +25,6 @@
 namespace {
 
 using ScopedUnicodeString = std::unique_ptr<UNICODE_STRING, NtAllocDeleter>;
-void InitUnicodeString(UNICODE_STRING* unistr, const wchar_t* wstr) {
-  static RtlInitUnicodeStringFunction rtl_init_unicode_string = nullptr;
-  if (!rtl_init_unicode_string) {
-    rtl_init_unicode_string =
-        reinterpret_cast<RtlInitUnicodeStringFunction>(::GetProcAddress(
-            ::GetModuleHandle(L"ntdll.dll"), "RtlInitUnicodeString"));
-  }
-  rtl_init_unicode_string(unistr, wstr);
-}
 
 TEST(SandboxNtUtil, IsSameProcessPseudoHandle) {
   HANDLE current_process_pseudo = GetCurrentProcess();
@@ -315,7 +307,7 @@
 TEST(SandboxNtUtil, ExtractModuleName) {
   {
     UNICODE_STRING module_path = {};
-    InitUnicodeString(&module_path, L"no-path-sep");
+    ::RtlInitUnicodeString(&module_path, L"no-path-sep");
     ScopedUnicodeString result(ExtractModuleName(&module_path));
     EXPECT_TRUE(result);
     EXPECT_EQ(result->Length, module_path.Length);
@@ -323,7 +315,7 @@
   }
   {
     UNICODE_STRING module_path = {};
-    InitUnicodeString(&module_path, L"c:\\has a\\path\\module.dll");
+    ::RtlInitUnicodeString(&module_path, L"c:\\has a\\path\\module.dll");
     ScopedUnicodeString result(ExtractModuleName(&module_path));
 
     EXPECT_TRUE(result);
@@ -332,14 +324,14 @@
   }
   {
     UNICODE_STRING module_path = {};
-    InitUnicodeString(&module_path, L"c:\\only a\\path\\");
+    ::RtlInitUnicodeString(&module_path, L"c:\\only a\\path\\");
     ScopedUnicodeString result(ExtractModuleName(&module_path));
 
     EXPECT_FALSE(result);
   }
   {
     UNICODE_STRING module_path = {};
-    InitUnicodeString(&module_path, L"A");
+    ::RtlInitUnicodeString(&module_path, L"A");
     ScopedUnicodeString result(ExtractModuleName(&module_path));
 
     EXPECT_TRUE(result);
@@ -348,7 +340,7 @@
   }
   {
     UNICODE_STRING module_path = {};
-    InitUnicodeString(&module_path, L"");
+    ::RtlInitUnicodeString(&module_path, L"");
     ScopedUnicodeString result(ExtractModuleName(&module_path));
 
     EXPECT_TRUE(result);
diff --git a/sandbox/win/src/sandbox_utils.cc b/sandbox/win/src/sandbox_utils.cc
index f0312027..64c5505 100644
--- a/sandbox/win/src/sandbox_utils.cc
+++ b/sandbox/win/src/sandbox_utils.cc
@@ -5,6 +5,7 @@
 #include "sandbox/win/src/sandbox_utils.h"
 
 #include <windows.h>
+#include <winternl.h>
 
 #include "base/check.h"
 #include "sandbox/win/src/internal_types.h"
@@ -18,14 +19,7 @@
                        OBJECT_ATTRIBUTES* obj_attr,
                        UNICODE_STRING* uni_name,
                        SECURITY_QUALITY_OF_SERVICE* security_qos) {
-  static RtlInitUnicodeStringFunction RtlInitUnicodeString;
-  if (!RtlInitUnicodeString) {
-    HMODULE ntdll = ::GetModuleHandle(kNtdllName);
-    RtlInitUnicodeString = reinterpret_cast<RtlInitUnicodeStringFunction>(
-        GetProcAddress(ntdll, "RtlInitUnicodeString"));
-    DCHECK(RtlInitUnicodeString);
-  }
-  RtlInitUnicodeString(uni_name, name.c_str());
+  ::RtlInitUnicodeString(uni_name, name.c_str());
   InitializeObjectAttributes(obj_attr, uni_name, attributes, root, nullptr);
   obj_attr->SecurityQualityOfService = security_qos;
 }
diff --git a/services/viz/public/cpp/compositing/mojom_traits_unittest.cc b/services/viz/public/cpp/compositing/mojom_traits_unittest.cc
index 5f97609c..8a12997 100644
--- a/services/viz/public/cpp/compositing/mojom_traits_unittest.cc
+++ b/services/viz/public/cpp/compositing/mojom_traits_unittest.cc
@@ -519,12 +519,9 @@
   // TransferableResource constants.
   const ResourceId single_plane_id(1337);
   const ResourceId multi_plane_id(1338);
-  const SharedImageFormat single_plane_format =
-      SharedImageFormat::SinglePlane(ALPHA_8);
+  const SharedImageFormat single_plane_format = SinglePlaneFormat::kALPHA_8;
   const SharedImageFormat multi_plane_format =
-      SharedImageFormat::MultiPlane(SharedImageFormat::PlaneConfig::kY_UV,
-                                    SharedImageFormat::Subsampling::k420,
-                                    SharedImageFormat::ChannelFormat::k8);
+      MultiPlaneFormat::kYUV_420_BIPLANAR;
   const uint32_t tr_filter = 1234;
   const gfx::Size tr_size(1234, 5678);
   TransferableResource single_plane_resource;
@@ -1159,7 +1156,7 @@
 
 TEST_F(StructTraitsTest, TransferableResource) {
   const ResourceId id(1337);
-  const SharedImageFormat format = SharedImageFormat::SinglePlane(ALPHA_8);
+  const SharedImageFormat format = SinglePlaneFormat::kALPHA_8;
   const uint32_t filter = 1234;
   const gfx::Size size(1234, 5678);
   const int8_t mailbox_name[GL_MAILBOX_SIZE_CHROMIUM] = {
@@ -1208,28 +1205,16 @@
 }
 
 TEST_F(StructTraitsTest, SharedImageFormatWithSinglePlane) {
-  const ResourceFormat resource_format = RED_8;
-  SharedImageFormat input = SharedImageFormat::SinglePlane(resource_format);
-
+  SharedImageFormat input = SinglePlaneFormat::kRED_8;
   SharedImageFormat output;
   mojo::test::SerializeAndDeserialize<mojom::SharedImageFormat>(input, output);
-
   EXPECT_EQ(input, output);
 }
 
 TEST_F(StructTraitsTest, SharedImageFormatWithMultiPlane) {
-  const SharedImageFormat::PlaneConfig plane_config =
-      SharedImageFormat::PlaneConfig::kY_UV;
-  const SharedImageFormat::Subsampling subsampling =
-      SharedImageFormat::Subsampling::k420;
-  const SharedImageFormat::ChannelFormat channel_format =
-      SharedImageFormat::ChannelFormat::k8;
-  SharedImageFormat input =
-      SharedImageFormat::MultiPlane(plane_config, subsampling, channel_format);
-
+  SharedImageFormat input = MultiPlaneFormat::kYUV_420_BIPLANAR;
   SharedImageFormat output;
   mojo::test::SerializeAndDeserialize<mojom::SharedImageFormat>(input, output);
-
   EXPECT_EQ(input, output);
 }
 
diff --git a/testing/android/native_test/BUILD.gn b/testing/android/native_test/BUILD.gn
index ec43813..c6dd193 100644
--- a/testing/android/native_test/BUILD.gn
+++ b/testing/android/native_test/BUILD.gn
@@ -45,12 +45,14 @@
 
 android_library("native_main_runner_java") {
   testonly = true
+  annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
   sources = [ "java/src/org/chromium/native_test/MainRunner.java" ]
   deps = [ "//base:jni_java" ]
 }
 
 android_library("native_test_java") {
   testonly = true
+  annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
   deps = [
     ":native_main_runner_java",
     "//base:base_java",
@@ -61,7 +63,6 @@
     "//testing/android/reporter:reporter_java",
     "//third_party/androidx:androidx_fragment_fragment_java",
   ]
-  annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
   sources = [
     "java/src/org/chromium/native_test/NativeBrowserTest.java",
     "java/src/org/chromium/native_test/NativeBrowserTestActivity.java",
diff --git a/testing/android/native_test/java/src/org/chromium/native_test/MainRunner.java b/testing/android/native_test/java/src/org/chromium/native_test/MainRunner.java
index b8e39794..1d7e6de 100644
--- a/testing/android/native_test/java/src/org/chromium/native_test/MainRunner.java
+++ b/testing/android/native_test/java/src/org/chromium/native_test/MainRunner.java
@@ -5,6 +5,7 @@
 package org.chromium.native_test;
 
 import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
 
 /**
  * This class provides a way to run the native main method.
@@ -20,7 +21,11 @@
 
     // Maps the file descriptors and executes the main method with the passed in command line.
     public static int runMain(String[] commandLine) {
-        return nativeRunMain(commandLine);
+        return MainRunnerJni.get().runMain(commandLine);
     }
-    private static native int nativeRunMain(String[] commandLine);
+
+    @NativeMethods
+    interface Natives {
+        int runMain(String[] commandLine);
+    }
 }
\ No newline at end of file
diff --git a/testing/android/native_test/java/src/org/chromium/native_test/NativeTest.java b/testing/android/native_test/java/src/org/chromium/native_test/NativeTest.java
index af85737b..e8bcd8d 100644
--- a/testing/android/native_test/java/src/org/chromium/native_test/NativeTest.java
+++ b/testing/android/native_test/java/src/org/chromium/native_test/NativeTest.java
@@ -16,6 +16,7 @@
 
 import org.chromium.base.Log;
 import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
 import org.chromium.base.test.util.UrlUtils;
 import org.chromium.build.gtest_apk.NativeTestIntent;
 import org.chromium.test.reporter.TestStatusReporter;
@@ -173,8 +174,8 @@
     }
 
     private void runTests(Activity activity) {
-        nativeRunTests(mCommandLineFlags.toString(), mCommandLineFilePath, mStdoutFilePath,
-                activity.getApplicationContext(), UrlUtils.getIsolatedTestRoot());
+        NativeTestJni.get().runTests(mCommandLineFlags.toString(), mCommandLineFilePath,
+                mStdoutFilePath, activity.getApplicationContext(), UrlUtils.getIsolatedTestRoot());
         activity.finish();
         mReporter.testRunFinished(Process.myPid());
     }
@@ -186,6 +187,9 @@
         Log.e(TAG, "[ RUNNER_FAILED ] could not load native library");
     }
 
-    private native void nativeRunTests(String commandLineFlags, String commandLineFilePath,
-            String stdoutFilePath, Context appContext, String testDataDir);
+    @NativeMethods
+    interface Natives {
+        void runTests(String commandLineFlags, String commandLineFilePath, String stdoutFilePath,
+                Context appContext, String testDataDir);
+    }
 }
diff --git a/testing/android/native_test/native_test_launcher.cc b/testing/android/native_test/native_test_launcher.cc
index 4b7ba88f..587cf07 100644
--- a/testing/android/native_test/native_test_launcher.cc
+++ b/testing/android/native_test/native_test_launcher.cc
@@ -77,7 +77,6 @@
 
 static void JNI_NativeTest_RunTests(
     JNIEnv* env,
-    const JavaParamRef<jobject>& obj,
     const JavaParamRef<jstring>& jcommand_line_flags,
     const JavaParamRef<jstring>& jcommand_line_file_path,
     const JavaParamRef<jstring>& jstdout_file_path,
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 361d2604..e153790 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -21584,6 +21584,7 @@
     "gtest_tests": [
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -21644,6 +21645,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -21706,6 +21708,7 @@
       {
         "args": [
           "--test-launcher-batch-limit=1",
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -21767,6 +21770,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -21827,6 +21831,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "-v",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
         ],
@@ -21872,6 +21877,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -21932,6 +21938,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -21992,6 +21999,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -22052,6 +22060,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
@@ -22113,6 +22122,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -22176,6 +22186,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -22236,6 +22247,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -22297,6 +22309,7 @@
       {
         "args": [
           "--gtest_filter=-*UsingRealWebcam*",
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -22357,6 +22370,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -22417,6 +22431,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -22477,6 +22492,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
@@ -22543,6 +22559,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -22604,6 +22621,7 @@
       {
         "args": [
           "--gtest_filter=-org.chromium.chrome.browser.contextualsearch.ContextualSearchManagerTest.test*ExternalNavigationWithUserGesture*:org.chromium.shape_detection.*",
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
@@ -22673,6 +22691,7 @@
       {
         "args": [
           "--use-persistent-shell",
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
@@ -22745,6 +22764,7 @@
       {
         "args": [
           "--gtest_filter=org.chromium.chrome.browser.contextualsearch.ContextualSearchManagerTest.test*ExternalNavigationWithUserGesture*:org.chromium.shape_detection.*",
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
@@ -22812,6 +22832,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
@@ -22880,6 +22901,7 @@
       {
         "args": [
           "--use-persistent-shell",
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
@@ -22950,6 +22972,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -23011,6 +23034,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -23073,6 +23097,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
@@ -23136,6 +23161,7 @@
       {
         "args": [
           "--use-persistent-shell",
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
@@ -23201,6 +23227,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
@@ -23263,6 +23290,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -23324,6 +23352,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -23384,6 +23413,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -23444,6 +23474,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -23504,6 +23535,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -23564,6 +23596,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -23624,6 +23657,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -23684,6 +23718,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -23744,6 +23779,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -23805,6 +23841,7 @@
       {
         "args": [
           "--use-cmd-decoder=validating",
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
@@ -23867,6 +23904,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -23927,6 +23965,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -23987,6 +24026,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -24047,6 +24087,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -24107,6 +24148,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -24167,6 +24209,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -24227,6 +24270,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -24287,6 +24331,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -24347,6 +24392,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -24407,6 +24453,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -24467,6 +24514,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -24527,6 +24575,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -24587,6 +24636,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -24647,6 +24697,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -24707,6 +24758,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -24768,6 +24820,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
@@ -24829,6 +24882,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
@@ -24890,6 +24944,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
@@ -24953,6 +25008,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -25013,6 +25069,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -25073,6 +25130,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -25133,6 +25191,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -25193,6 +25252,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -25253,6 +25313,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -25313,6 +25374,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -25373,6 +25435,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -25433,6 +25496,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -25494,6 +25558,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -25554,6 +25619,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -25614,6 +25680,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
@@ -25683,6 +25750,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
@@ -25745,6 +25813,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -25805,6 +25874,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -25865,6 +25935,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
@@ -25926,6 +25997,9 @@
     ],
     "isolated_scripts": [
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "android_webview_junit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -25953,6 +26027,9 @@
         "use_isolated_scripts_api": true
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "base_junit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -25980,6 +26057,9 @@
         "use_isolated_scripts_api": true
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "build_junit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -26007,6 +26087,9 @@
         "use_isolated_scripts_api": true
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "chrome_java_test_pagecontroller_junit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -26035,7 +26118,8 @@
       },
       {
         "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/android.nougat-x86-rel.chrome_junit_tests.filter"
+          "--test-launcher-filter-file=../../testing/buildbot/filters/android.nougat-x86-rel.chrome_junit_tests.filter",
+          "--use-persistent-shell"
         ],
         "isolate_name": "chrome_junit_tests",
         "isolate_profile_data": true,
@@ -26064,6 +26148,9 @@
         "use_isolated_scripts_api": true
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "components_junit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -26093,6 +26180,7 @@
       {
         "args": [
           "--gtest-benchmark-name=components_perftests",
+          "--use-persistent-shell",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
         ],
         "isolate_name": "components_perftests",
@@ -26138,6 +26226,9 @@
         "test_id_prefix": "ninja://components:components_perftests/"
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "content_junit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -26165,6 +26256,9 @@
         "use_isolated_scripts_api": true
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "device_junit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -26192,6 +26286,9 @@
         "use_isolated_scripts_api": true
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "junit_unit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -26219,6 +26316,9 @@
         "use_isolated_scripts_api": true
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "media_base_junit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -26246,6 +26346,9 @@
         "use_isolated_scripts_api": true
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "module_installer_junit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -26274,6 +26377,7 @@
       },
       {
         "args": [
+          "--use-persistent-shell",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
         ],
         "isolate_name": "monochrome_public_apk_checker",
@@ -26319,6 +26423,9 @@
         "test_id_prefix": "ninja://chrome/android/monochrome:monochrome_public_apk_checker/"
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "net_junit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -26346,6 +26453,9 @@
         "use_isolated_scripts_api": true
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "paint_preview_junit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -26373,6 +26483,9 @@
         "use_isolated_scripts_api": true
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "password_check_junit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -26400,6 +26513,9 @@
         "use_isolated_scripts_api": true
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "password_manager_junit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -26427,6 +26543,9 @@
         "use_isolated_scripts_api": true
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "services_junit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -26460,6 +26579,7 @@
           "-v",
           "--passthrough",
           "--retry-limit=2",
+          "--use-persistent-shell",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
         ],
         "check_flakiness_for_new_tests": false,
@@ -26511,6 +26631,7 @@
           "-v",
           "--passthrough",
           "--retry-limit=2",
+          "--use-persistent-shell",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
         ],
         "ci_only": true,
@@ -26557,6 +26678,7 @@
       {
         "args": [
           "--extra-browser-args=--enable-crashpad",
+          "--use-persistent-shell",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
           "--browser=android-chromium"
         ],
@@ -26604,6 +26726,9 @@
         "test_id_prefix": "ninja://chrome/test:telemetry_perf_unittests_android_chrome/"
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "touch_to_fill_junit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -26631,6 +26756,9 @@
         "use_isolated_scripts_api": true
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "ui_junit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -26658,6 +26786,9 @@
         "use_isolated_scripts_api": true
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "webapk_client_junit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -26685,6 +26816,9 @@
         "use_isolated_scripts_api": true
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "webapk_shell_apk_h2o_junit_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -26712,6 +26846,9 @@
         "use_isolated_scripts_api": true
       },
       {
+        "args": [
+          "--use-persistent-shell"
+        ],
         "isolate_name": "webapk_shell_apk_junit_tests",
         "isolate_profile_data": true,
         "merge": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 9b06f7c..944f82a 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -99842,7 +99842,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.finch"
             }
           ],
@@ -99865,7 +99865,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.finch"
             }
           ],
@@ -99887,7 +99887,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.finch"
             }
           ],
@@ -99909,7 +99909,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.finch"
             }
           ],
@@ -99931,7 +99931,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.finch"
             }
           ],
@@ -99953,7 +99953,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.finch"
             }
           ],
@@ -101367,7 +101367,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101388,7 +101388,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101409,7 +101409,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101431,7 +101431,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101452,7 +101452,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101473,7 +101473,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101494,7 +101494,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101515,7 +101515,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101536,7 +101536,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101557,7 +101557,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101579,7 +101579,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101600,7 +101600,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101621,7 +101621,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101645,7 +101645,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101679,7 +101679,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101703,7 +101703,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101724,7 +101724,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101745,7 +101745,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101766,7 +101766,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101787,7 +101787,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101808,7 +101808,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101829,7 +101829,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101850,7 +101850,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101871,7 +101871,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101892,7 +101892,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101913,7 +101913,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101937,7 +101937,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101959,7 +101959,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -101980,7 +101980,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102001,7 +102001,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102022,7 +102022,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102043,7 +102043,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102064,7 +102064,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102085,7 +102085,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102106,7 +102106,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102127,7 +102127,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102148,7 +102148,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102169,7 +102169,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102190,7 +102190,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102211,7 +102211,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102232,7 +102232,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102253,7 +102253,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102274,7 +102274,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102295,7 +102295,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102316,7 +102316,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102337,7 +102337,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102358,7 +102358,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102379,7 +102379,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102400,7 +102400,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102421,7 +102421,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102442,7 +102442,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102464,7 +102464,7 @@
             {
               "cpu": "x86-64",
               "integrity": "high",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102485,7 +102485,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102519,7 +102519,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102540,7 +102540,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102561,7 +102561,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102582,7 +102582,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102603,7 +102603,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102624,7 +102624,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102645,7 +102645,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102666,7 +102666,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102687,7 +102687,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102708,7 +102708,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102729,7 +102729,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102750,7 +102750,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102771,7 +102771,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102792,7 +102792,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102813,7 +102813,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102834,7 +102834,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102855,7 +102855,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102876,7 +102876,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102897,7 +102897,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102919,7 +102919,7 @@
             {
               "cpu": "x86-64",
               "integrity": "high",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102940,7 +102940,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102961,7 +102961,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -102982,7 +102982,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103003,7 +103003,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103025,7 +103025,7 @@
             {
               "cpu": "x86-64",
               "integrity": "high",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103046,7 +103046,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103067,7 +103067,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103088,7 +103088,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103109,7 +103109,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103130,7 +103130,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103151,7 +103151,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103172,7 +103172,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103193,7 +103193,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103214,7 +103214,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103235,7 +103235,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103256,7 +103256,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103277,7 +103277,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103306,7 +103306,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103327,7 +103327,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103348,7 +103348,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103369,7 +103369,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103390,7 +103390,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103411,7 +103411,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103432,7 +103432,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103453,7 +103453,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103474,7 +103474,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103502,7 +103502,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103543,7 +103543,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103585,7 +103585,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103615,7 +103615,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103637,7 +103637,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103664,7 +103664,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103690,7 +103690,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103716,7 +103716,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103741,7 +103741,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103764,7 +103764,7 @@
             {
               "cpu": "x86-64",
               "integrity": "high",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103789,7 +103789,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103812,7 +103812,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103844,7 +103844,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103869,7 +103869,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
@@ -103897,7 +103897,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Windows-10-19042",
+              "os": "Windows-10-19042|Windows-10-19045",
               "pool": "chromium.tests.no-external-ip"
             }
           ],
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 09f4438..06215aed 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -12581,7 +12581,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-18.04"
+              "os": "Ubuntu-20.04"
             }
           ],
           "expiration": 36000,
@@ -12625,7 +12625,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Ubuntu-18.04"
+              "os": "Ubuntu-20.04"
             }
           ],
           "expiration": 36000,
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl
index 76defb5..94118c7 100644
--- a/testing/buildbot/mixins.pyl
+++ b/testing/buildbot/mixins.pyl
@@ -1255,13 +1255,6 @@
       },
     },
   },
-  'win10-20h2': {
-    'swarming': {
-      'dimensions': {
-        'os': 'Windows-10-19042',
-      },
-    },
-  },
   'win10-any': {
     'swarming': {
       'dimensions': {
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 9ce6d58..15afaf7 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -942,6 +942,9 @@
           'cronet_test_instrumentation_apk',
           'chrome_nocompile_tests',
         ],
+        'args': [
+          '--use-persistent-shell',
+        ],
         'os_type': 'android',
         'test_suites': {
           'gtest_tests': 'android_nougat_emulator_gtests',
@@ -3675,7 +3678,7 @@
       },
       'win-fieldtrial-rel': {
         'mixins': [
-            'win10-20h2',
+            'win10',
             'finch-chromium-swarming-pool',
         ],
         'test_suites': {
@@ -3709,7 +3712,7 @@
       'win10-rel-no-external-ip': {
         'mixins': [
           'x86-64',
-          'win10-20h2',
+          'win10',
           'isolate_profile_data',
         ],
         'swarming': {
@@ -5174,7 +5177,7 @@
       },
       'WebKit Linux MSAN': {
         'mixins': [
-          'linux-bionic',
+          'linux-focal',
         ],
         'test_suites': {
           'isolated_scripts': 'chromium_webkit_isolated_scripts',
diff --git a/testing/scripts/get_compile_targets.py b/testing/scripts/get_compile_targets.py
index d6cbc74..7e6af17 100755
--- a/testing/scripts/get_compile_targets.py
+++ b/testing/scripts/get_compile_targets.py
@@ -36,7 +36,6 @@
                     'PRESUBMIT.py',
                     'sizes_common.py',
                     'variations_seed_access_helper.py',
-                    'wpt_common.py',
                     'run_variations_smoke_tests.py',
                     'run_performance_tests_unittest.py'):
       continue
diff --git a/testing/scripts/wpt_common.py b/testing/scripts/wpt_common.py
deleted file mode 100644
index ba9767fbd..0000000
--- a/testing/scripts/wpt_common.py
+++ /dev/null
@@ -1,181 +0,0 @@
-# Copyright 2020 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import argparse
-import glob
-import logging
-import os
-import sys
-
-# Add src/testing/ into sys.path for importing common without pylint errors.
-sys.path.append(
-    os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))
-from scripts import common
-
-BLINK_TOOLS_DIR = os.path.join(common.SRC_DIR, 'third_party', 'blink', 'tools')
-CATAPULT_DIR = os.path.join(common.SRC_DIR, 'third_party', 'catapult')
-OUT_DIR = os.path.join(common.SRC_DIR, "out", "{}")
-DEFAULT_ISOLATED_SCRIPT_TEST_OUTPUT = os.path.join(OUT_DIR, "results.json")
-TYP_DIR = os.path.join(CATAPULT_DIR, 'third_party', 'typ')
-WEB_TESTS_DIR = os.path.normpath(
-    os.path.join(BLINK_TOOLS_DIR, os.pardir, 'web_tests'))
-
-if BLINK_TOOLS_DIR not in sys.path:
-    sys.path.append(BLINK_TOOLS_DIR)
-
-if TYP_DIR not in sys.path:
-    sys.path.append(TYP_DIR)
-
-from blinkpy.common.host import Host
-from blinkpy.common.path_finder import PathFinder
-
-logger = logging.getLogger(__name__)
-
-
-# pylint: disable=super-with-arguments
-class BaseWptScriptAdapter(common.BaseIsolatedScriptArgsAdapter):
-    """The base class for script adapters that use wptrunner to execute web
-    platform tests. This contains any code shared between these scripts, such
-    as integrating output with the results viewer. Subclasses contain other
-    (usually platform-specific) logic."""
-
-    def __init__(self, host=None):
-        self.host = host or Host()
-        self.fs = self.host.filesystem
-        self.path_finder = PathFinder(self.fs)
-        self.port = self.host.port_factory.get()
-        super(BaseWptScriptAdapter, self).__init__()
-        self.wptreport = None
-        self._include_filename = None
-        self.layout_test_results_subdir = 'layout-test-results'
-
-    def maybe_set_default_isolated_script_test_output(self):
-        if self.options.isolated_script_test_output:
-            return
-        default_value = DEFAULT_ISOLATED_SCRIPT_TEST_OUTPUT.format(
-            self.options.target)
-        print("--isolated-script-test-output not set, defaulting to %s" %
-              default_value)
-        self.options.isolated_script_test_output = default_value
-
-    def generate_test_output_args(self, output):
-        return ['--log-chromium=%s' % output]
-
-    def _resolve_tests_from_isolate_filter(self, test_filter):
-        """Resolve an isolated script-style filter string into lists of tests.
-
-        Arguments:
-            test_filter (str): Glob patterns delimited by double colons ('::').
-                The glob is prefixed with '-' to indicate that tests matching
-                the pattern should not run. Assume a valid wpt name cannot start
-                with '-'.
-
-        Returns:
-            tuple[list[str], list[str]]: Tests to include and exclude,
-                respectively.
-        """
-        included_tests, excluded_tests = [], []
-        for pattern in common.extract_filter_list(test_filter):
-            test_group = included_tests
-            if pattern.startswith('-'):
-                test_group, pattern = excluded_tests, pattern[1:]
-            if self.path_finder.is_wpt_internal_path(pattern):
-                pattern_on_disk = self.path_finder.path_from_web_tests(pattern)
-            else:
-                pattern_on_disk = self.fs.join(self.wpt_root_dir, pattern)
-            test_group.extend(glob.glob(pattern_on_disk))
-        return included_tests, excluded_tests
-
-    def generate_test_filter_args(self, test_filter_str):
-        included_tests, excluded_tests = \
-            self._resolve_tests_from_isolate_filter(test_filter_str)
-        include_file, self._include_filename = self.fs.open_text_tempfile()
-        with include_file:
-            for test in included_tests:
-                include_file.write(test)
-                include_file.write('\n')
-        wpt_args = ['--include-file=%s' % self._include_filename]
-        for test in excluded_tests:
-            wpt_args.append('--exclude=%s' % test)
-        return wpt_args
-
-    def generate_test_repeat_args(self, repeat_count):
-        return ['--repeat=%d' % repeat_count]
-
-    @property
-    def _has_explicit_tests(self):
-        # TODO(crbug.com/1356318): `run_wpt_tests` has multiple ways to
-        # explicitly specify tests. Some are inherited from wptrunner, the rest
-        # from Chromium infra. After we consolidate `run_wpt_tests` and
-        # `wpt_common`, maybe we should build a single explicit test list to
-        # simplify this check?
-        for test_or_option in super().rest_args:
-            if not test_or_option.startswith('-'):
-                return True
-        return (getattr(self.options, 'include', None) or
-                getattr(self.options, 'include_file', None) or
-                getattr(self.options, 'gtest_filter', None) or
-                self._include_filename)
-
-    def generate_test_launcher_retry_limit_args(self, retry_limit):
-        return ['--retry-unexpected=%d' % retry_limit]
-
-    def generate_sharding_args(self, total_shards, shard_index):
-        return ['--total-chunks=%d' % total_shards,
-                # shard_index is 0-based but WPT's this-chunk to be 1-based
-                '--this-chunk=%d' % (shard_index + 1),
-                # The default sharding strategy is to shard by directory. But
-                # we want to hash each test to determine which shard runs it.
-                # This allows running individual directories that have few
-                # tests across many shards.
-                '--chunk-type=hash']
-
-    @property
-    def _default_retry_limit(self) -> int:
-        return 0 if self._has_explicit_tests else 3
-
-    @property
-    def wpt_output(self):
-        return self.options.isolated_script_test_output
-
-    def _show_wpt_help(self):
-        command = [
-            self.select_python_executable(),
-        ]
-        command.extend(self._wpt_run_args)
-        command.extend(['--help'])
-        exit_code = common.run_command(command)
-        self.parser.exit(exit_code)
-
-    @property
-    def _wpt_run_args(self):
-        """The start of a 'wpt run' command."""
-        return [
-            self.wpt_binary,
-            # Use virtualenv packages installed by vpython, not wpt.
-            '--venv=%s' % self.path_finder.chromium_base(),
-            '--skip-venv-setup',
-            'run',
-        ]
-
-    def process_and_upload_results(self):
-        command = [
-            self.select_python_executable(),
-            os.path.join(BLINK_TOOLS_DIR, 'wpt_process_results.py'),
-            '--target',
-            self.options.target,
-            '--web-tests-dir',
-            WEB_TESTS_DIR,
-            '--artifacts-dir',
-            os.path.join(os.path.dirname(self.wpt_output),
-                         self.layout_test_results_subdir),
-            '--wpt-results',
-            self.wpt_output,
-        ]
-        if self.options.verbose:
-            command.append('--verbose')
-        if self.wptreport:
-            command.extend(['--wpt-report',
-                            self.wptreport])
-        return common.run_command(command)
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index f9316014..c6527bce 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -1485,13 +1485,7 @@
     "AutofillUpstreamAllowAllEmailDomains": [
         {
             "platforms": [
-                "android",
-                "chromeos",
-                "chromeos_lacros",
-                "ios",
-                "linux",
-                "mac",
-                "windows"
+                "android"
             ],
             "experiments": [
                 {
@@ -2790,6 +2784,24 @@
             ]
         }
     ],
+    "ClearOmniboxFocusAsync": [
+        {
+            "platforms": [
+                "android"
+            ],
+            "experiments": [
+                {
+                    "name": "ClearOmniboxFocusAsync_20230112",
+                    "params": {
+                        "clear_focus_asynchronously": "true"
+                    },
+                    "enable_features": [
+                        "ClearOmniboxFocusAfterNavigation"
+                    ]
+                }
+            ]
+        }
+    ],
     "Collections": [
         {
             "platforms": [
@@ -5691,6 +5703,21 @@
             ]
         }
     ],
+    "IOSFeedBackOfCardP13nPromo": [
+        {
+            "platforms": [
+                "ios"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled_20230113",
+                    "enable_features": [
+                        "EnableFeedCardMenuSignInPromo"
+                    ]
+                }
+            ]
+        }
+    ],
     "IOSFeedSyncPromo": [
         {
             "platforms": [
@@ -7510,27 +7537,6 @@
             ]
         }
     ],
-    "OmniboxNavigationLatencyImprovements": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "LaunchTarget",
-                    "params": {
-                        "clear_focus_asynchronously": "false"
-                    },
-                    "enable_features": [
-                        "CacheDeprecatedSystemLocationSetting",
-                        "ClearOmniboxFocusAfterNavigation",
-                        "OptimizeGeolocationHeaderGeneration",
-                        "PostTaskFocusTab"
-                    ]
-                }
-            ]
-        }
-    ],
     "OmniboxOnClobberFocusTypeOnContent": [
         {
             "platforms": [
@@ -8761,28 +8767,6 @@
             ]
         }
     ],
-    "PermuteTLSExtensions": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "chromeos_lacros",
-                "fuchsia",
-                "ios",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "PermuteTLSExtensions"
-                    ]
-                }
-            ]
-        }
-    ],
     "PersistentOriginTrials": [
         {
             "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index b94ee7e..82cc208 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -1692,6 +1692,11 @@
              "AllowPageWithIDBTransactionInBFCache",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+bool IsAllowPageWithIDBConnectionAndTransactionInBFCacheEnabled() {
+  return base::FeatureList::IsEnabled(kAllowPageWithIDBConnectionInBFCache) &&
+         base::FeatureList::IsEnabled(kAllowPageWithIDBTransactionInBFCache);
+}
+
 BASE_FEATURE(kUseBlinkSchedulerTaskRunnerWithCustomDeleter,
              "UseBlinkSchedulerTaskRunnerWithCustomDeleter",
              base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 2531d5e..a6394177 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -957,8 +957,7 @@
 // enabled.
 BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kSpeculationRulesPrefetchFuture);
 
-// TODO(leimy crbug.com/1378823): Merge the following two together into a
-// multi-level feature. Feature for allowing page with open IDB connection to be
+// Feature for allowing page with open IDB connection to be
 // stored in back/forward cache.
 BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kAllowPageWithIDBConnectionInBFCache);
 
@@ -966,6 +965,12 @@
 // back/forward cache.
 BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kAllowPageWithIDBTransactionInBFCache);
 
+// Checks both of kAllowPageWithIDBConnectionInBFCache and
+// kAllowPageWithIDBTransactionInBFCache are turned on when determining if a
+// page with IndexedDB transaction is eligible for BFCache.
+BLINK_COMMON_EXPORT bool
+IsAllowPageWithIDBConnectionAndTransactionInBFCacheEnabled();
+
 // Kill switch for using a custom task runner in the blink scheduler that makes
 // DeleteSoon/ReleaseSoon less prone to memory leaks.
 BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
index 888b105..9473aff 100644
--- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl
+++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -783,6 +783,7 @@
       NoSysexWebMIDIWithoutPermission
       NotificationInsecureOrigin
       NotificationPermissionRequestedIframe
+      ObsoleteCreateImageBitmapImageOrientationNone
       ObsoleteWebRtcCipherSuite
       OpenWebDatabaseInsecureContext
       OverflowVisibleOnReplacedElement
@@ -10552,6 +10553,10 @@
       # https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-minpinlength-extension
       # Defaults to false.
       optional boolean hasMinPinLength
+      # If set to true, the authenticator will support the prf extension.
+      # https://w3c.github.io/webauthn/#prf-extension
+      # Defaults to false.
+      optional boolean hasPrf
       # If set to true, tests of user presence will succeed immediately.
       # Otherwise, they will not be resolved. Defaults to true.
       optional boolean automaticPresenceSimulation
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
index c705c57d..3835be04 100644
--- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
+++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -3784,6 +3784,7 @@
   kPrivateNetworkAccessFetchedTopFrame = 4443,
   kDisableThirdPartyStoragePartitioning = 4444,
   kServiceWorkerFetchHandlerUpdateAfterInitialization = 4445,
+  kObsoleteCreateImageBitmapImageOrientationNone = 4446,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom b/third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom
index 8345f68..cc52f4a 100644
--- a/third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom
+++ b/third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom
@@ -34,6 +34,7 @@
   bool has_large_blob;
   bool has_cred_blob;
   bool has_min_pin_length;
+  bool has_prf;
 };
 
 // Encapsulates both public (key handle) and private information associated
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc b/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc
index c3176f4..101d0e9 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc
@@ -139,6 +139,9 @@
 void ScriptPromiseResolver::ResolveOrRejectImmediately() {
   DCHECK(!GetExecutionContext()->IsContextDestroyed());
   DCHECK(!GetExecutionContext()->IsContextPaused());
+
+  probe::WillReactToScriptPromise(GetExecutionContext());
+
   {
     if (state_ == kResolving) {
       resolver_.Resolve(value_.Get(script_state_->GetIsolate()));
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni
index 33313ef..1b2680d1 100644
--- a/third_party/blink/renderer/bindings/generated_in_modules.gni
+++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -165,6 +165,12 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_client_inputs.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_client_outputs.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_client_outputs.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_prf_inputs.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_prf_inputs.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_prf_outputs.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_prf_outputs.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_prf_values.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_prf_values.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_device_public_key_inputs.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_device_public_key_inputs.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_device_public_key_outputs.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni
index 23727bb97..7da6295 100644
--- a/third_party/blink/renderer/bindings/idl_in_modules.gni
+++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -137,6 +137,8 @@
           "//third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.idl",
           "//third_party/blink/renderer/modules/cookie_store/service_worker_registration_cookies.idl",
           "//third_party/blink/renderer/modules/cookie_store/window_cookie_store.idl",
+          "//third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_prf_inputs.idl",
+          "//third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_prf_outputs.idl",
           "//third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_client_inputs.idl",
           "//third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_client_outputs.idl",
           "//third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_device_public_key_inputs.idl",
diff --git a/third_party/blink/renderer/core/dom/dom_node_ids.h b/third_party/blink/renderer/core/dom/dom_node_ids.h
index dbd14182..7f31040 100644
--- a/third_party/blink/renderer/core/dom/dom_node_ids.h
+++ b/third_party/blink/renderer/core/dom/dom_node_ids.h
@@ -19,8 +19,14 @@
   STATIC_ONLY(DOMNodeIds);
 
  public:
+  // Return a DOMNodeID or 0 if one hasn't been assigned.
   static DOMNodeId ExistingIdForNode(Node*);
+
+  // Return the existing DOMNodeID if it has already been assigned, otherwise,
+  // assign a new DOMNodeID and return that.
   static DOMNodeId IdForNode(Node*);
+
+  // Return a node for the DOMNodeID or null if one hasn't been assigned.
   static Node* NodeForId(DOMNodeId);
 };
 
diff --git a/third_party/blink/renderer/core/dom/dom_node_ids_test.cc b/third_party/blink/renderer/core/dom/dom_node_ids_test.cc
index b7e22cf..353addd 100644
--- a/third_party/blink/renderer/core/dom/dom_node_ids_test.cc
+++ b/third_party/blink/renderer/core/dom/dom_node_ids_test.cc
@@ -58,4 +58,20 @@
   EXPECT_EQ(nullptr, DOMNodeIds::NodeForId(kInvalidDOMNodeId));
 }
 
+TEST_F(DOMNodeIdsTest, ExistingIdForNode) {
+  SetBodyContent("<div id='a'></div>");
+  Node* a = GetDocument().getElementById("a");
+
+  // Node a does not yet have an ID.
+  EXPECT_EQ(kInvalidDOMNodeId, DOMNodeIds::ExistingIdForNode(a));
+
+  // IdForNode() forces node a to have an ID.
+  DOMNodeId id_a = DOMNodeIds::IdForNode(a);
+  EXPECT_NE(kInvalidDOMNodeId, id_a);
+
+  // Both ExistingIdForNode() and IdForNode() still return the same ID.
+  EXPECT_EQ(id_a, DOMNodeIds::ExistingIdForNode(a));
+  EXPECT_EQ(id_a, DOMNodeIds::IdForNode(a));
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/weak_identifier_map.h b/third_party/blink/renderer/core/dom/weak_identifier_map.h
index b759c87..9415d24 100644
--- a/third_party/blink/renderer/core/dom/weak_identifier_map.h
+++ b/third_party/blink/renderer/core/dom/weak_identifier_map.h
@@ -43,8 +43,12 @@
     return result;
   }
 
+  // If the object is not found, returns 0 which is not a valid identifier.
   static IdentifierType ExistingIdentifier(T* object) {
-    return Instance().object_to_identifier_.at(object);
+    auto it_result = Instance().object_to_identifier_.find(object);
+    return it_result != Instance().object_to_identifier_.end()
+               ? it_result->value
+               : 0;
   }
 
   static T* Lookup(IdentifierType identifier) {
diff --git a/third_party/blink/renderer/core/frame/deprecation/deprecation.cc b/third_party/blink/renderer/core/frame/deprecation/deprecation.cc
index 3f87790..5b79e80 100644
--- a/third_party/blink/renderer/core/frame/deprecation/deprecation.cc
+++ b/third_party/blink/renderer/core/frame/deprecation/deprecation.cc
@@ -153,6 +153,10 @@
     case WebFeature::kObsoleteWebrtcTlsVersion:
       return DeprecationInfo::WithTranslation(
           feature, DeprecationIssueType::kObsoleteWebRtcCipherSuite);
+    case WebFeature::kObsoleteCreateImageBitmapImageOrientationNone:
+      return DeprecationInfo::WithTranslation(
+          feature,
+          DeprecationIssueType::kObsoleteCreateImageBitmapImageOrientationNone);
     case WebFeature::kOpenWebDatabaseInsecureContext:
       return DeprecationInfo::WithTranslation(
           feature, DeprecationIssueType::kOpenWebDatabaseInsecureContext);
diff --git a/third_party/blink/renderer/core/frame/performance_monitor.cc b/third_party/blink/renderer/core/frame/performance_monitor.cc
index 4538562..f0b57d5 100644
--- a/third_party/blink/renderer/core/frame/performance_monitor.cc
+++ b/third_party/blink/renderer/core/frame/performance_monitor.cc
@@ -154,6 +154,10 @@
   --script_depth_;
 }
 
+void PerformanceMonitor::WillReactToScriptPromise(ExecutionContext* context) {
+  UpdateTaskAttribution(context);
+}
+
 void PerformanceMonitor::UpdateTaskAttribution(ExecutionContext* context) {
   // If |context| is not a window, unable to attribute a frame context.
   auto* window = DynamicTo<LocalDOMWindow>(context);
diff --git a/third_party/blink/renderer/core/frame/performance_monitor.h b/third_party/blink/renderer/core/frame/performance_monitor.h
index eac33e0..b87047b8 100644
--- a/third_party/blink/renderer/core/frame/performance_monitor.h
+++ b/third_party/blink/renderer/core/frame/performance_monitor.h
@@ -99,6 +99,8 @@
 
   void DocumentWriteFetchScript(Document*);
 
+  void WillReactToScriptPromise(ExecutionContext*);
+
   // Direct API for core.
   void Subscribe(Violation, base::TimeDelta threshold, Client*);
   void UnsubscribeAll(Client*);
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index f4a3b22..c59a0b0c 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -1580,7 +1580,7 @@
     ExceptionState& exception_state) {
   return ImageBitmapSource::FulfillImageBitmap(
       script_state, MakeGarbageCollected<ImageBitmap>(this, crop_rect, options),
-      exception_state);
+      options, exception_state);
 }
 
 void HTMLCanvasElement::SetOffscreenCanvasResource(
diff --git a/third_party/blink/renderer/core/html/canvas/image_data.cc b/third_party/blink/renderer/core/html/canvas/image_data.cc
index 0080fa2..2bf8eab 100644
--- a/third_party/blink/renderer/core/html/canvas/image_data.cc
+++ b/third_party/blink/renderer/core/html/canvas/image_data.cc
@@ -298,7 +298,7 @@
   }
   return ImageBitmapSource::FulfillImageBitmap(
       script_state, MakeGarbageCollected<ImageBitmap>(this, crop_rect, options),
-      exception_state);
+      options, exception_state);
 }
 
 PredefinedColorSpace ImageData::GetPredefinedColorSpace() const {
diff --git a/third_party/blink/renderer/core/html/canvas/image_element_base.cc b/third_party/blink/renderer/core/html/canvas/image_element_base.cc
index a549d25..3e90582 100644
--- a/third_party/blink/renderer/core/html/canvas/image_element_base.cc
+++ b/third_party/blink/renderer/core/html/canvas/image_element_base.cc
@@ -199,7 +199,7 @@
   }
   return ImageBitmapSource::FulfillImageBitmap(
       script_state, MakeGarbageCollected<ImageBitmap>(this, crop_rect, options),
-      exception_state);
+      options, exception_state);
 }
 
 Image::ImageDecodingMode ImageElementBase::GetDecodingModeForPainting(
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.cc b/third_party/blink/renderer/core/html/media/html_video_element.cc
index 29e83b16..8c53b16 100644
--- a/third_party/blink/renderer/core/html/media/html_video_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_video_element.cc
@@ -384,7 +384,7 @@
   if (flags) {
     media_flags = *flags;
   } else {
-    media_flags.setAlpha(0xFF);
+    media_flags.setAlphaf(1.0f);
     media_flags.setFilterQuality(cc::PaintFlags::FilterQuality::kLow);
     media_flags.setBlendMode(SkBlendMode::kSrc);
   }
@@ -601,7 +601,7 @@
 
   return ImageBitmapSource::FulfillImageBitmap(
       script_state, MakeGarbageCollected<ImageBitmap>(this, crop_rect, options),
-      exception_state);
+      options, exception_state);
 }
 
 void HTMLVideoElement::MediaRemotingStarted(
diff --git a/third_party/blink/renderer/core/html/resources/forced_colors.css b/third_party/blink/renderer/core/html/resources/forced_colors.css
index f718cb6..45b7cbd 100644
--- a/third_party/blink/renderer/core/html/resources/forced_colors.css
+++ b/third_party/blink/renderer/core/html/resources/forced_colors.css
@@ -168,7 +168,7 @@
   select:-internal-list-box option:checked:hover,
   select:-internal-list-box:enabled option:checked:enabled:hover {
     background-color: Highlight !important;
-    color: Canvas !important;
+    color: HighlightText !important;
     forced-color-adjust: none;
   }
 
@@ -186,7 +186,7 @@
 
   select:-internal-list-box option:hover {
     background-color: Highlight !important;
-    color: Canvas;
+    color: HighlightText !important;
     forced-color-adjust: none;
   }
 
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
index 6713041..e670e72 100644
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
@@ -980,7 +980,7 @@
     ExceptionState& exception_state) {
   return ImageBitmapSource::FulfillImageBitmap(
       script_state, MakeGarbageCollected<ImageBitmap>(this, crop_rect, options),
-      exception_state);
+      options, exception_state);
 }
 
 scoped_refptr<Image> ImageBitmap::GetSourceImageForCanvas(
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.cc b/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.cc
index 18bf9a6..6bb17ce 100644
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.cc
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.cc
@@ -7,15 +7,19 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_image_bitmap_options.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/frame/deprecation/deprecation.h"
 #include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 
 namespace blink {
 
+constexpr const char* kImageBitmapOptionNone = "none";
+
 ScriptPromise ImageBitmapSource::FulfillImageBitmap(
     ScriptState* script_state,
     ImageBitmap* image_bitmap,
+    const ImageBitmapOptions* options,
     ExceptionState& exception_state) {
   if (!image_bitmap || !image_bitmap->BitmapImage()) {
     exception_state.ThrowDOMException(
@@ -24,6 +28,17 @@
     return ScriptPromise();
   }
 
+  // imageOrientation: 'from-image' will be used to replace imageOrientation:
+  // 'none'. Adding a deprecation warning when 'none' is called in
+  // createImageBitmap.
+  if (options->imageOrientation() == kImageBitmapOptionNone) {
+    auto* execution_context =
+        ExecutionContext::From(script_state->GetContext());
+    Deprecation::CountDeprecation(
+        execution_context,
+        WebFeature::kObsoleteCreateImageBitmapImageOrientationNone);
+  }
+
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
   ScriptPromise promise = resolver->Promise();
   resolver->Resolve(image_bitmap);
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.h b/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.h
index 89790e8..84250f9a 100644
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.h
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.h
@@ -30,8 +30,13 @@
 
   virtual bool IsBlob() const { return false; }
 
+  // TODO(crbug.com/1342260): Option imageOrientation: 'none' will be
+  // deprecated. A deprecation warning will be shown to developers when it is
+  // used. Adding |options| temporarily here to verify if 'none' is used, which
+  // will be removed in the next milestone.
   static ScriptPromise FulfillImageBitmap(ScriptState*,
                                           ImageBitmap*,
+                                          const ImageBitmapOptions* options,
                                           ExceptionState&);
 
  protected:
diff --git a/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc b/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc
index feab07a..3d2c79fe 100644
--- a/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc
@@ -547,6 +547,10 @@
       type = protocol::Audits::DeprecationIssueTypeEnum::
           NotificationPermissionRequestedIframe;
       break;
+    case DeprecationIssueType::kObsoleteCreateImageBitmapImageOrientationNone:
+      type = protocol::Audits::DeprecationIssueTypeEnum::
+          ObsoleteCreateImageBitmapImageOrientationNone;
+      break;
     case DeprecationIssueType::kObsoleteWebRtcCipherSuite:
       type =
           protocol::Audits::DeprecationIssueTypeEnum::ObsoleteWebRtcCipherSuite;
diff --git a/third_party/blink/renderer/core/inspector/inspector_audits_issue.h b/third_party/blink/renderer/core/inspector/inspector_audits_issue.h
index 68556d7..c00c35ef 100644
--- a/third_party/blink/renderer/core/inspector/inspector_audits_issue.h
+++ b/third_party/blink/renderer/core/inspector/inspector_audits_issue.h
@@ -66,6 +66,7 @@
   kNotDeprecated,
   kNotificationInsecureOrigin,
   kNotificationPermissionRequestedIframe,
+  kObsoleteCreateImageBitmapImageOrientationNone,
   kObsoleteWebRtcCipherSuite,
   kOpenWebDatabaseInsecureContext,
   kOverflowVisibleOnReplacedElement,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
index bababaf..20154089 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
@@ -20,6 +20,7 @@
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
 #include "third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 
 namespace blink {
 
@@ -655,16 +656,38 @@
 
   bool shrink_to_fit_column_block_size = false;
 
-  // We balance if block-size is unconstrained, or when we're explicitly told
-  // to. Note that the block-size may be constrained by outer fragmentation
-  // contexts, not just by a block-size specified on this multicol container.
-  bool balance_columns = Style().GetColumnFill() == EColumnFill::kBalance ||
-                         (column_size.block_size == kIndefiniteSize &&
-                          !is_constrained_by_outer_fragmentation_context_);
+  bool balance_columns;
+  bool has_content_based_block_size;
+  if (RuntimeEnabledFeatures::UnconstrainedColumnFillAutoEnabled()) {
+    // If column-fill is 'balance', we should of course balance. Additionally,
+    // we need to do it if we're *inside* another multicol container that's
+    // performing its initial column balancing pass. Otherwise we might report a
+    // taller block-size that we eventually end up with, resulting in the outer
+    // columns to be overstretched.
+    balance_columns = Style().GetColumnFill() == EColumnFill::kBalance ||
+                      (ConstraintSpace().HasBlockFragmentation() &&
+                       !ConstraintSpace().HasKnownFragmentainerBlockSize());
 
-  if (balance_columns) {
-    column_size.block_size = CalculateBalancedColumnBlockSize(
-        column_size, row_offset, next_column_token);
+    // If columns are to be balanced, we need to examine the contents of the
+    // multicol container to figure out a good initial (minimal) column
+    // block-size. We also need to do this if column-fill is 'auto' and the
+    // block-size is unconstrained.
+    has_content_based_block_size =
+        balance_columns || (column_size.block_size == kIndefiniteSize &&
+                            !is_constrained_by_outer_fragmentation_context_);
+  } else {
+    // We balance if block-size is unconstrained, or when we're explicitly told
+    // to. Note that the block-size may be constrained by outer fragmentation
+    // contexts, not just by a block-size specified on this multicol container.
+    balance_columns = Style().GetColumnFill() == EColumnFill::kBalance ||
+                      (column_size.block_size == kIndefiniteSize &&
+                       !is_constrained_by_outer_fragmentation_context_);
+    has_content_based_block_size = balance_columns;
+  }
+
+  if (has_content_based_block_size) {
+    column_size.block_size = ResolveColumnAutoBlockSize(
+        column_size, row_offset, next_column_token, balance_columns);
   } else if (available_outer_space != kIndefiniteSize) {
     // Finally, resolve any remaining auto block-size, and make sure that we
     // don't take up more space than there's room for in the outer fragmentation
@@ -859,8 +882,8 @@
         // and lay out again.
         balance_columns = true;
         new_columns.clear();
-        column_size.block_size = CalculateBalancedColumnBlockSize(
-            column_size, row_offset, next_column_token);
+        column_size.block_size = ResolveColumnAutoBlockSize(
+            column_size, row_offset, next_column_token, balance_columns);
         continue;
       }
 
@@ -1158,19 +1181,21 @@
   container_builder_.SetUseLastBaselineForInlineBaseline();
 }
 
-LayoutUnit NGColumnLayoutAlgorithm::CalculateBalancedColumnBlockSize(
+LayoutUnit NGColumnLayoutAlgorithm::ResolveColumnAutoBlockSize(
     const LogicalSize& column_size,
     LayoutUnit row_offset,
-    const NGBlockBreakToken* child_break_token) {
+    const NGBlockBreakToken* child_break_token,
+    bool balance_columns) {
   spanner_path_ = nullptr;
-  return CalculateBalancedColumnBlockSizeInternal(column_size, row_offset,
-                                                  child_break_token);
+  return ResolveColumnAutoBlockSizeInternal(column_size, row_offset,
+                                            child_break_token, balance_columns);
 }
 
-LayoutUnit NGColumnLayoutAlgorithm::CalculateBalancedColumnBlockSizeInternal(
+LayoutUnit NGColumnLayoutAlgorithm::ResolveColumnAutoBlockSizeInternal(
     const LogicalSize& column_size,
     LayoutUnit row_offset,
-    const NGBlockBreakToken* child_break_token) {
+    const NGBlockBreakToken* child_break_token,
+    bool balance_columns) {
   // To calculate a balanced column size for one row of columns, we need to
   // figure out how tall our content is. To do that we need to lay out. Create a
   // special constraint space for column balancing, without allowing soft
@@ -1316,8 +1341,8 @@
       if (forced_break_count && !knew_about_spanner) {
         // We may incorrectly have entered parallel flows, because we didn't
         // know about the spanner. Try again.
-        return CalculateBalancedColumnBlockSizeInternal(column_size, row_offset,
-                                                        child_break_token);
+        return ResolveColumnAutoBlockSizeInternal(
+            column_size, row_offset, child_break_token, balance_columns);
       }
       break;
     }
@@ -1351,7 +1376,10 @@
                                     row_offset);
   }
 
-  content_runs.DistributeImplicitBreaks(used_column_count_);
+  if (balance_columns) {
+    // We should create as many columns as specified by column-count.
+    content_runs.DistributeImplicitBreaks(used_column_count_);
+  }
   return ConstrainColumnBlockSize(content_runs.TallestColumnBlockSize(),
                                   row_offset);
 }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h
index 6ce5994..67400d5e2 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h
@@ -74,17 +74,24 @@
   void PropagateBaselineFromChild(const NGPhysicalBoxFragment& child,
                                   LayoutUnit block_offset);
 
-  // Calculate the smallest possible block-size for balanced columns. This will
-  // be the initial size we'll try with when actually lay out the columns.
-  LayoutUnit CalculateBalancedColumnBlockSize(
+  // Calculate the smallest possible block-size for columns, based on the
+  // content. For column balancing this will be the initial size we'll try with
+  // when actually lay out the columns (and then stretch the columns and re-lay
+  // out until the desired result is achieved). For column-fill:auto and
+  // unconstrained block-size, we also need to go through this, since we need to
+  // know the column block-size before performing "real" layout, since all
+  // columns in a row need to have the same block-size.
+  LayoutUnit ResolveColumnAutoBlockSize(
       const LogicalSize& column_size,
       LayoutUnit row_offset,
-      const NGBlockBreakToken* child_break_token);
+      const NGBlockBreakToken* child_break_token,
+      bool balance_columns);
 
-  LayoutUnit CalculateBalancedColumnBlockSizeInternal(
+  LayoutUnit ResolveColumnAutoBlockSizeInternal(
       const LogicalSize& column_size,
       LayoutUnit row_offset,
-      const NGBlockBreakToken* child_break_token);
+      const NGBlockBreakToken* child_break_token,
+      bool balance_columns);
 
   LayoutUnit ConstrainColumnBlockSize(LayoutUnit size,
                                       LayoutUnit row_offset) const;
diff --git a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
index 344328f..505bfef0 100644
--- a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
+++ b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
@@ -286,7 +286,7 @@
       IsPaintable()
           ? MakeGarbageCollected<ImageBitmap>(this, crop_rect, options)
           : nullptr,
-      exception_state);
+      options, exception_state);
 }
 
 bool OffscreenCanvas::IsOpaque() const {
diff --git a/third_party/blink/renderer/core/probe/core_probes.json5 b/third_party/blink/renderer/core/probe/core_probes.json5
index 1eb4590..56210b2 100644
--- a/third_party/blink/renderer/core/probe/core_probes.json5
+++ b/third_party/blink/renderer/core/probe/core_probes.json5
@@ -223,6 +223,7 @@
         "UserCallback",
         "V8Compile",
         "DocumentWriteFetchScript",
+        "WillReactToScriptPromise",
       ]
     },
     InspectorPerformanceAgent: {
diff --git a/third_party/blink/renderer/core/probe/core_probes.pidl b/third_party/blink/renderer/core/probe/core_probes.pidl
index df454194..e541426 100644
--- a/third_party/blink/renderer/core/probe/core_probes.pidl
+++ b/third_party/blink/renderer/core/probe/core_probes.pidl
@@ -163,6 +163,7 @@
   UserCallback([Keep] ExecutionContext* context, const char* name, const AtomicString& atomic_name, bool recurring, EventTarget* event_target = nullptr);
   V8Compile([Keep] ExecutionContext* context, const String& file_name, int line, int column);
   ParseHTML(Document* document, HTMLDocumentParser* parser);
+  void WillReactToScriptPromise([Keep] ExecutionContext* context);
   void ForcePseudoState([Keep] Element* element, CSSSelector::PseudoType pseudo_state, bool* result);
   void ShouldForceCorsPreflight(ExecutionContext*, bool* result);
   void ShouldBlockRequest(CoreProbeSink*, const KURL&, bool* result);
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
index 84b9c0c..67b3f8b 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
@@ -213,7 +213,7 @@
         std::max(state_stack_.size(), max_state_stack_depth_);
 
     cc::PaintFlags extra_flags;
-    extra_flags.setAlpha(globalAlpha() * 255);
+    extra_flags.setAlphaf(static_cast<float>(globalAlpha()));
     if (GetState().ShouldDrawShadows())
       extra_flags.setImageFilter(StateGetFilter());
     canvas->saveLayer(extra_flags);
@@ -224,7 +224,7 @@
     // shadows, or filters, both of them, or none of them.
     flags.setImageFilter(sk_make_sp<ComposePaintFilter>(
         GetState().ShadowAndForegroundImageFilter(), StateGetFilter()));
-    flags.setAlpha(globalAlpha() * 255);
+    flags.setAlphaf(static_cast<float>(globalAlpha()));
     canvas->saveLayer(flags);
   }
 
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h
index a43a3ba..793fa07 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h
@@ -829,7 +829,7 @@
           canvas_filter));
       // Resetting the alpha of the shadow layer, to avoid the alpha being
       // applied twice.
-      shadow_flags.setAlpha(255);
+      shadow_flags.setAlphaf(1.0f);
       // Saving the shadow layer before setting the matrix, so the shadow offset
       // does not get modified by the transformation matrix
       shadow_flags.setBlendMode(state.GlobalComposite());
diff --git a/third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_client_inputs.idl b/third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_client_inputs.idl
index 32e9839f..e10e0ce0 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_client_inputs.idl
+++ b/third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_client_inputs.idl
@@ -46,4 +46,8 @@
   // Device-bound public-key support.
   // https://github.com/w3c/webauthn/pull/1663
   [RuntimeEnabled=WebAuthenticationDevicePublicKey] AuthenticationExtensionsDevicePublicKeyInputs devicePubKey;
+
+  // Pseudo-random function support.
+  // https://w3c.github.io/webauthn/#prf-extension
+  [RuntimeEnabled=WebAuthenticationPRF] AuthenticationExtensionsPRFInputs prf;
 };
diff --git a/third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_client_outputs.idl b/third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_client_outputs.idl
index aa2ce49..e37879a 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_client_outputs.idl
+++ b/third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_client_outputs.idl
@@ -27,4 +27,8 @@
   // Device-bound public-key support.
   // https://github.com/w3c/webauthn/pull/1663
   [RuntimeEnabled=WebAuthenticationDevicePublicKey] AuthenticationExtensionsDevicePublicKeyOutputs devicePubKey;
+
+  // Pseudo-random function support.
+  // https://w3c.github.io/webauthn/#prf-extension
+  [RuntimeEnabled=WebAuthenticationPRF] AuthenticationExtensionsPRFOutputs prf;
 };
diff --git a/third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_prf_inputs.idl b/third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_prf_inputs.idl
new file mode 100644
index 0000000..991fa474
--- /dev/null
+++ b/third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_prf_inputs.idl
@@ -0,0 +1,15 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://w3c.github.io/webauthn/#prf-extension
+
+dictionary AuthenticationExtensionsPRFInputs {
+  AuthenticationExtensionsPRFValues eval;
+  record<USVString, AuthenticationExtensionsPRFValues> evalByCredential;
+};
+
+dictionary AuthenticationExtensionsPRFValues {
+    required ArrayBuffer first;
+    ArrayBuffer second;
+};
diff --git a/third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_prf_outputs.idl b/third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_prf_outputs.idl
new file mode 100644
index 0000000..2b7db22c
--- /dev/null
+++ b/third_party/blink/renderer/modules/credentialmanagement/authentication_extensions_prf_outputs.idl
@@ -0,0 +1,10 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://w3c.github.io/webauthn/#prf-extension
+
+dictionary AuthenticationExtensionsPRFOutputs {
+    boolean enabled;
+    AuthenticationExtensionsPRFValues results;
+};
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc
index 483b904b..484615b 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc
+++ b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc
@@ -17,6 +17,8 @@
 #include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_device_public_key_inputs.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_large_blob_inputs.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_payment_inputs.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_prf_inputs.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_prf_values.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_authenticator_selection_criteria.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_cable_authentication_data.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_cable_registration_data.h"
@@ -38,6 +40,8 @@
 #include "third_party/blink/renderer/modules/credentialmanagement/public_key_credential.h"
 #include "third_party/blink/renderer/platform/bindings/enumeration_base.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/wtf/text/base64.h"
+#include "third_party/boringssl/src/include/openssl/sha.h"
 
 namespace mojo {
 
@@ -61,6 +65,8 @@
 using blink::mojom::blink::LargeBlobSupport;
 using blink::mojom::blink::LogoutRpsRequest;
 using blink::mojom::blink::LogoutRpsRequestPtr;
+using blink::mojom::blink::PRFValues;
+using blink::mojom::blink::PRFValuesPtr;
 using blink::mojom::blink::PublicKeyCredentialCreationOptionsPtr;
 using blink::mojom::blink::PublicKeyCredentialDescriptor;
 using blink::mojom::blink::PublicKeyCredentialDescriptorPtr;
@@ -90,6 +96,40 @@
   return mojo_parameter;
 }
 
+// HashPRFValue hashes a PRF evaluation point with a fixed prefix in order to
+// separate the set of points that a website can evaluate. See
+// https://w3c.github.io/webauthn/#prf-extension.
+Vector<uint8_t> HashPRFValue(const blink::DOMArrayBuffer* value) {
+  constexpr char kPrefix[] = "WebAuthn PRF";
+
+  SHA256_CTX ctx;
+  SHA256_Init(&ctx);
+  // This deliberately includes the terminating NUL.
+  SHA256_Update(&ctx, kPrefix, sizeof(kPrefix));
+  SHA256_Update(&ctx, value->Data(), value->ByteLength());
+
+  uint8_t digest[SHA256_DIGEST_LENGTH];
+  SHA256_Final(digest, &ctx);
+
+  return Vector<uint8_t>(base::span(digest));
+}
+
+// SortPRFValuesByCredentialId is a "less than" function that puts the single,
+// optional element without a credential ID at the beginning and otherwise
+// lexicographically sorts by credential ID. The browser requires that PRF
+// values be presented in this order so that it can easily establish that there
+// are no duplicates.
+bool SortPRFValuesByCredentialId(const PRFValuesPtr& a, const PRFValuesPtr& b) {
+  if (!a->id.has_value()) {
+    return true;
+  } else if (!b->id.has_value()) {
+    return false;
+  } else {
+    return std::lexicographical_compare(a->id->begin(), a->id->end(),
+                                        b->id->begin(), b->id->end());
+  }
+}
+
 }  // namespace
 
 // static
@@ -543,6 +583,9 @@
       mojo_options->device_public_key =
           DevicePublicKeyRequest::From(*extensions->devicePubKey());
     }
+    if (extensions->hasPrf()) {
+      mojo_options->prf_enable = true;
+    }
   }
 
   return mojo_options;
@@ -678,6 +721,11 @@
       mojo_options->device_public_key =
           DevicePublicKeyRequest::From(*extensions->devicePubKey());
     }
+    if (extensions->hasPrf()) {
+      mojo_options->prf = true;
+      mojo_options->prf_inputs =
+          ConvertTo<Vector<PRFValuesPtr>>(*extensions->prf());
+    }
   }
 
   return mojo_options;
@@ -747,4 +795,40 @@
   return ret;
 }
 
+// static
+PRFValuesPtr
+TypeConverter<PRFValuesPtr, blink::AuthenticationExtensionsPRFValues>::Convert(
+    const blink::AuthenticationExtensionsPRFValues& values) {
+  PRFValuesPtr ret = PRFValues::New();
+  ret->first = HashPRFValue(values.first());
+  if (values.hasSecond()) {
+    ret->second = HashPRFValue(values.second());
+  }
+  return ret;
+}
+
+// static
+Vector<PRFValuesPtr>
+TypeConverter<Vector<PRFValuesPtr>, blink::AuthenticationExtensionsPRFInputs>::
+    Convert(const blink::AuthenticationExtensionsPRFInputs& prf) {
+  Vector<PRFValuesPtr> ret;
+  if (prf.hasEval()) {
+    ret.push_back(ConvertTo<PRFValuesPtr>(*prf.eval()));
+  }
+  if (prf.hasEvalByCredential()) {
+    for (const auto& pair : prf.evalByCredential()) {
+      Vector<char> cred_id;
+      // The fact that this decodes successfully has already been tested.
+      CHECK(WTF::Base64UnpaddedURLDecode(pair.first, cred_id));
+
+      PRFValuesPtr values = ConvertTo<PRFValuesPtr>(*pair.second);
+      values->id = Vector<uint8_t>(base::as_bytes(base::make_span(cred_id)));
+      ret.emplace_back(std::move(values));
+    }
+  }
+
+  std::sort(ret.begin(), ret.end(), SortPRFValuesByCredentialId);
+  return ret;
+}
+
 }  // namespace mojo
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h
index 2f40233..0ea9774 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h
+++ b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h
@@ -17,6 +17,8 @@
 
 namespace blink {
 class AuthenticationExtensionsDevicePublicKeyInputs;
+class AuthenticationExtensionsPRFInputs;
+class AuthenticationExtensionsPRFValues;
 class AuthenticatorSelectionCriteria;
 class CableAuthenticationData;
 class CableRegistrationData;
@@ -216,6 +218,20 @@
       const blink::AuthenticationExtensionsDevicePublicKeyInputs&);
 };
 
+template <>
+struct TypeConverter<blink::mojom::blink::PRFValuesPtr,
+                     blink::AuthenticationExtensionsPRFValues> {
+  static StructPtr<blink::mojom::blink::PRFValues> Convert(
+      const blink::AuthenticationExtensionsPRFValues&);
+};
+
+template <>
+struct TypeConverter<Vector<blink::mojom::blink::PRFValuesPtr>,
+                     blink::AuthenticationExtensionsPRFInputs> {
+  static Vector<StructPtr<blink::mojom::blink::PRFValues>> Convert(
+      const blink::AuthenticationExtensionsPRFInputs&);
+};
+
 }  // namespace mojo
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_CREDENTIALMANAGEMENT_CREDENTIAL_MANAGER_TYPE_CONVERTERS_H_
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc b/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc
index 3f7e135..cf9fb4a 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc
+++ b/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc
@@ -24,6 +24,9 @@
 #include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_large_blob_inputs.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_large_blob_outputs.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_payment_inputs.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_prf_inputs.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_prf_outputs.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_prf_values.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_authenticator_selection_criteria.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_credential_creation_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_credential_properties_output.h"
@@ -70,6 +73,7 @@
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "third_party/blink/renderer/platform/wtf/text/base64.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
 
@@ -699,6 +703,11 @@
         std::move(credential->device_public_key->signature)));
     extension_outputs->setDevicePubKey(device_public_key_outputs);
   }
+  if (credential->echo_prf) {
+    auto* prf_outputs = AuthenticationExtensionsPRFOutputs::Create();
+    prf_outputs->setEnabled(credential->prf);
+    extension_outputs->setPrf(prf_outputs);
+  }
   resolver->Resolve(MakeGarbageCollected<PublicKeyCredential>(
       credential->info->id, raw_id, authenticator_response,
       credential->authenticator_attachment, extension_outputs));
@@ -842,6 +851,20 @@
           std::move(credential->device_public_key->signature)));
       extension_outputs->setDevicePubKey(device_public_key_outputs);
     }
+    if (credential->echo_prf) {
+      auto* prf_outputs = AuthenticationExtensionsPRFOutputs::Create();
+      if (credential->prf_results) {
+        auto* values = AuthenticationExtensionsPRFValues::Create();
+        values->setFirst(
+            VectorToDOMArrayBuffer(std::move(credential->prf_results->first)));
+        if (credential->prf_results->second) {
+          values->setSecond(VectorToDOMArrayBuffer(
+              std::move(credential->prf_results->second.value())));
+        }
+        prf_outputs->setResults(values);
+      }
+      extension_outputs->setPrf(prf_outputs);
+    }
     resolver->Resolve(MakeGarbageCollected<PublicKeyCredential>(
         credential->info->id,
         VectorToDOMArrayBuffer(std::move(credential->info->raw_id)),
@@ -1000,6 +1023,25 @@
   return true;
 }
 
+const char* validateGetPublicKeyCredentialPRFExtension(
+    const AuthenticationExtensionsPRFInputs& prf) {
+  if (prf.hasEvalByCredential()) {
+    for (const auto& pair : prf.evalByCredential()) {
+      Vector<char> cred_id;
+      if (!pair.first.Is8Bit() ||
+          !WTF::Base64UnpaddedURLDecode(pair.first, cred_id)) {
+        return "'prf' extension contains invalid base64url data in "
+               "'evalByCredential'";
+      }
+      if (cred_id.empty()) {
+        return "'prf' extension contains an empty credential ID in "
+               "'evalByCredential'";
+      }
+    }
+  }
+  return nullptr;
+}
+
 }  // namespace
 
 const char CredentialsContainer::kSupplementName[] = "CredentialsContainer";
@@ -1173,6 +1215,24 @@
           return promise;
         }
       }
+      if (options->publicKey()->extensions()->hasPrf()) {
+        const char* error = validateGetPublicKeyCredentialPRFExtension(
+            *options->publicKey()->extensions()->prf());
+        if (error == nullptr &&
+            options->publicKey()->extensions()->prf()->hasEvalByCredential() &&
+            options->publicKey()->allowCredentials().empty()) {
+          error =
+              "'prf' extension has 'evalByCredential' with an empty allow list";
+        }
+        // Prohibiting uv=preferred is omitted. See
+        // https://github.com/w3c/webauthn/pull/1836.
+
+        if (error != nullptr) {
+          resolver->Reject(MakeGarbageCollected<DOMException>(
+              DOMExceptionCode::kNotSupportedError, error));
+          return promise;
+        }
+      }
       if (RuntimeEnabledFeatures::SecurePaymentConfirmationEnabled(context) &&
           options->publicKey()->extensions()->hasPayment()) {
         resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -1615,6 +1675,16 @@
         !IsPaymentExtensionValid(options, resolver)) {
       return promise;
     }
+    if (options->publicKey()->extensions()->hasPrf()) {
+      const auto& prf = *options->publicKey()->extensions()->prf();
+      if (prf.hasEvalByCredential()) {
+        resolver->Reject(MakeGarbageCollected<DOMException>(
+            DOMExceptionCode::kNotSupportedError,
+            "The 'evalByCredential' field cannot be set when creating a "
+            "credential."));
+        return promise;
+      }
+    }
   }
 
   std::unique_ptr<ScopedAbortState> scoped_abort_state = nullptr;
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_database.cc b/third_party/blink/renderer/modules/indexeddb/idb_database.cc
index 75b35b5c..1a34c86 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_database.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_database.cc
@@ -560,13 +560,7 @@
 }
 
 void IDBDatabase::ContextEnteredBackForwardCache() {
-  if (base::FeatureList::IsEnabled(
-          features::kAllowPageWithIDBTransactionInBFCache)) {
-    CHECK(base::FeatureList::IsEnabled(
-        features::kAllowPageWithIDBConnectionInBFCache))
-        << "kAllowPageWithIDBTransactionInBFCache should only be turned on "
-           "when kAllowPageWithIDBConnectionInBFCache is on.";
-
+  if (features::IsAllowPageWithIDBConnectionAndTransactionInBFCacheEnabled()) {
     if (backend_) {
       backend_->DidBecomeInactive();
     }
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_xnnpack.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_xnnpack.cc
index d8735d08..3d7b8caa 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_xnnpack.cc
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_xnnpack.cc
@@ -15,6 +15,7 @@
 #include "base/trace_event/typed_macros.h"
 #include "build/buildflag.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_ml_clamp_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_conv_2d_options.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/modules/ml/ml.h"
@@ -354,6 +355,19 @@
   XnnOutputRange output_range;
   switch (ml_operator->Kind()) {
     // TODO(crbug.com/1273291): Support clamp.
+    case MLOperator::OperatorKind::kClamp: {
+      // According to WebNN clamp spec:
+      // https://www.w3.org/TR/webnn/#api-mlgraphbuilder-clamp, clamping occurs
+      // only if the lower bound or/and upper bound are provided.
+      const auto* options =
+          static_cast<const MLClampOptions*>(ml_operator->Options());
+      DCHECK(options);
+      output_range.min =
+          options->getMinValueOr(-std::numeric_limits<float>::infinity());
+      output_range.max =
+          options->getMaxValueOr(+std::numeric_limits<float>::infinity());
+      break;
+    }
     case MLOperator::OperatorKind::kRelu:
       // Set the minimum value to 0 according to the rectified linear function,
       // y = max(0, x).
@@ -367,6 +381,22 @@
   return output_range;
 }
 
+xnn_status DefineXnnNodeForClamp(xnn_subgraph_t subgraph,
+                                 const MLOperator* clamp,
+                                 const OperandValueIdMap& operand_value_id_map,
+                                 String& error_message) {
+  const uint32_t input_id =
+      GetOperatorInputValueId(clamp, operand_value_id_map);
+  const uint32_t output_id =
+      GetOperatorOutputValueId(clamp, operand_value_id_map);
+  const auto output_range = GetXnnOutputRangeForActivation(clamp);
+  const uint32_t flags = 0;
+  XNN_CHECK_STATUS_AND_SET_ERROR_MESSAGE(
+      xnn_define_clamp(subgraph, output_range.min, output_range.max, input_id,
+                       output_id, flags));
+  return xnn_status_success;
+}
+
 xnn_status DefineXnnNodeForConv2d(xnn_subgraph_t subgraph,
                                   const MLOperator* conv2d,
                                   const OperandValueIdMap& operand_value_id_map,
@@ -496,6 +526,7 @@
                               .max = +std::numeric_limits<float>::infinity()};
   if (options->hasActivation()) {
     switch (options->activation()->Kind()) {
+      case MLOperator::OperatorKind::kClamp:
       case MLOperator::OperatorKind::kRelu:
         output_range = GetXnnOutputRangeForActivation(options->activation());
         break;
@@ -608,6 +639,10 @@
                          const OperandValueIdMap& operand_value_id_map,
                          String& error_message) {
   switch (ml_operator->Kind()) {
+    case MLOperator::OperatorKind::kClamp:
+      XNN_CHECK_STATUS(DefineXnnNodeForClamp(
+          subgraph, ml_operator, operand_value_id_map, error_message));
+      break;
     case MLOperator::OperatorKind::kConv2d:
       XNN_CHECK_STATUS(DefineXnnNodeForConv2d(
           subgraph, ml_operator, operand_value_id_map, error_message));
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_xnnpack_test.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_xnnpack_test.cc
index 819b10cea..17c8cf7 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_xnnpack_test.cc
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_xnnpack_test.cc
@@ -12,6 +12,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_ml_clamp_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_conv_2d_options.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -780,6 +781,84 @@
 }
 
 template <typename T>
+struct ClampTester {
+  MLGraphXnnpackTest* helper;
+  OperandInfo<T> input;
+  Vector<T> expected;
+
+  void Test(V8TestingScope& scope,
+            MLClampOptions* options = MLClampOptions::Create()) {
+    // Build the graph.
+    auto* builder = CreateMLGraphBuilder(scope);
+    auto* input_operand =
+        BuildInput(scope, builder, "input", input.dimensions, input.type);
+    auto* output_operand =
+        builder->clamp(input_operand, options, scope.GetExceptionState());
+    auto [graph, build_exception] =
+        helper->BuildGraph(scope, builder, {{"output", output_operand}});
+    EXPECT_NE(graph, nullptr);
+
+    // Compute the graph.
+    auto input_buffer =
+        CreateArrayBufferViewForOperand(input_operand, input.values);
+    auto output_buffer = CreateArrayBufferViewForOperand(output_operand);
+    auto* compute_exception = helper->ComputeGraph(
+        scope, graph, {{"input", input_buffer}}, {{"output", output_buffer}});
+    EXPECT_EQ(compute_exception, nullptr);
+    auto results = GetArrayBufferViewValues<T>(output_buffer);
+    EXPECT_EQ(results, expected);
+  }
+};
+
+TEST_P(MLGraphXnnpackTest, ClampTest) {
+  V8TestingScope scope;
+  {
+    // Test clamp operator with default options that no minimum and maximum
+    // values are defined.
+    ClampTester<float>{.helper = this,
+                       .input = {.type = V8MLOperandType::Enum::kFloat32,
+                                 .dimensions = {1, 2, 2, 1},
+                                 .values = {-10.0, -0.5, 0.5, 10.0}},
+                       .expected = {-10.0, -0.5, 0.5, 10.0}}
+        .Test(scope);
+  }
+  {
+    // Test clamp operator with the minimum value defined.
+    MLClampOptions* options = MLClampOptions::Create();
+    options->setMinValue(0.0);
+    ClampTester<float>{.helper = this,
+                       .input = {.type = V8MLOperandType::Enum::kFloat32,
+                                 .dimensions = {1, 2, 2, 1},
+                                 .values = {-10.0, -0.5, 0.5, 10.0}},
+                       .expected = {0.0, 0.0, 0.5, 10.0}}
+        .Test(scope, options);
+  }
+  {
+    // Test clamp operator with the maximum value defined.
+    MLClampOptions* options = MLClampOptions::Create();
+    options->setMaxValue(6.0);
+    ClampTester<float>{.helper = this,
+                       .input = {.type = V8MLOperandType::Enum::kFloat32,
+                                 .dimensions = {1, 2, 2, 1},
+                                 .values = {-10.0, -0.5, 0.5, 10.0}},
+                       .expected = {-10.0, -0.5, 0.5, 6.0}}
+        .Test(scope, options);
+  }
+  {
+    // Test clamp operator with both the minimum and maximum values defined.
+    MLClampOptions* options = MLClampOptions::Create();
+    options->setMinValue(0.0);
+    options->setMaxValue(6.0);
+    ClampTester<float>{.helper = this,
+                       .input = {.type = V8MLOperandType::Enum::kFloat32,
+                                 .dimensions = {1, 2, 2, 1},
+                                 .values = {-10.0, -0.5, 0.5, 10.0}},
+                       .expected = {0.0, 0.0, 0.5, 6.0}}
+        .Test(scope, options);
+  }
+}
+
+template <typename T>
 MLOperand* BuildConstant(V8TestingScope& scope,
                          MLGraphBuilder* builder,
                          const Vector<uint32_t>& dimensions,
@@ -918,6 +997,35 @@
         .expected = {0.0, 0.0, 11000.0, 9000.0}}
         .Test(scope, builder, options);
   }
+  {
+    // Test fused depthwise conv2d operator by setting groups to input channels,
+    // nhwc input layout, ihwo filter layout, fusing with bias operand and clamp
+    // activation.
+    auto* options = MLConv2dOptions::Create();
+    options->setInputLayout(V8MLInputOperandLayout::Enum::kNhwc);
+    options->setFilterLayout(V8MLConv2dFilterOperandLayout::Enum::kIhwo);
+    options->setGroups(4);
+    auto* clamp_options = MLClampOptions::Create();
+    clamp_options->setMinValue(0.0);
+    clamp_options->setMaxValue(6.0);
+    options->setActivation(
+        builder->clamp(clamp_options, scope.GetExceptionState()));
+    Conv2dTester<float>{
+        .input = {.type = V8MLOperandType::Enum::kFloat32,
+                  .dimensions = {1, 2, 2, 4},
+                  .values = {10.0, 21.0, 10.0, 0.0, 10.0, 22.0, 20.0, 0.0, 10.0,
+                             23.0, 30.0, 0.0, 10.0, 24.0, 40.0, 0.0}},
+        .filter = {.type = V8MLOperandType::Enum::kFloat32,
+                   .dimensions = {1, 2, 2, 4},
+                   .values = {0.25, 0.0, 10.0, 50.0, 0.25, 1.0, 20.0, 50.0,
+                              0.25, 0.0, 30.0, 50.0, 0.25, 1.0, 40.0, 50.0}},
+        .bias =
+            OperandInfo<float>{.type = V8MLOperandType::Enum::kFloat32,
+                               .dimensions = {4},
+                               .values = {-6000.0, -7000.0, 8000.0, 9000.0}},
+        .expected = {0.0, 0.0, 6.0, 6.0}}
+        .Test(scope, builder, options);
+  }
 }
 
 // TODO(crbug.com/1273291): Test the async execution mode once the
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame.cc b/third_party/blink/renderer/modules/webcodecs/video_frame.cc
index 4992e31..c976c91c 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_frame.cc
+++ b/third_party/blink/renderer/modules/webcodecs/video_frame.cc
@@ -1298,7 +1298,7 @@
                                                orientation_enum),
         crop_rect, options);
     return ImageBitmapSource::FulfillImageBitmap(script_state, image_bitmap,
-                                                 exception_state);
+                                                 options, exception_state);
   }
 
   auto* execution_context =
@@ -1335,7 +1335,7 @@
   auto* image_bitmap =
       MakeGarbageCollected<ImageBitmap>(image, crop_rect, options);
   return ImageBitmapSource::FulfillImageBitmap(script_state, image_bitmap,
-                                               exception_state);
+                                               options, exception_state);
 }
 
 void VideoFrame::Trace(Visitor* visitor) const {
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
index 7f49d321..c28545c 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
@@ -599,7 +599,7 @@
     if (has_other_effects) {
       cc::PaintFlags flags;
       flags.setBlendMode(effect.BlendMode());
-      flags.setAlpha(alpha);
+      flags.setAlphaf(alpha / 255.0f);
       save_layer_id = push<cc::SaveLayerOp>(flags);
     } else {
       save_layer_id =
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_image_util.cc b/third_party/blink/renderer/platform/graphics/video_frame_image_util.cc
index 6c6c7388..6368e893 100644
--- a/third_party/blink/renderer/platform/graphics/video_frame_image_util.cc
+++ b/third_party/blink/renderer/platform/graphics/video_frame_image_util.cc
@@ -269,7 +269,7 @@
   }
 
   cc::PaintFlags media_flags;
-  media_flags.setAlpha(0xFF);
+  media_flags.setAlphaf(1.0f);
   media_flags.setFilterQuality(cc::PaintFlags::FilterQuality::kLow);
   media_flags.setBlendMode(SkBlendMode::kSrc);
 
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 2f26171..ce3ca1964 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -2908,6 +2908,14 @@
       status: "experimental",
     },
     {
+      // Allow unbalanced columns (no implicit breaks), even if the block-size
+      // of the multicol container isn't constrained, rather than forcing column
+      // balancing in such cases. See crbug.com/1156312
+      name: "UnconstrainedColumnFillAuto",
+      status: "stable",
+      base_feature: "UnconstrainedColumnFillAuto",
+    },
+    {
       name: "UnexposedTaskIds",
     },
     // This is a reverse OT used for a phased deprecation, on desktop
@@ -3134,6 +3142,11 @@
       name: "WebAuthenticationLargeBlobExtension",
       status: "experimental",
     },
+    // https://w3c.github.io/webauthn/#prf-extension
+    {
+      name: "WebAuthenticationPRF",
+      status: "experimental",
+    },
     {
       name: "WebAuthenticationRemoteDesktopSupport",
       public: true,
diff --git a/third_party/blink/tools/BUILD.gn b/third_party/blink/tools/BUILD.gn
index 41485e0..55e419ac 100644
--- a/third_party/blink/tools/BUILD.gn
+++ b/third_party/blink/tools/BUILD.gn
@@ -7,7 +7,6 @@
   testonly = true
   data = [
     # Include the test runner.
-    "//testing/scripts/wpt_common.py",
     "//third_party/blink/tools/run_wpt_tests.py",
 
     # WPT tooling
diff --git a/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py b/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py
index a9d86d8..4c836e1 100644
--- a/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py
+++ b/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py
@@ -154,6 +154,8 @@
             mapping tests that couldn't be rebaselined to lists of expectation
             lines written to flag specific test expectations.
         """
+        # TODO(crbug.com/1344709): This method has no coverage and should be
+        # merged with `update_expectations`.
         self.port.wpt_manifest.cache_clear()
 
         issue_number = self.get_issue_number()
@@ -164,7 +166,7 @@
         # instead of hardcoding.
         builder = 'linux-blink-rel'
         builder_names = [builder]
-        test_suite = self.flag_specific_suite(builder, flag_specific)
+        test_suite = self.suite_for_builder(builder, flag_specific)
 
         build_to_status = self.git_cl.latest_try_jobs(
             builder_names=builder_names,
diff --git a/third_party/blink/tools/run_wpt_tests.py b/third_party/blink/tools/run_wpt_tests.py
index eee5535..b8d4aeb 100755
--- a/third_party/blink/tools/run_wpt_tests.py
+++ b/third_party/blink/tools/run_wpt_tests.py
@@ -6,6 +6,7 @@
 
 import argparse
 import contextlib
+import glob
 import json
 import logging
 import os
@@ -14,6 +15,7 @@
 
 from blinkpy.common import exit_codes
 from blinkpy.common import path_finder
+from blinkpy.common.host import Host
 from blinkpy.common.path_finder import PathFinder
 from blinkpy.web_tests.port.android import (
     ANDROID_WEBLAYER,
@@ -24,7 +26,6 @@
 path_finder.add_testing_dir_to_sys_path()
 path_finder.add_build_android_to_sys_path()
 
-from scripts import wpt_common
 from scripts import common
 
 logger = logging.getLogger(__name__)
@@ -84,10 +85,17 @@
     'wpt_args', lambda arg: '--binary-arg=%s' % arg)
 
 
-class WPTAdapter(wpt_common.BaseWptScriptAdapter):
+class WPTAdapter(common.BaseIsolatedScriptArgsAdapter):
     def __init__(self):
         self._tmp_dir = None
-        super().__init__()
+        self.host = Host()
+        self.fs = self.host.filesystem
+        self.path_finder = PathFinder(self.fs)
+        self.port = self.host.port_factory.get()
+        super(WPTAdapter, self).__init__()
+        self.wptreport = None
+        self._include_filename = None
+        self.layout_test_results_subdir = 'layout-test-results'
         self._parser = self._override_options(self._parser)
         # Parent adapter adds extra arguments, so it is safe to parse the
         # arguments and set options here.
@@ -408,6 +416,138 @@
         with self.fs.open_text_file_for_writing(run_info_path) as file_handle:
             json.dump(run_info, file_handle)
 
+    @property
+    def _wpt_run_args(self):
+        """The start of a 'wpt run' command."""
+        return [
+            self.wpt_binary,
+            # Use virtualenv packages installed by vpython, not wpt.
+            '--venv=%s' % self.path_finder.chromium_base(),
+            '--skip-venv-setup',
+            'run',
+        ]
+
+    def maybe_set_default_isolated_script_test_output(self):
+        if self.options.isolated_script_test_output:
+            return
+        default_value = self.path_finder.path_from_chromium_base(
+            'out', self.options.target, "results.json")
+        print("--isolated-script-test-output not set, defaulting to %s" %
+              default_value)
+        self.options.isolated_script_test_output = default_value
+
+    def generate_test_output_args(self, output):
+        return ['--log-chromium=%s' % output]
+
+    def _resolve_tests_from_isolate_filter(self, test_filter):
+        """Resolve an isolated script-style filter string into lists of tests.
+
+        Arguments:
+            test_filter (str): Glob patterns delimited by double colons ('::').
+                The glob is prefixed with '-' to indicate that tests matching
+                the pattern should not run. Assume a valid wpt name cannot start
+                with '-'.
+
+        Returns:
+            tuple[list[str], list[str]]: Tests to include and exclude,
+                respectively.
+        """
+        included_tests, excluded_tests = [], []
+        for pattern in common.extract_filter_list(test_filter):
+            test_group = included_tests
+            if pattern.startswith('-'):
+                test_group, pattern = excluded_tests, pattern[1:]
+            if self.path_finder.is_wpt_internal_path(pattern):
+                pattern_on_disk = self.path_finder.path_from_web_tests(pattern)
+            else:
+                pattern_on_disk = self.fs.join(self.wpt_root_dir, pattern)
+            test_group.extend(glob.glob(pattern_on_disk))
+        return included_tests, excluded_tests
+
+    def generate_test_filter_args(self, test_filter_str):
+        included_tests, excluded_tests = \
+            self._resolve_tests_from_isolate_filter(test_filter_str)
+        include_file, self._include_filename = self.fs.open_text_tempfile()
+        with include_file:
+            for test in included_tests:
+                include_file.write(test)
+                include_file.write('\n')
+        wpt_args = ['--include-file=%s' % self._include_filename]
+        for test in excluded_tests:
+            wpt_args.append('--exclude=%s' % test)
+        return wpt_args
+
+    def generate_test_repeat_args(self, repeat_count):
+        return ['--repeat=%d' % repeat_count]
+
+    @property
+    def _has_explicit_tests(self):
+        # TODO(crbug.com/1356318): `run_wpt_tests` has multiple ways to
+        # explicitly specify tests. Some are inherited from wptrunner, the rest
+        # from Chromium infra. After we consolidate `run_wpt_tests` and
+        # `wpt_common`, maybe we should build a single explicit test list to
+        # simplify this check?
+        for test_or_option in super().rest_args:
+            if not test_or_option.startswith('-'):
+                return True
+        return (getattr(self.options, 'include', None)
+                or getattr(self.options, 'include_file', None)
+                or getattr(self.options, 'gtest_filter', None)
+                or self._include_filename)
+
+    def generate_test_launcher_retry_limit_args(self, retry_limit):
+        return ['--retry-unexpected=%d' % retry_limit]
+
+    def generate_sharding_args(self, total_shards, shard_index):
+        return [
+            '--total-chunks=%d' % total_shards,
+            # shard_index is 0-based but WPT's this-chunk to be 1-based
+            '--this-chunk=%d' % (shard_index + 1),
+            # The default sharding strategy is to shard by directory. But
+            # we want to hash each test to determine which shard runs it.
+            # This allows running individual directories that have few
+            # tests across many shards.
+            '--chunk-type=hash'
+        ]
+
+    @property
+    def _default_retry_limit(self) -> int:
+        return 0 if self._has_explicit_tests else 3
+
+    @property
+    def wpt_output(self):
+        return self.options.isolated_script_test_output
+
+    def _show_wpt_help(self):
+        command = [
+            self.select_python_executable(),
+        ]
+        command.extend(self._wpt_run_args)
+        command.extend(['--help'])
+        exit_code = common.run_command(command)
+        self.parser.exit(exit_code)
+
+    def process_and_upload_results(self):
+        command = [
+            self.select_python_executable(),
+            os.path.join(path_finder.get_blink_tools_dir(),
+                         'wpt_process_results.py'),
+            '--target',
+            self.options.target,
+            '--web-tests-dir',
+            self.path_finder.web_tests_dir(),
+            '--artifacts-dir',
+            os.path.join(os.path.dirname(self.wpt_output),
+                         self.layout_test_results_subdir),
+            '--wpt-results',
+            self.wpt_output,
+        ]
+        if self.options.verbose:
+            command.append('--verbose')
+        if self.wptreport:
+            command.extend(['--wpt-report', self.wptreport])
+        return common.run_command(command)
+
     def do_post_test_run_tasks(self):
         process_return = self.process_and_upload_results()
 
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 50227557..619444b 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -3427,9 +3427,6 @@
 crbug.com/614667 external/wpt/css/css-break/grid/grid-item-fragmentation-039.html [ Failure ]
 crbug.com/1058792 external/wpt/css/css-break/transform-007.html [ Failure ]
 crbug.com/1224888 external/wpt/css/css-break/transform-009.html [ Failure ]
-crbug.com/1156312 external/wpt/css/css-break/widows-orphans-017.html [ Failure ]
-crbug.com/967329 external/wpt/css/css-multicol/columnfill-auto-max-height-001.html [ Failure ]
-crbug.com/967329 external/wpt/css/css-multicol/columnfill-auto-max-height-002.html [ Failure ]
 crbug.com/1225630 external/wpt/css/css-multicol/large-actual-column-count.html [ Crash Failure Pass Timeout ]
 crbug.com/990240 external/wpt/css/css-multicol/multicol-breaking-000.html [ Failure ]
 crbug.com/990240 external/wpt/css/css-multicol/multicol-breaking-001.html [ Failure ]
@@ -6337,6 +6334,7 @@
 crbug.com/1395840 [ Mac ] http/tests/accessibility/slow-document-load.html [ Failure ]
 crbug.com/1404767 [ Debug Linux ] external/wpt/css/css-cascade/all-prop-revert-layer-noop.html [ Failure Timeout ]
 crbug.com/1406027 [ Win ] virtual/media-foundation-for-clear-dcomp/media/controls/overflow-menu-hide-on-resize.html [ Failure ]
+crbug.com/1289607 [ Linux ] external/wpt/cookie-store/cookieStore_subscribe_arguments.https.any.html [ Failure ]
 
 # Sheriff 2022-10-07
 crbug.com/1372556 [ Linux ] external/wpt/css/css-text/text-transform/text-transform-capitalize-* [ Failure Pass ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/columnfill-auto-max-height-003.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/columnfill-auto-max-height-003.html
new file mode 100644
index 0000000..a632c8fb
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/columnfill-auto-max-height-003.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-multicol-1/#cf">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width:100px; height:100px; background:red;">
+  <div style="columns:2; gap:0; column-fill:auto; max-height:200px; background:red;">
+    <div style="width:200%; height:100px; background:green;"></div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-fill-auto-004.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-fill-auto-004.html
new file mode 100644
index 0000000..18e6fa7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-fill-auto-004.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-multicol-1/#cf">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width:100px; height:100px; background:red;">
+  <div style="columns:5; gap:10px; column-fill:auto; column-rule:10px solid green;">
+    <div style="background:green;">
+      <div style="height:10px;"></div>
+      <div style="break-before:column; height:10px;"></div>
+      <div style="break-before:column; height:10px;"></div>
+      <div style="break-before:column; height:10px;"></div>
+      <div style="break-before:column; height:100px;"></div>
+    </div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-fill-balance-026.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-fill-balance-026.html
new file mode 100644
index 0000000..d38ca32
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-fill-balance-026.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-multicol-1/#cf">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width:100px; height:100px; background:red;">
+  <div style="columns:5; gap:0;">
+    <div style="columns:2; column-fill:auto; gap:0;">
+      <div style="height:1000px; background:green;"></div>
+    </div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/longtask-timing/longtask-promise.html b/third_party/blink/web_tests/external/wpt/longtask-timing/longtask-promise.html
new file mode 100644
index 0000000..1709304
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/longtask-timing/longtask-promise.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>LongTask Timing: long task in rAF</title>
+<body>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/utils.js"></script>
+
+<h1>Long Task: promises</h1>
+<script>
+  function test_promise_long_task(name, promise) {
+    promise_test(async t => {
+      assert_implements(window.PerformanceLongTaskTiming, 'Longtasks are not supported.');
+      const longTaskPromise = new Promise(resolve => {
+        const observer = new PerformanceObserver(t.step_func(entryList => resolve(entryList.getEntries())));
+        observer.observe({entryTypes: ['longtask']});
+      });
+
+      await promise().catch(() => {});
+      busyWait();
+      const entries = await longTaskPromise;
+      assert_greater_than_equal(entries.length, 1);
+    }, `Performance longtask entries after a promise: ${name}`);
+  }
+
+  test_promise_long_task("successful fetch", () => fetch("/common/dummy.xml"));
+  test_promise_long_task("Response.text()", () => fetch("/common/dummy.xml").then(r => r.text()));
+  test_promise_long_task("rejected fetch", () => fetch("/common/non-existent.xml"));
+  test_promise_long_task("JSON error", () => fetch("/common/dummy.xml").then(r => r.json()));
+  test_promise_long_task("image.decode", async () => {
+    const img = document.createElement("img");
+    img.src = "/images/blue.png";
+    return img.decode();
+  })
+</script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/longtask-timing/resources/utils.js b/third_party/blink/web_tests/external/wpt/longtask-timing/resources/utils.js
index 36bd6c7b..482b2b3 100644
--- a/third_party/blink/web_tests/external/wpt/longtask-timing/resources/utils.js
+++ b/third_party/blink/web_tests/external/wpt/longtask-timing/resources/utils.js
@@ -11,3 +11,8 @@
 function hasUnrelatedTaskName(taskName, expectedTaskName) {
   return (taskName !== expectedTaskName);
 }
+
+function busyWait(millis = 60) {
+  const start = performance.now()
+  while (performance.now() < (start + millis)) {}
+}
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/change-shipping-address-manual-manifest.json b/third_party/blink/web_tests/external/wpt/payment-handler/change-shipping-address-manual-manifest.json
new file mode 100644
index 0000000..08b034e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/payment-handler/change-shipping-address-manual-manifest.json
@@ -0,0 +1,20 @@
+{
+  "default_applications": ["change-shipping-address-manual-manifest.json"],
+  "name": "Test Payment Handler",
+  "icons": [
+    {
+      "src": "/images/rgrg-256x256.png",
+      "sizes": "256x256",
+      "type": "image/png"
+    }
+  ],
+  "serviceworker": {
+    "src": "app-change-shipping-address.js",
+    "scope": "change-shipping-address-manual-payment-app/"
+  },
+  "payment": {
+    "supported_delegations": [
+      "shippingAddress"
+    ]
+  }
+}
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/change-shipping-address-manual.https.html b/third_party/blink/web_tests/external/wpt/payment-handler/change-shipping-address-manual.https.html
index 3b98d56..e881745 100644
--- a/third_party/blink/web_tests/external/wpt/payment-handler/change-shipping-address-manual.https.html
+++ b/third_party/blink/web_tests/external/wpt/payment-handler/change-shipping-address-manual.https.html
@@ -1,161 +1,145 @@
 <!DOCTYPE html>
 <meta charset="utf-8" />
 <title>Tests for PaymentRequestEvent.changeShippingAddress()</title>
+<link
+  rel="help"
+  href="https://w3c.github.io/payment-handler/#changeshippingaddress-method"
+/>
 
-<link rel="manifest" href="/payment-handler/basic-card.json" />
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/resources/testdriver.js"></script>
 <script src="/resources/testdriver-vendor.js"></script>
-<script src="register-and-activate-service-worker.js"></script>
 <p>If the payment sheet is shown, please authorize the mock payment.</p>
 <script>
-  const methodName = window.location.origin + '/payment-handler/payment-app/';
-  function createRequest() {
-    return new PaymentRequest([{supportedMethods: methodName}], {
-        total: {label: 'Total', amount: {currency: 'USD', value: '0.01'}},
-        shippingOptions: [{
+const methodName = window.location.origin
+    + '/payment-handler/change-shipping-address-manual-manifest.json';
+function createRequest() {
+  return new PaymentRequest([{supportedMethods: methodName}], {
+      total: {label: 'Total', amount: {currency: 'USD', value: '0.01'}},
+      shippingOptions: [{
+        id: 'freeShippingOption',
+        label: 'Free global shipping',
+        amount: {
+          currency: 'USD',
+          value: '0',
+        },
+        selected: false,
+      }],
+    }, {requestShipping: true});
+}
+
+promise_test(async (t) => {
+  const request = createRequest();
+  // Intentionally do not respond to the 'shippingaddresschange' event.
+  const response = await test_driver.bless('showing a payment sheet', () =>
+    request.show()
+  );
+  const complete_promise = response.complete('success');
+
+  assert_equals(response.details.changeShippingAddressReturned, null);
+
+  return complete_promise;
+}, 'If updateWith(details) is not run, changeShippingAddress() returns null.');
+
+promise_test(async (t) => {
+  const request = createRequest();
+  request.addEventListener('shippingaddresschange', (event) => {
+    assert_equals(request.shippingAddress.organization, '', 'organization should be redacted');
+    assert_equals(request.shippingAddress.phone, '', 'phone should be redacted');
+    assert_equals(request.shippingAddress.recipient, '', 'recipient should be redacted');
+    assert_equals(request.shippingAddress.addressLine.length, 0, 'addressLine should be redacted');
+    assert_equals(request.shippingAddress.city, 'Reston');
+    assert_equals(request.shippingAddress.country, 'US');
+    assert_equals(request.shippingAddress.postalCode, '20190');
+    assert_equals(request.shippingAddress.region, 'VA');
+    event.updateWith({
+      total: {label: 'Total', amount: {currency: 'GBP', value: '0.02'}},
+      error: 'Error for test',
+      modifiers: [
+        {
+          supportedMethods: methodName,
+          data: {soup: 'potato'},
+          total: {
+            label: 'Modified total',
+            amount: {currency: 'EUR', value: '0.03'},
+          },
+          additionalDisplayItems: [
+            {
+              label: 'Modified display item',
+              amount: {currency: 'INR', value: '0.06'},
+            },
+          ],
+        },
+        {
+          supportedMethods: methodName + '2',
+          data: {soup: 'tomato'},
+          total: {
+            label: 'Modified total #2',
+            amount: {currency: 'CHF', value: '0.07'},
+          },
+          additionalDisplayItems: [
+            {
+              label: 'Modified display item #2',
+              amount: {currency: 'CAD', value: '0.08'},
+            },
+          ],
+        },
+      ],
+      displayItems: [
+        {
+          label: 'Display item',
+          amount: {currency: 'CNY', value: '0.04'},
+        },
+      ],
+      shippingOptions: [
+        {
           id: 'freeShippingOption',
-          label: 'Free global shipping',
+          label: 'express global shipping',
           amount: {
             currency: 'USD',
             value: '0',
           },
-          selected: false,
-        }],
-      }, {requestShipping: true});
-  }
-
-  async function completeAppSetUp(registration) {
-    await registration.paymentManager.instruments.clear();
-    await registration.paymentManager.instruments.set('instrument-key', {
-      name: 'Instrument Name',
-      method: methodName,
+          selected: true,
+        }
+      ],
+        shippingAddressErrors: {
+        country: 'US only shipping',
+      }
     });
-    await navigator.serviceWorker.ready;
-    await registration.paymentManager.enableDelegations(['shippingAddress']);
-  }
-
-  async function runTests(registration) {
-    await completeAppSetUp(registration);
-    promise_test(async (t) => {
-      const request = createRequest();
-      // Intentionally do not respond to the 'shippingaddresschange' event.
-      const response = await test_driver.bless('showing a payment sheet', () =>
-        request.show()
-      );
-      const complete_promise = response.complete('success');
-
-      assert_equals(response.details.changeShippingAddressReturned, null);
-
-      return complete_promise;
-    }, 'If updateWith(details) is not run, changeShippingAddress() returns null.');
-
-    promise_test(async (t) => {
-      const request = createRequest();
-      request.addEventListener('shippingaddresschange', (event) => {
-        assert_equals(request.shippingAddress.organization, '', 'organization should be redacted');
-        assert_equals(request.shippingAddress.phone, '', 'phone should be redacted');
-        assert_equals(request.shippingAddress.recipient, '', 'recipient should be redacted');
-        assert_equals(request.shippingAddress.addressLine.length, 0, 'addressLine should be redacted');
-        assert_equals(request.shippingAddress.city, 'Reston');
-        assert_equals(request.shippingAddress.country, 'US');
-        assert_equals(request.shippingAddress.postalCode, '20190');
-        assert_equals(request.shippingAddress.region, 'VA');
-        event.updateWith({
-          total: {label: 'Total', amount: {currency: 'GBP', value: '0.02'}},
-          error: 'Error for test',
-          modifiers: [
-            {
-              supportedMethods: methodName,
-              data: {soup: 'potato'},
-              total: {
-                label: 'Modified total',
-                amount: {currency: 'EUR', value: '0.03'},
-              },
-              additionalDisplayItems: [
-                {
-                  label: 'Modified display item',
-                  amount: {currency: 'INR', value: '0.06'},
-                },
-              ],
-            },
-            {
-              supportedMethods: methodName + '2',
-              data: {soup: 'tomato'},
-              total: {
-                label: 'Modified total #2',
-                amount: {currency: 'CHF', value: '0.07'},
-              },
-              additionalDisplayItems: [
-                {
-                  label: 'Modified display item #2',
-                  amount: {currency: 'CAD', value: '0.08'},
-                },
-              ],
-            },
-          ],
-          displayItems: [
-            {
-              label: 'Display item',
-              amount: {currency: 'CNY', value: '0.04'},
-            },
-          ],
-          shippingOptions: [
-            {
-              id: 'freeShippingOption',
-              label: 'express global shipping',
-              amount: {
-                currency: 'USD',
-                value: '0',
-              },
-              selected: true,
-            }
-          ],
-           shippingAddressErrors: {
-            country: 'US only shipping',
-          }
-        });
-      });
-      const response = await test_driver.bless('showing a payment sheet', () =>
-        request.show()
-      );
-      const complete_promise = response.complete('success');
-      const changeShippingAddressReturned =
-        response.details.changeShippingAddressReturned;
-
-      assert_equals(changeShippingAddressReturned.total.currency, 'GBP');
-      assert_equals(changeShippingAddressReturned.total.value, '0.02');
-      assert_equals(changeShippingAddressReturned.total.label, undefined);
-      assert_equals(changeShippingAddressReturned.error, 'Error for test');
-      assert_equals(changeShippingAddressReturned.modifiers.length, 1);
-      assert_equals(changeShippingAddressReturned.displayItems, undefined);
-      assert_equals(changeShippingAddressReturned.shippingOptions.length, 1);
-      assert_equals(changeShippingAddressReturned.paymentMethodErrors, undefined);
-      assert_equals(changeShippingAddressReturned.shippingAddressErrors.country, 'US only shipping');
-
-      const shipping_option = changeShippingAddressReturned.shippingOptions[0];
-      assert_equals(shipping_option.id, 'freeShippingOption' );
-      assert_equals(shipping_option.label, 'express global shipping');
-      assert_equals(shipping_option.amount.currency, 'USD');
-      assert_equals(shipping_option.amount.value, '0');
-      assert_true(shipping_option.selected);
-
-      const modifier = changeShippingAddressReturned.modifiers[0];
-      assert_equals(modifier.supportedMethods, methodName);
-      assert_equals(modifier.data.soup, 'potato');
-      assert_equals(modifier.total.label, '');
-      assert_equals(modifier.total.amount.currency, 'EUR');
-      assert_equals(modifier.total.amount.value, '0.03');
-      assert_equals(modifier.additionalDisplayItems, undefined);
-
-      return complete_promise;
-    }, 'The changeShippingAddress() returns some details from the "shippingaddresschange" event\'s updateWith(details) call.');
-  }
-
-  registerAndActiveServiceWorker(
-    'app-change-shipping-address.js',
-    'payment-app/',
-    runTests
+  });
+  const response = await test_driver.bless('showing a payment sheet', () =>
+    request.show()
   );
+  const complete_promise = response.complete('success');
+  const changeShippingAddressReturned =
+    response.details.changeShippingAddressReturned;
+
+  assert_equals(changeShippingAddressReturned.total.currency, 'GBP');
+  assert_equals(changeShippingAddressReturned.total.value, '0.02');
+  assert_equals(changeShippingAddressReturned.total.label, undefined);
+  assert_equals(changeShippingAddressReturned.error, 'Error for test');
+  assert_equals(changeShippingAddressReturned.modifiers.length, 1);
+  assert_equals(changeShippingAddressReturned.displayItems, undefined);
+  assert_equals(changeShippingAddressReturned.shippingOptions.length, 1);
+  assert_equals(changeShippingAddressReturned.paymentMethodErrors, undefined);
+  assert_equals(changeShippingAddressReturned.shippingAddressErrors.country, 'US only shipping');
+
+  const shipping_option = changeShippingAddressReturned.shippingOptions[0];
+  assert_equals(shipping_option.id, 'freeShippingOption' );
+  assert_equals(shipping_option.label, 'express global shipping');
+  assert_equals(shipping_option.amount.currency, 'USD');
+  assert_equals(shipping_option.amount.value, '0');
+  assert_true(shipping_option.selected);
+
+  const modifier = changeShippingAddressReturned.modifiers[0];
+  assert_equals(modifier.supportedMethods, methodName);
+  assert_equals(modifier.data.soup, 'potato');
+  assert_equals(modifier.total.label, '');
+  assert_equals(modifier.total.amount.currency, 'EUR');
+  assert_equals(modifier.total.amount.value, '0.03');
+  assert_equals(modifier.additionalDisplayItems, undefined);
+
+  return complete_promise;
+}, 'The changeShippingAddress() returns some details from the "shippingaddresschange" event\'s updateWith(details) call.');
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-extensions.https.html b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-extensions.https.html
index 64690e7..5a55a8d 100644
--- a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-extensions.https.html
+++ b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-extensions.https.html
@@ -31,6 +31,19 @@
     new CreateCredentialsTest("options.publicKey.extensions", {appid: ""}).runTest("empty appid in create request", "NotSupportedError");
     new CreateCredentialsTest("options.publicKey.extensions", {appid: null}).runTest("null appid in create request", "NotSupportedError");
     new CreateCredentialsTest("options.publicKey.extensions", {appid: "anything"}).runTest("appid in create request", "NotSupportedError");
+
+    promise_test(async t => {
+      const credential = await createCredential({
+        options: {
+          publicKey: {
+            extensions: {
+              prf: {},
+            },
+          },
+        },
+      });
+      assert_false(credential.getClientExtensionResults().prf.enabled);
+    }, "navigator.credentials.create() with prf requested but no support in authenticator");
 });
 
 /* JSHINT */
diff --git a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-prf.https.html b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-prf.https.html
new file mode 100644
index 0000000..7243e088d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-prf.https.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>navigator.credentials.create() prf extension tests with authenticator support</title>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src=helpers.js></script>
+<body></body>
+<script>
+standardSetup(function() {
+  "use strict";
+
+  promise_test(async t => {
+    const credential = await createCredential({
+      options: {
+        publicKey: {
+          extensions: {
+            prf: {},
+          },
+        },
+      },
+    });
+    assert_true(credential.getClientExtensionResults().prf.enabled);
+  }, "navigator.credentials.create() with prf requested");
+
+  promise_test(async t => {
+    const promise = createCredential({
+      options: {
+        publicKey: {
+          extensions: {
+            prf: {evalByCredential: {"Zm9v": {first: new Uint8Array([1,2,3,4]).buffer}}},
+          },
+        },
+      },
+    });
+    return promise_rejects_dom(t, "NotSupportedError", promise);
+  }, "navigator.credentials.create() with nonsensical evalByCredential");
+}, {
+  protocol: "ctap2_1",
+  extensions: ["prf"],
+});
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/webauthn/getcredential-extensions.https.html b/third_party/blink/web_tests/external/wpt/webauthn/getcredential-extensions.https.html
index 2b5557d..16c1e574 100644
--- a/third_party/blink/web_tests/external/wpt/webauthn/getcredential-extensions.https.html
+++ b/third_party/blink/web_tests/external/wpt/webauthn/getcredential-extensions.https.html
@@ -53,6 +53,26 @@
     new GetCredentialsTest("options.publicKey.extensions", {payment: {isPayment:true}})
         .addCredential(credPromise)
         .runTest("Payment extension is only supported at registration", "NotAllowedError");
+
+    promise_test(async t => {
+      const id = (await credPromise).rawId;
+      const assertion = await navigator.credentials.get({publicKey: {
+        challenge: new Uint8Array(),
+        allowCredentials: [{
+          id: id,
+          type: "public-key",
+        }],
+        extensions: {
+          prf: {
+            eval: {
+              first: new Uint8Array([1,2,3,4]).buffer,
+            },
+          },
+        },
+      }});
+
+      assert_not_own_property(assertion.getClientExtensionResults().prf, 'results');
+    }, "navigator.credentials.get() with prf requested but no support in authenticator");
 });
 
 /* JSHINT */
diff --git a/third_party/blink/web_tests/external/wpt/webauthn/getcredential-prf.https.html b/third_party/blink/web_tests/external/wpt/webauthn/getcredential-prf.https.html
new file mode 100644
index 0000000..6f8670f6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webauthn/getcredential-prf.https.html
@@ -0,0 +1,157 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>navigator.credentials.get() prf extension tests with authenticator support</title>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src=helpers.js></script>
+<body></body>
+<script>
+standardSetup(async function(authenticator) {
+  "use strict";
+
+  const b64 = buf => btoa(String.fromCharCode.apply(null, new Uint8Array(buf)));
+  const b64url = buf => b64(buf).
+    replace(/\+/g, '-').
+    replace(/\//g, '_').
+    replace(/=+$/, '');
+
+  const credential = createCredential({
+    options: {
+      publicKey: {
+        extensions: {
+          prf: {},
+        },
+      },
+    },
+  });
+
+  const assert = (id, prfExt) =>
+    navigator.credentials.get({publicKey: {
+      challenge: new Uint8Array(),
+      allowCredentials: [{
+        id: id,
+        type: "public-key",
+      }],
+      extensions: {
+        prf: prfExt,
+      },
+    }});
+
+  promise_test(async t => {
+    const id = (await credential).rawId;
+    const assertion = await assert(id, {
+          eval: {
+            first: new Uint8Array([1,2,3,4]).buffer,
+          },
+    });
+    const results = assertion.getClientExtensionResults().prf.results;
+    assert_equals(results.first.byteLength, 32)
+    assert_not_own_property(results, 'second');
+  }, "navigator.credentials.get() with single evaluation point");
+
+  promise_test(async t => {
+    const id = (await credential).rawId;
+    const assertion = await assert(id, {
+          eval: {
+            first: new Uint8Array([1,2,3,4]).buffer,
+            second: new Uint8Array([1,2,3,4]).buffer,
+          },
+    });
+    const results = assertion.getClientExtensionResults().prf.results;
+    assert_equals(results.first.byteLength, 32)
+    assert_equals(results.second.byteLength, 32)
+    assert_equals(b64(results.first), b64(results.second));
+  }, "navigator.credentials.get() with two equal evaluation points");
+
+  promise_test(async t => {
+    const id = (await credential).rawId;
+    const assertion = await assert(id, {
+          eval: {
+            first: new Uint8Array([1,2,3,4]).buffer,
+            second: new Uint8Array([1,2,3,5]).buffer,
+          },
+    });
+    const results = assertion.getClientExtensionResults().prf.results;
+    assert_equals(results.first.byteLength, 32)
+    assert_equals(results.second.byteLength, 32)
+    assert_not_equals(b64(results.first), b64(results.second));
+  }, "navigator.credentials.get() with two distinct evaluation points");
+
+  promise_test(async t => {
+    const id = (await credential).rawId;
+    const byCred = {};
+    byCred[b64url(id)] = {
+      first: new Uint8Array([1,2,3,4]).buffer,
+    };
+    const assertion = await assert(id, {
+          evalByCredential: byCred,
+    });
+    const results = assertion.getClientExtensionResults().prf.results;
+    assert_equals(results.first.byteLength, 32)
+    assert_not_own_property(results, 'second');
+  }, "navigator.credentials.get() using credential ID with one evaluation point");
+
+  promise_test(async t => {
+    const id = (await credential).rawId;
+    const byCred = {};
+    byCred[b64url(id)] = {
+      first: new Uint8Array([1,2,3,4]).buffer,
+      second: new Uint8Array([1,2,3,4]).buffer,
+    };
+    const assertion = await assert(id, {
+          evalByCredential: byCred,
+    });
+    const results = assertion.getClientExtensionResults().prf.results;
+    assert_equals(results.first.byteLength, 32)
+    assert_equals(results.second.byteLength, 32)
+    assert_equals(b64(results.first), b64(results.second));
+  }, "navigator.credentials.get() using credential ID with two evaluation points");
+
+  promise_test(async t => {
+    const id = (await credential).rawId;
+    const byCred = {};
+    byCred["Zm9v"] = {
+      first: new Uint8Array([1,2,3,4]).buffer,
+    };
+    const assertion = await assert(id, {
+          evalByCredential: byCred,
+    });
+    assert_own_property(assertion.getClientExtensionResults(), 'prf');
+    assert_not_own_property(assertion.getClientExtensionResults().prf,
+                            'results');
+  }, "navigator.credentials.get() using wrong credential ID");
+
+  promise_test(async t => {
+    const id = (await credential).rawId;
+    const byCred = {};
+    byCred["Zm9v="] = {
+      first: new Uint8Array([1,2,3,4]).buffer,
+    };
+    return promise_rejects_dom(
+      t, "NotSupportedError", assert(id, {evalByCredential: byCred }));
+  }, "navigator.credentials.get() using invalid base64url credential ID");
+
+  promise_test(async t => {
+    const id = (await credential).rawId;
+    const byCred = {};
+    byCred["Zm9v"] = {
+      first: new Uint8Array([1,2,3,4]).buffer,
+    };
+    const promise = navigator.credentials.get({publicKey: {
+      challenge: new Uint8Array(),
+      extensions: {
+        prf: {evalByCredential: byCred },
+      },
+    }});
+    return promise_rejects_dom(t, "NotSupportedError", promise);
+  }, "navigator.credentials.get() with an empty allow list but also using evalByCredential");
+}, {
+  protocol: "ctap2_1",
+  extensions: ["prf"],
+  hasUserVerification: true,
+  isUserVerified: true,
+});
+</script>
diff --git a/third_party/blink/web_tests/fast/borders/border-mixed-alpha2-expected.png b/third_party/blink/web_tests/fast/borders/border-mixed-alpha2-expected.png
index a2e97d5..09d8818 100644
--- a/third_party/blink/web_tests/fast/borders/border-mixed-alpha2-expected.png
+++ b/third_party/blink/web_tests/fast/borders/border-mixed-alpha2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/create-image-bitmap-none-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/create-image-bitmap-none-expected.txt
new file mode 100644
index 0000000..61d3471
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/create-image-bitmap-none-expected.txt
@@ -0,0 +1,21 @@
+Verifies that ObsoleteCreateImageBitmapImageOrientationNone deprecation issue is created from page with {imageOrientation: "none"}.
+Inspector issue: {
+    issue : {
+        code : DeprecationIssue
+        details : {
+            deprecationIssueDetails : {
+                affectedFrame : {
+                    frameId : <string>
+                }
+                sourceCodeLocation : {
+                    columnNumber : 9
+                    lineNumber : 14
+                    scriptId : <string>
+                    url : http://127.0.0.1:8000/inspector-protocol/resources/create-image-bitmap-none.html
+                }
+                type : ObsoleteCreateImageBitmapImageOrientationNone
+            }
+        }
+    }
+}
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/create-image-bitmap-none.js b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/create-image-bitmap-none.js
new file mode 100644
index 0000000..1f56621
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/create-image-bitmap-none.js
@@ -0,0 +1,13 @@
+(async function (testRunner) {
+  const { session, dp } = await testRunner.startBlank(
+  'Verifies that ObsoleteCreateImageBitmapImageOrientationNone deprecation issue is created ' +
+  'from page with {imageOrientation: "none"}.');
+  await dp.Audits.enable();
+  const promise = dp.Audits.onceIssueAdded();
+
+  await session.navigate('../resources/create-image-bitmap-none.html');
+
+  const result = await promise;
+  testRunner.log(result.params, "Inspector issue: ");
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/create-image-bitmap-none.html b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/create-image-bitmap-none.html
new file mode 100644
index 0000000..50e41f5
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/create-image-bitmap-none.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<html>
+<head>
+<title>Webpage for testing Content-Security-Policy in PaymentRequest</title>
+<!-- Deny connections to all payment method identifiers. -->
+<meta http-equiv="Content-Security-Policy" content="connect-src 'none'">
+</head>
+<body>
+<script>
+
+async function runTest() {
+  const ctx_temp = document.createElement('canvas').getContext('2d');
+  ctx_temp.fillRect(0, 0, 100, 100);
+  const imageSource = ctx_temp.getImageData(0, 0, 100, 100);
+  await createImageBitmap(imageSource, 0, 0, 100, 100, { imageOrientation: 'none' });
+}
+
+runTest();
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
index 22c2ef4..13875dd 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png
index 07aaaf6..4c0fb3d 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-selected-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-selected-expected.png
index 9ca6c031..d2d5e6c 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-selected-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-selected-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-unselected-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-unselected-expected.png
index 8035f23..2e81ddd1 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-unselected-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-unselected-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/borders/border-mixed-alpha2-expected.png b/third_party/blink/web_tests/platform/mac/fast/borders/border-mixed-alpha2-expected.png
new file mode 100644
index 0000000..a2e97d5
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/borders/border-mixed-alpha2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
index 81c606d..b602db9 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png
index 4a787ed6..697b1046 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-selected-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-selected-expected.png
index 3b772ff..69c6045b 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-selected-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-selected-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-unselected-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-unselected-expected.png
index 5f68ee3..4f29a34a 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-unselected-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-unselected-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
index d34c7af..e3dc096a 100644
--- a/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png
index 8d0db00..90f77474 100644
--- a/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-focused-unselected-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-selected-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-selected-expected.png
index 20d40370..5f0f2eb 100644
--- a/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-selected-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-selected-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-unselected-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-unselected-expected.png
index 888f131a..17367b26 100644
--- a/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-unselected-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-hover-unselected-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/resources/testdriver-vendor.js b/third_party/blink/web_tests/resources/testdriver-vendor.js
index 6255a74..cf4307a 100644
--- a/third_party/blink/web_tests/resources/testdriver-vendor.js
+++ b/third_party/blink/web_tests/resources/testdriver-vendor.js
@@ -360,6 +360,7 @@
     mojoOptions.hasLargeBlob = options.extensions.indexOf("largeBlob") !== -1;
     mojoOptions.hasCredBlob = options.extensions.indexOf("credBlob") !== -1;
     mojoOptions.hasMinPinLength = options.extensions.indexOf("minPinLength") !== -1;
+    mojoOptions.hasPrf = options.extensions.indexOf('prf') !== -1;
     mojoOptions.isUserPresent = options.isUserConsenting;
 
     let authenticator = (await manager.createAuthenticator(mojoOptions)).authenticator;
diff --git a/third_party/eigen3/README.chromium b/third_party/eigen3/README.chromium
index f096bfc..2945e0d 100644
--- a/third_party/eigen3/README.chromium
+++ b/third_party/eigen3/README.chromium
@@ -1,8 +1,8 @@
 Name: Eigen
 Short Name: eigen3
 URL: http://eigen.tuxfamily.org/
-Version: 3564668908afc66351c1c3cc47dca2fcdb91dc12
-Date: 2023/01/09
+Version: 6156797016164b87b3e360e02d0e4107f7f66fbc
+Date: 2023/01/17
 License: MPL 2
 License File: LICENSE
 Security Critical: Yes
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index 89816ea..fc57cd2 100644
--- a/third_party/freetype/README.chromium
+++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@
 Name: FreeType
 URL: http://www.freetype.org/
-Version: VER-2-12-1-156-g6a179ff7d
-Revision: 6a179ff7d55714501c5efce85e2a47de6055a07a
+Version: VER-2-12-1-162-gf80be4e95
+Revision: f80be4e959a5d41688dd6e257497e2627ae2d967
 CPEPrefix: cpe:/a:freetype:freetype:2.12.1
 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent
          JPEG Group) licenses"
diff --git a/third_party/freetype/include/freetype-custom/freetype/config/ftoption.h b/third_party/freetype/include/freetype-custom/freetype/config/ftoption.h
index 32283a6..b209277 100644
--- a/third_party/freetype/include/freetype-custom/freetype/config/ftoption.h
+++ b/third_party/freetype/include/freetype-custom/freetype/config/ftoption.h
@@ -4,7 +4,7 @@
  *
  *   User-selectable configuration macros (specification only).
  *
- * Copyright (C) 1996-2022 by
+ * Copyright (C) 1996-2023 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/third_party/freetype/include/freetype-custom/freetype/config/public-macros.h b/third_party/freetype/include/freetype-custom/freetype/config/public-macros.h
index 0103a4ca..2d258c6 100644
--- a/third_party/freetype/include/freetype-custom/freetype/config/public-macros.h
+++ b/third_party/freetype/include/freetype-custom/freetype/config/public-macros.h
@@ -4,7 +4,7 @@
  *
  *   Define a set of compiler macros used in public FreeType headers.
  *
- * Copyright (C) 2020-2022 by
+ * Copyright (C) 2020-2023 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/third_party/material_web_components/tsconfig_base.json b/third_party/material_web_components/tsconfig_base.json
index bb6cebc..eb86752 100644
--- a/third_party/material_web_components/tsconfig_base.json
+++ b/third_party/material_web_components/tsconfig_base.json
@@ -11,6 +11,7 @@
     "noImplicitReturns": true,
     "noFallthroughCasesInSwitch": true,
     "experimentalDecorators": true,
+    "skipLibCheck": true,
     "strict": true,
     "noImplicitAny": false,
     "importHelpers": true,
diff --git a/third_party/metrics_proto/README.chromium b/third_party/metrics_proto/README.chromium
index 3343caab..c59d389 100644
--- a/third_party/metrics_proto/README.chromium
+++ b/third_party/metrics_proto/README.chromium
@@ -1,8 +1,8 @@
 Name: Metrics Protos
 Short Name: metrics_proto
 URL: This is the canonical public repository
-Version: 500333648
-Date: 2023/01/07 UTC
+Version: 502422900
+Date: 2023/01/16 UTC
 License: BSD
 Security Critical: Yes
 
diff --git a/third_party/metrics_proto/system_profile.proto b/third_party/metrics_proto/system_profile.proto
index 3960fd4fc..e58e1ff 100644
--- a/third_party/metrics_proto/system_profile.proto
+++ b/third_party/metrics_proto/system_profile.proto
@@ -182,7 +182,8 @@
     // used only on iOS. Chrome for iOS detects whether device contains a
     // DynamicLibraries/ directory. It's a necessary but insufficient indicator
     // of whether the operating system has been jailbroken.
-    optional bool is_jailbroken = 4;
+    // Deprecated 01/2023. This was never set.
+    optional bool DEPRECATED_is_jailbroken = 4 [deprecated = true];
 
     // The build number for the OS version. The same OS version may have a
     // different build number. The meaning of this field is OS-dependent.
@@ -1085,7 +1086,7 @@
 
   // Information about what Chrome components are registered and at which
   // version.
-  // Next Tag: 4
+  // Next Tag: 5
   message ChromeComponent {
     // Which component this information is for.
     optional ComponentId component_id = 1 [default = UNKNOWN];
@@ -1100,6 +1101,11 @@
     // was installed as the component. It is a stronger version number that can
     // vary across platform, architecture, or branches of an A/B component test.
     optional fixed32 omaha_fingerprint = 3;
+
+    // A hash of the cohort identifier of this component, excluding
+    // non-assignment information. The hash function is Chromium's
+    // PersistentHash.
+    optional fixed32 cohort_hash = 4;
   }
   repeated ChromeComponent chrome_component = 24;
 
diff --git a/third_party/metrics_proto/ukm/entry.proto b/third_party/metrics_proto/ukm/entry.proto
index b6b45576..d69491c 100644
--- a/third_party/metrics_proto/ukm/entry.proto
+++ b/third_party/metrics_proto/ukm/entry.proto
@@ -13,12 +13,12 @@
 message Entry {
   // Unique identifier for an Event. This is used to provide hierarchical
   // structure for Events.
-  optional int32 id = 1;
+  optional int32 DEPRECATED_id = 1 [deprecated = true];
 
   // Parent id, which is associated with an id for another Event. This is set
   // only if the Event has another Event which can be considered a parent.
   // This is to provide hierarchies for Events.
-  optional int32 parent_id = 2;
+  optional int32 DEPRECATED_parent_id = 2 [deprecated = true];
 
   // The id of the Source this Event is associated with.
   optional int64 source_id = 3;
diff --git a/third_party/nearby/README.chromium b/third_party/nearby/README.chromium
index 52100f6b..90713d1 100644
--- a/third_party/nearby/README.chromium
+++ b/third_party/nearby/README.chromium
@@ -1,7 +1,7 @@
 Name: Nearby Connections Library
 Short Name: Nearby
 URL: https://github.com/google/nearby
-Version: 589829f9470d656695938b725c53c4c29f754f86
+Version: ea3fa0e3924c9e4be23504cbde398cef305d3197
 License: Apache 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/third_party/node/node_modules.tar.gz.sha1 b/third_party/node/node_modules.tar.gz.sha1
index 3f871f9..694ca42 100644
--- a/third_party/node/node_modules.tar.gz.sha1
+++ b/third_party/node/node_modules.tar.gz.sha1
@@ -1 +1 @@
-32dc8abec1486818f6ef4afc4996abc002b5218e
+22ef661af0e85e393bdb632564e9d0583dd606a5
diff --git a/third_party/node/package-lock.json b/third_party/node/package-lock.json
index 4b858e6..4ac423d2 100644
--- a/third_party/node/package-lock.json
+++ b/third_party/node/package-lock.json
@@ -10,7 +10,6 @@
       "dependencies": {
         "@types/chai": "4.2.22",
         "@types/d3": "5.16.0",
-        "@types/dom-mediacapture-record": "1.0.11",
         "@types/dom-speech-recognition": "0.0.1",
         "@types/filesystem": "0.0.32",
         "@types/filewriter": "0.0.29",
@@ -20,7 +19,7 @@
         "@types/trusted-types": "1.0.6",
         "@types/w3c-css-typed-object-model-level-1": "20180410.0.4",
         "@types/w3c-image-capture": "1.0.4",
-        "@types/webrtc": "0.0.31",
+        "@types/webrtc": "0.0.33",
         "@types/wicg-file-system-access": "2020.09.05",
         "@typescript-eslint/eslint-plugin": "5.12.0",
         "@typescript-eslint/parser": "5.12.0",
@@ -31,7 +30,7 @@
         "rollup": "2.58.0",
         "svgo": "2.8.0",
         "terser": "5.3.3",
-        "typescript": "4.6.3"
+        "typescript": "4.9.4"
       }
     },
     "node_modules/@babel/code-frame": {
@@ -500,11 +499,6 @@
         "@types/d3-selection": "*"
       }
     },
-    "node_modules/@types/dom-mediacapture-record": {
-      "version": "1.0.11",
-      "resolved": "https://registry.npmjs.org/@types/dom-mediacapture-record/-/dom-mediacapture-record-1.0.11.tgz",
-      "integrity": "sha512-ODVOH95x08arZhbQOjH3no7Iye64akdO+55nM+IGtTzpu2ACKr9CQTrI//CCVieIjlI/eL+rK1hQjMycxIgylQ=="
-    },
     "node_modules/@types/dom-speech-recognition": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/@types/dom-speech-recognition/-/dom-speech-recognition-0.0.1.tgz",
@@ -567,9 +561,9 @@
       }
     },
     "node_modules/@types/webrtc": {
-      "version": "0.0.31",
-      "resolved": "https://registry.npmjs.org/@types/webrtc/-/webrtc-0.0.31.tgz",
-      "integrity": "sha512-GEoJIoM/ddxdaGnu0enJVDTdvwwr3/tPkpXz0LBTSi282gqxWDg1ffk4fzHU2dosNshp+Slq1kfGxpKs5083Nw=="
+      "version": "0.0.33",
+      "resolved": "https://registry.npmjs.org/@types/webrtc/-/webrtc-0.0.33.tgz",
+      "integrity": "sha512-xjN6BelzkY3lzXjIjXGqJVDS6XDleEsvp1bVIyNccXCcMoTH3wvUXFew4/qflwJdNqjmq98Zc5VcALV+XBKBvg=="
     },
     "node_modules/@types/wicg-file-system-access": {
       "version": "2020.9.5",
@@ -2492,9 +2486,9 @@
       }
     },
     "node_modules/typescript": {
-      "version": "4.6.3",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
-      "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==",
+      "version": "4.9.4",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
+      "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
       "bin": {
         "tsc": "bin/tsc",
         "tsserver": "bin/tsserver"
@@ -2982,11 +2976,6 @@
         "@types/d3-selection": "*"
       }
     },
-    "@types/dom-mediacapture-record": {
-      "version": "1.0.11",
-      "resolved": "https://registry.npmjs.org/@types/dom-mediacapture-record/-/dom-mediacapture-record-1.0.11.tgz",
-      "integrity": "sha512-ODVOH95x08arZhbQOjH3no7Iye64akdO+55nM+IGtTzpu2ACKr9CQTrI//CCVieIjlI/eL+rK1hQjMycxIgylQ=="
-    },
     "@types/dom-speech-recognition": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/@types/dom-speech-recognition/-/dom-speech-recognition-0.0.1.tgz",
@@ -3049,9 +3038,9 @@
       }
     },
     "@types/webrtc": {
-      "version": "0.0.31",
-      "resolved": "https://registry.npmjs.org/@types/webrtc/-/webrtc-0.0.31.tgz",
-      "integrity": "sha512-GEoJIoM/ddxdaGnu0enJVDTdvwwr3/tPkpXz0LBTSi282gqxWDg1ffk4fzHU2dosNshp+Slq1kfGxpKs5083Nw=="
+      "version": "0.0.33",
+      "resolved": "https://registry.npmjs.org/@types/webrtc/-/webrtc-0.0.33.tgz",
+      "integrity": "sha512-xjN6BelzkY3lzXjIjXGqJVDS6XDleEsvp1bVIyNccXCcMoTH3wvUXFew4/qflwJdNqjmq98Zc5VcALV+XBKBvg=="
     },
     "@types/wicg-file-system-access": {
       "version": "2020.9.5",
@@ -4408,9 +4397,9 @@
       "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="
     },
     "typescript": {
-      "version": "4.6.3",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
-      "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw=="
+      "version": "4.9.4",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
+      "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg=="
     },
     "uglify-js": {
       "version": "3.15.5",
diff --git a/third_party/node/package.json b/third_party/node/package.json
index 9841052..800e718e 100644
--- a/third_party/node/package.json
+++ b/third_party/node/package.json
@@ -5,7 +5,6 @@
   "dependencies": {
     "@types/chai": "4.2.22",
     "@types/d3": "5.16.0",
-    "@types/dom-mediacapture-record": "1.0.11",
     "@types/dom-speech-recognition": "0.0.1",
     "@types/filesystem": "0.0.32",
     "@types/filewriter": "0.0.29",
@@ -15,7 +14,7 @@
     "@types/trusted-types": "1.0.6",
     "@types/w3c-css-typed-object-model-level-1": "20180410.0.4",
     "@types/w3c-image-capture": "1.0.4",
-    "@types/webrtc": "0.0.31",
+    "@types/webrtc": "0.0.33",
     "@types/wicg-file-system-access": "2020.09.05",
     "@typescript-eslint/eslint-plugin": "5.12.0",
     "@typescript-eslint/parser": "5.12.0",
@@ -26,6 +25,6 @@
     "rollup": "2.58.0",
     "svgo": "2.8.0",
     "terser": "5.3.3",
-    "typescript": "4.6.3"
+    "typescript": "4.9.4"
   }
 }
diff --git a/third_party/tflite/BUILD.gn b/third_party/tflite/BUILD.gn
index 749ffa8..faf25f24 100644
--- a/third_party/tflite/BUILD.gn
+++ b/third_party/tflite/BUILD.gn
@@ -477,6 +477,8 @@
     "src/tensorflow/lite/profiling/root_profiler.h",
     "src/tensorflow/lite/profiling/telemetry/profiler.cc",
     "src/tensorflow/lite/profiling/telemetry/profiler.h",
+    "src/tensorflow/lite/profiling/telemetry/telemetry.cc",
+    "src/tensorflow/lite/profiling/telemetry/telemetry.h",
     "src/tensorflow/lite/profiling/time.cc",
     "src/tensorflow/lite/profiling/time.h",
     "src/tensorflow/lite/schema/schema_utils.cc",
diff --git a/third_party/tflite/README.chromium b/third_party/tflite/README.chromium
index d9a1d39..dd93c56 100644
--- a/third_party/tflite/README.chromium
+++ b/third_party/tflite/README.chromium
@@ -1,8 +1,8 @@
 Name: TensorFlow Lite
 Short Name: tflite
 URL: https://github.com/tensorflow/tensorflow
-Version: 74caf3d43b7036464e7d1fb972a8b021e6856d1f
-Date: 2023/01/09
+Version: e6ad9bf9bcd3f33783f4363984f4b24adfd8a469
+Date: 2023/01/17
 License: Apache 2.0
 License File: LICENSE
 Security Critical: Yes
diff --git a/tools/code_coverage/coverage.py b/tools/code_coverage/coverage.py
index 826496a..b1894a0 100755
--- a/tools/code_coverage/coverage.py
+++ b/tools/code_coverage/coverage.py
@@ -70,6 +70,7 @@
 import sys
 
 import argparse
+import glob
 import json
 import logging
 import multiprocessing
@@ -460,7 +461,17 @@
   """Split a command string into parts in a platform-specific way."""
   if coverage_utils.GetHostPlatform() == 'win':
     return command.split()
-  return shlex.split(command)
+  split_command = shlex.split(command)
+  # Python's subprocess does not do glob expansion, so we expand it out here.
+  new_command = []
+  for item in split_command:
+    if '*' in item:
+      files = glob.glob(item)
+      for file in files:
+        new_command.append(file)
+    else:
+      new_command.append(item)
+  return new_command
 
 
 def _ExecuteCommand(target, command, output_file_path):
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 1d9c899..6e99c37 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -3161,7 +3161,7 @@
     ],
 
     'msan_release_bot_blink_reclient': [
-      'msan', 'release_bot_blink_reclient',
+      'msan_focal', 'release_bot_blink_reclient',
     ],
 
     'msan_release_bot_reclient': [
diff --git a/tools/mb/mb_config_expectations/chromium.memory.json b/tools/mb/mb_config_expectations/chromium.memory.json
index 2f33792c..0d1affa 100644
--- a/tools/mb/mb_config_expectations/chromium.memory.json
+++ b/tools/mb/mb_config_expectations/chromium.memory.json
@@ -105,7 +105,7 @@
     "gn_args": {
       "dcheck_always_on": false,
       "ffmpeg_branding": "Chrome",
-      "instrumented_libraries_release": "xenial",
+      "instrumented_libraries_release": "focal",
       "is_component_build": false,
       "is_debug": false,
       "is_msan": true,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 3145032..a1257dec 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -41829,6 +41829,7 @@
   <int value="4443" label="PrivateNetworkAccessFetchedTopFrame"/>
   <int value="4444" label="DisableThirdPartyStoragePartitioning"/>
   <int value="4445" label="ServiceWorkerFetchHandlerUpdateAfterInitialization"/>
+  <int value="4446" label="ObsoleteCreateImageBitmapImageOrientationNone"/>
 </enum>
 
 <enum name="FeaturePolicyAllowlistType">
@@ -59955,6 +59956,7 @@
   <int value="-641777884" label="SharedHighlightingManager:enabled"/>
   <int value="-641719457" label="disable-compositor-touch-hit-testing"/>
   <int value="-641423897" label="CompositeAfterPaint:disabled"/>
+  <int value="-640915559" label="FastPairHandshakeRefactor:enabled"/>
   <int value="-640191786" label="DesktopPWAsWithoutExtensions:enabled"/>
   <int value="-639070391" label="FreezeUserAgent:disabled"/>
   <int value="-639026783" label="disable-gpu-appcontainer"/>
@@ -60254,6 +60256,7 @@
   <int value="-466665702" label="RevampedPasswordManagementBubble:disabled"/>
   <int value="-466164593"
       label="CacheControlNoStoreEnterBackForwardCache:disabled"/>
+  <int value="-465429170" label="BackGestureRefactorActivityAndroid:enabled"/>
   <int value="-465381408" label="Sharesheet:disabled"/>
   <int value="-462554210"
       label="OminboxUIExperimentUseGenericSearchEngineIcon:enabled"/>
@@ -60369,6 +60372,7 @@
   <int value="-395259448" label="VideoPlayerJsModules:disabled"/>
   <int value="-394734604" label="FillingPasswordsFromAnyOrigin:disabled"/>
   <int value="-392813122" label="LibinputHandleTouchpad"/>
+  <int value="-390984438" label="FastPairHandshakeRefactor:disabled"/>
   <int value="-390798267" label="DynamicColorButtonsAndroid:disabled"/>
   <int value="-390734327" label="WallpaperGooglePhotosIntegration:disabled"/>
   <int value="-390624541" label="RestrictedApiOrigins:disabled"/>
@@ -64034,6 +64038,7 @@
       label="OmniboxUIExperimentVerticalMarginLimitToNonTouchOnly:disabled"/>
   <int value="1758688616" label="OmniboxModernizeVisualUpdate:disabled"/>
   <int value="1759323272" label="DefaultCalculatorWebApp:disabled"/>
+  <int value="1760547768" label="BackGestureRefactorActivityAndroid:disabled"/>
   <int value="1760946944" label="MacViewsAutofillPopup:disabled"/>
   <int value="1761576233" label="OmniboxReportAssistedQueryStats:disabled"/>
   <int value="1761920078"
diff --git a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
index 4b77a11..1023e2d 100644
--- a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
+++ b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
@@ -1426,18 +1426,6 @@
   <affected-histogram name="CryptohomeClient"/>
 </histogram_suffixes>
 
-<histogram_suffixes name="CurrentTabState" separator="_">
-  <suffix name="Active"
-      label="For an active tab which is shown foreground in a browser window."/>
-  <suffix name="Detached"
-      label="For a tab that is being dragged by user to outside of the
-             browser window."/>
-  <suffix name="Inactive"
-      label="For tabs in background and not shown to user."/>
-  <suffix name="Initial" label="For a tab that is just being created."/>
-  <affected-histogram name="Tabs.StateTransfer.Target"/>
-</histogram_suffixes>
-
 <histogram_suffixes name="CustomTabOpenSource" separator=".">
   <suffix name="MediaLauncherActivity"
       label="CustomTab opened by MediaLauncherActivity."/>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml
index fdea114..3efaa74 100644
--- a/tools/metrics/histograms/metadata/others/histograms.xml
+++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -5388,7 +5388,7 @@
 <histogram name="Eche.AppStream.LaunchAttempt" enum="AppStreamLaunchEntryPoint"
     expires_after="2023-05-18">
   <owner>crisrael@google.com</owner>
-  <owner>jonmann@google.com</owner>
+  <owner>jonmann@chromium.org</owner>
   <owner>chromeos-cross-device-eng@google.com</owner>
   <summary>
     This metric logs where the Eche app was launched from. The metric is emmited
@@ -5399,7 +5399,7 @@
 <histogram name="Eche.CompleteAppList.Available.Latency" units="ms"
     expires_after="2023-05-18">
   <owner>crisrael@google.com</owner>
-  <owner>jonmann@google.com</owner>
+  <owner>jonmann@chromium.org</owner>
   <owner>chromeos-cross-device-eng@google.com</owner>
   <summary>
     This metric tracks the time it takes from the phone becoming connected to
@@ -5512,6 +5512,18 @@
   </summary>
 </histogram>
 
+<histogram name="Eche.UniqueAppsStreamed.PerDay" units="count"
+    expires_after="2023-05-18">
+  <owner>crisrael@google.com</owner>
+  <owner>jonmann@chromium.org</owner>
+  <owner>chromeos-cross-device-eng@google.com</owner>
+  <summary>
+    This metric tracks the number of unique apps the user attempts to launch an
+    app stream. Emitted when the app stream is launched and the app has not been
+    launched in the current session.
+  </summary>
+</histogram>
+
 <histogram name="EphemeralTab.BottomSheet.CloseReason"
     enum="BottomSheet.StateChangeReason" expires_after="M92">
   <obsolete>
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml
index c06f1be..ed88d3d0 100644
--- a/tools/metrics/histograms/metadata/page/histograms.xml
+++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -279,7 +279,7 @@
 </histogram>
 
 <histogram name="PageLoad.Clients.Ads.AllPages.PercentNetworkBytesAds"
-    units="%" expires_after="2022-10-09">
+    units="%" expires_after="2024-01-17">
   <owner>alexmt@chromium.org</owner>
   <owner>johnidel@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
index d609f87..9418cbd 100644
--- a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
+++ b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
@@ -617,7 +617,7 @@
 
 <histogram
     name="SafeBrowsing.EsbDisabled.TimesDisabledLast28Days.{EnabledDuration}"
-    units="times" expires_after="2023-02-28">
+    units="times" expires_after="2023-08-28">
   <owner>thefrog@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/subresource/histograms.xml b/tools/metrics/histograms/metadata/subresource/histograms.xml
index 6b937cb..331a51c 100644
--- a/tools/metrics/histograms/metadata/subresource/histograms.xml
+++ b/tools/metrics/histograms/metadata/subresource/histograms.xml
@@ -517,7 +517,7 @@
 
 <histogram
     name="SubresourceFilter.PageLoad.SubresourceEvaluation.TotalCPUDuration"
-    units="microseconds" expires_after="2023-01-12">
+    units="microseconds" expires_after="2024-01-17">
   <owner>alexmt@chromium.org</owner>
   <owner>chrome-ads-histograms@google.com</owner>
   <summary>
@@ -535,7 +535,7 @@
 
 <histogram
     name="SubresourceFilter.PageLoad.SubresourceEvaluation.TotalWallDuration"
-    units="microseconds" expires_after="2023-01-12">
+    units="microseconds" expires_after="2024-01-17">
   <owner>alexmt@chromium.org</owner>
   <owner>chrome-ads-histograms@google.com</owner>
   <summary>
@@ -613,7 +613,7 @@
 </histogram>
 
 <histogram name="SubresourceFilter.SubresourceLoad.Evaluation.WallDuration"
-    units="microseconds" expires_after="2023-01-12">
+    units="microseconds" expires_after="2024-01-17">
   <owner>alexmt@chromium.org</owner>
   <owner>chrome-ads-histograms@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml
index 67d3163..4683c7db 100644
--- a/tools/metrics/histograms/metadata/tab/histograms.xml
+++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -1866,18 +1866,6 @@
   </summary>
 </histogram>
 
-<histogram name="Tabs.StateTransfer.Target" enum="TabStripState"
-    expires_after="M85">
-  <owner>kouhei@chromium.org</owner>
-  <owner>tzik@chromium.org</owner>
-  <summary>
-    The state to which a tab transitioned. Recorded when a tab transitions from
-    the state in the histogram name to a new state.
-
-    kouhei@ and tzik@ will remove some variation of these once M46 hits stable.
-  </summary>
-</histogram>
-
 <histogram name="Tabs.Suggestions.NumSuggestionsChanged{TabSuggestionType}"
     units="count" expires_after="2023-10-16">
   <owner>yusufo@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 3d3ac48..1d45955e 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -6,15 +6,15 @@
         },
         "win": {
             "hash": "371bc9104cbabd002f15fd4eda416278636c7ae7",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/62fdec216f3598aaf050e546fcc5766014adcc64/trace_processor_shell.exe"
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/5d0bac17a2cb9779156eaa23f4b019c6bcc3d20c/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "6373f26144aad58f230d11d6a91efda5a09c9873",
             "full_remote_path": "perfetto-luci-artifacts/v31.0/linux-arm/trace_processor_shell"
         },
         "mac": {
-            "hash": "73cdd9df6eb717b71e4992101d0ad14d27a8d41c",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/62fdec216f3598aaf050e546fcc5766014adcc64/trace_processor_shell"
+            "hash": "259a2819e0d2457439874cb126d6ab23aec117c1",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/5d0bac17a2cb9779156eaa23f4b019c6bcc3d20c/trace_processor_shell"
         },
         "mac_arm64": {
             "hash": "5f47ee79e59d00bf3889d30ca52315522c158040",
@@ -22,7 +22,7 @@
         },
         "linux": {
             "hash": "da8b1f4b7d01bb8e5f06082c02b585f2460b147a",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/62fdec216f3598aaf050e546fcc5766014adcc64/trace_processor_shell"
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/5d0bac17a2cb9779156eaa23f4b019c6bcc3d20c/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/ui/aura/demo/demo_main.cc b/ui/aura/demo/demo_main.cc
index b8bea24..5161fbde5 100644
--- a/ui/aura/demo/demo_main.cc
+++ b/ui/aura/demo/demo_main.cc
@@ -169,7 +169,7 @@
   ui::OzonePlatform::InitializeForUI(params);
   ui::OzonePlatform::InitializeForGPU(params);
 #endif
-  gl::init::InitializeGLOneOff(/*system_device_id=*/0);
+  gl::init::InitializeGLOneOff(/*gpu_preference=*/gl::GpuPreference::kDefault);
 
 #if BUILDFLAG(IS_WIN)
   display::win::SetDefaultDeviceScaleFactor(1.0f);
diff --git a/ui/base/cursor/cursor_factory.cc b/ui/base/cursor/cursor_factory.cc
index 953eb7a..1b15e63e 100644
--- a/ui/base/cursor/cursor_factory.cc
+++ b/ui/base/cursor/cursor_factory.cc
@@ -13,6 +13,7 @@
 #include "base/observer_list.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "ui/base/cursor/cursor.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
 #include "ui/base/cursor/platform_cursor.h"
 
@@ -68,6 +69,11 @@
   return nullptr;
 }
 
+absl::optional<CursorData> CursorFactory::GetCursorData(
+    mojom::CursorType type) {
+  return absl::nullopt;
+}
+
 scoped_refptr<PlatformCursor> CursorFactory::CreateAnimatedCursor(
     mojom::CursorType type,
     const std::vector<SkBitmap>& bitmaps,
diff --git a/ui/base/cursor/cursor_factory.h b/ui/base/cursor/cursor_factory.h
index aff8a20..ffefd26 100644
--- a/ui/base/cursor/cursor_factory.h
+++ b/ui/base/cursor/cursor_factory.h
@@ -11,6 +11,7 @@
 #include "base/component_export.h"
 #include "base/observer_list.h"
 #include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-forward.h"
 
 class SkBitmap;
@@ -28,6 +29,7 @@
 
 namespace ui {
 class PlatformCursor;
+struct CursorData;
 
 class COMPONENT_EXPORT(UI_BASE_CURSOR) CursorFactoryObserver {
  public:
@@ -54,6 +56,11 @@
   virtual scoped_refptr<PlatformCursor> GetDefaultCursor(
       mojom::CursorType type);
 
+  // Return the {bitmaps, hotspot} for the default cursor of the specified
+  // `type`. If that cursor is not available or the extraction of the data
+  // fails, return `absl::nullopt`.
+  virtual absl::optional<CursorData> GetCursorData(mojom::CursorType type);
+
   // Return an image cursor for the specified `type` with a `bitmap` and
   // `hotspot`.
   virtual scoped_refptr<PlatformCursor> CreateImageCursor(
diff --git a/ui/base/win/win_cursor_factory.cc b/ui/base/win/win_cursor_factory.cc
index 05728b2..89fb08d 100644
--- a/ui/base/win/win_cursor_factory.cc
+++ b/ui/base/win/win_cursor_factory.cc
@@ -7,18 +7,25 @@
 #include <windows.h>
 
 #include <string>
+#include <utility>
 
+#include "base/check_op.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/notreached.h"
 #include "base/win/scoped_gdi_object.h"
 #include "base/win/windows_types.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/cursor/cursor.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
 #include "ui/base/cursor/platform_cursor.h"
 #include "ui/base/resource/resource_bundle_win.h"
+#include "ui/gfx/geometry/point.h"
 #include "ui/gfx/icon_util.h"
 #include "ui/resources/grit/ui_unscaled_resources.h"
 
 namespace ui {
+
 namespace {
 
 const wchar_t* GetCursorId(mojom::CursorType type) {
@@ -149,6 +156,26 @@
   return default_cursors_[type];
 }
 
+absl::optional<CursorData> WinCursorFactory::GetCursorData(
+    mojom::CursorType type) {
+  DCHECK_NE(type, mojom::CursorType::kNone);
+  DCHECK_NE(type, mojom::CursorType::kCustom);
+
+  auto cursor = GetDefaultCursor(type);
+  if (!cursor) {
+    return absl::nullopt;
+  }
+
+  HCURSOR hcursor = WinCursor::FromPlatformCursor(cursor)->hcursor();
+  SkBitmap bitmap = IconUtil::CreateSkBitmapFromHICON(hcursor);
+  if (bitmap.isNull()) {
+    return absl::nullopt;
+  }
+
+  return ui::CursorData({std::move(bitmap)},
+                        IconUtil::GetHotSpotFromHICON(hcursor));
+}
+
 scoped_refptr<PlatformCursor> WinCursorFactory::CreateImageCursor(
     mojom::CursorType type,
     const SkBitmap& bitmap,
diff --git a/ui/base/win/win_cursor_factory.h b/ui/base/win/win_cursor_factory.h
index 3acd15a10..8572517 100644
--- a/ui/base/win/win_cursor_factory.h
+++ b/ui/base/win/win_cursor_factory.h
@@ -31,6 +31,7 @@
   // CursorFactory:
   scoped_refptr<PlatformCursor> GetDefaultCursor(
       mojom::CursorType type) override;
+  absl::optional<CursorData> GetCursorData(mojom::CursorType) override;
   scoped_refptr<PlatformCursor> CreateImageCursor(
       mojom::CursorType type,
       const SkBitmap& bitmap,
diff --git a/ui/color/color_id.h b/ui/color/color_id.h
index 4910594..3a5c037c0 100644
--- a/ui/color/color_id.h
+++ b/ui/color/color_id.h
@@ -66,16 +66,27 @@
   E_CPONLY(kColorRefError99) \
   E_CPONLY(kColorRefError100) \
   E_CPONLY(kColorRefNeutral0) \
+  E_CPONLY(kColorRefNeutral4) \
+  E_CPONLY(kColorRefNeutral6) \
   E_CPONLY(kColorRefNeutral10) \
+  E_CPONLY(kColorRefNeutral12) \
+  E_CPONLY(kColorRefNeutral17) \
   E_CPONLY(kColorRefNeutral20) \
+  E_CPONLY(kColorRefNeutral22) \
+  E_CPONLY(kColorRefNeutral24) \
   E_CPONLY(kColorRefNeutral30) \
   E_CPONLY(kColorRefNeutral40) \
   E_CPONLY(kColorRefNeutral50) \
   E_CPONLY(kColorRefNeutral60) \
   E_CPONLY(kColorRefNeutral70) \
   E_CPONLY(kColorRefNeutral80) \
+  E_CPONLY(kColorRefNeutral87) \
   E_CPONLY(kColorRefNeutral90) \
+  E_CPONLY(kColorRefNeutral92) \
+  E_CPONLY(kColorRefNeutral94) \
   E_CPONLY(kColorRefNeutral95) \
+  E_CPONLY(kColorRefNeutral96) \
+  E_CPONLY(kColorRefNeutral98) \
   E_CPONLY(kColorRefNeutral99) \
   E_CPONLY(kColorRefNeutral100) \
   E_CPONLY(kColorRefNeutralVariant0) \
diff --git a/ui/color/ref_color_mixer.cc b/ui/color/ref_color_mixer.cc
index 88216e3..3aa68b62 100644
--- a/ui/color/ref_color_mixer.cc
+++ b/ui/color/ref_color_mixer.cc
@@ -85,16 +85,27 @@
   mixer[kColorRefError100] = {palette.error().get(100)};
 
   mixer[kColorRefNeutral0] = {palette.neutral().get(0)};
+  mixer[kColorRefNeutral4] = {palette.neutral().get(4)};
+  mixer[kColorRefNeutral6] = {palette.neutral().get(6)};
   mixer[kColorRefNeutral10] = {palette.neutral().get(10)};
+  mixer[kColorRefNeutral12] = {palette.neutral().get(12)};
+  mixer[kColorRefNeutral17] = {palette.neutral().get(17)};
   mixer[kColorRefNeutral20] = {palette.neutral().get(20)};
+  mixer[kColorRefNeutral22] = {palette.neutral().get(22)};
+  mixer[kColorRefNeutral24] = {palette.neutral().get(24)};
   mixer[kColorRefNeutral30] = {palette.neutral().get(30)};
   mixer[kColorRefNeutral40] = {palette.neutral().get(40)};
   mixer[kColorRefNeutral50] = {palette.neutral().get(50)};
   mixer[kColorRefNeutral60] = {palette.neutral().get(60)};
   mixer[kColorRefNeutral70] = {palette.neutral().get(70)};
   mixer[kColorRefNeutral80] = {palette.neutral().get(80)};
+  mixer[kColorRefNeutral87] = {palette.neutral().get(87)};
   mixer[kColorRefNeutral90] = {palette.neutral().get(90)};
+  mixer[kColorRefNeutral92] = {palette.neutral().get(92)};
+  mixer[kColorRefNeutral94] = {palette.neutral().get(94)};
   mixer[kColorRefNeutral95] = {palette.neutral().get(95)};
+  mixer[kColorRefNeutral96] = {palette.neutral().get(96)};
+  mixer[kColorRefNeutral98] = {palette.neutral().get(98)};
   mixer[kColorRefNeutral99] = {palette.neutral().get(99)};
   mixer[kColorRefNeutral100] = {palette.neutral().get(100)};
 
diff --git a/ui/file_manager/file_manager/foreground/elements/files_tooltip.js b/ui/file_manager/file_manager/foreground/elements/files_tooltip.js
index 13b00b5..35eb53fa 100644
--- a/ui/file_manager/file_manager/foreground/elements/files_tooltip.js
+++ b/ui/file_manager/file_manager/foreground/elements/files_tooltip.js
@@ -62,11 +62,6 @@
      * @private {number}
      */
     this.hideTooltipTimerId_ = 0;
-
-    /**
-     * Add <files-tooltip files-ng> for files-ng specific CSS styles.
-     */
-    this.toggleAttribute('files-ng', true);
   },
 
   /**
diff --git a/ui/gfx/canvas.cc b/ui/gfx/canvas.cc
index 57c53ca..70fbd82 100644
--- a/ui/gfx/canvas.cc
+++ b/ui/gfx/canvas.cc
@@ -300,7 +300,7 @@
 
 void Canvas::DrawImageInt(const ImageSkia& image, int x, int y, uint8_t a) {
   cc::PaintFlags flags;
-  flags.setAlpha(a);
+  flags.setAlphaf(a / 255.0f);
   DrawImageInt(image, x, y, flags);
 }
 
diff --git a/ui/gfx/nine_image_painter.cc b/ui/gfx/nine_image_painter.cc
index 50f354b..330bff9 100644
--- a/ui/gfx/nine_image_painter.cc
+++ b/ui/gfx/nine_image_painter.cc
@@ -156,7 +156,7 @@
   int i4h = std::max(height_in_pixels - i4y - std::min({i6h, i7h, i8h}), 0);
 
   cc::PaintFlags flags;
-  flags.setAlpha(alpha);
+  flags.setAlphaf(alpha / 255.0f);
 
   Fill(canvas, image_reps[4], i4x, i4y, i4w, i4h, flags);
   Fill(canvas, image_reps[0], 0, 0, i0w, i0h, flags);
diff --git a/ui/gfx/paint_vector_icon.cc b/ui/gfx/paint_vector_icon.cc
index 7ec13dbb..60de4ab 100644
--- a/ui/gfx/paint_vector_icon.cc
+++ b/ui/gfx/paint_vector_icon.cc
@@ -273,7 +273,7 @@
         break;
 
       case PATH_COLOR_ALPHA:
-        flags.setAlpha(SkScalarFloorToInt(arg(0)));
+        flags.setAlphaf(SkScalarFloorToInt(arg(0)) / 255.0f);
         break;
 
       case PATH_COLOR_ARGB:
diff --git a/ui/gl/dcomp_presenter_unittest.cc b/ui/gl/dcomp_presenter_unittest.cc
index cddc11e1..b5e16de7 100644
--- a/ui/gl/dcomp_presenter_unittest.cc
+++ b/ui/gl/dcomp_presenter_unittest.cc
@@ -130,7 +130,7 @@
 
     // Without this, the following check always fails.
     display_ = gl::init::InitializeGLNoExtensionsOneOff(
-        /*init_bindings=*/true, /*system_device_id=*/0);
+        /*init_bindings=*/true, /*gpu_preference=*/gl::GpuPreference::kDefault);
     if (!DirectCompositionSupported()) {
       LOG(WARNING) << "DirectComposition not supported, skipping test.";
       return;
diff --git a/ui/gl/delegated_ink_point_renderer_gpu_unittest.cc b/ui/gl/delegated_ink_point_renderer_gpu_unittest.cc
index abba8eb..88b43ca 100644
--- a/ui/gl/delegated_ink_point_renderer_gpu_unittest.cc
+++ b/ui/gl/delegated_ink_point_renderer_gpu_unittest.cc
@@ -99,8 +99,9 @@
  protected:
   void SetUp() override {
     // Without this, the following check always fails.
-    display_ = gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings=*/true,
-                                                        /*system_device_id=*/0);
+    display_ = gl::init::InitializeGLNoExtensionsOneOff(
+        /*init_bindings=*/true,
+        /*gpu_preference=*/gl::GpuPreference::kDefault);
     if (!gl::DirectCompositionSupported()) {
       LOG(WARNING)
           << "GL implementation not using DirectComposition, skipping test.";
diff --git a/ui/gl/direct_composition_surface_win_unittest.cc b/ui/gl/direct_composition_surface_win_unittest.cc
index 9110f8c..03d075b 100644
--- a/ui/gl/direct_composition_surface_win_unittest.cc
+++ b/ui/gl/direct_composition_surface_win_unittest.cc
@@ -129,7 +129,7 @@
 
     // Without this, the following check always fails.
     display_ = gl::init::InitializeGLNoExtensionsOneOff(
-        /*init_bindings=*/true, /*system_device_id=*/0);
+        /*init_bindings=*/true, /*gpu_preference=*/gl::GpuPreference::kDefault);
     if (!DirectCompositionSupported()) {
       LOG(WARNING) << "DirectComposition not supported, skipping test.";
       return;
diff --git a/ui/gl/egl_api_unittest.cc b/ui/gl/egl_api_unittest.cc
index 3446827..464b7a8 100644
--- a/ui/gl/egl_api_unittest.cc
+++ b/ui/gl/egl_api_unittest.cc
@@ -12,6 +12,7 @@
 #include "ui/gl/gl_egl_api_implementation.h"
 #include "ui/gl/gl_surface_egl.h"
 #include "ui/gl/gl_switches.h"
+#include "ui/gl/init/gl_display_initializer.h"
 #include "ui/gl/init/gl_factory.h"
 
 namespace gl {
@@ -57,7 +58,7 @@
         GLDisplayManagerEGL::GetInstance()->GetDisplay(GpuPreference::kDefault);
     // Clear the display so InitializeDisplay() will re-initialize it.
     display_->SetDisplay(EGL_NO_DISPLAY);
-    display_->InitializeDisplay(EGLDisplayPlatform(EGL_DEFAULT_DISPLAY));
+    init::InitializeDisplay(display_, EGLDisplayPlatform(EGL_DEFAULT_DISPLAY));
   }
 
   void SetFakeExtensionString(const char* fake_string,
diff --git a/ui/gl/gl_display.cc b/ui/gl/gl_display.cc
index c94fa97..03838757 100644
--- a/ui/gl/gl_display.cc
+++ b/ui/gl/gl_display.cc
@@ -392,9 +392,11 @@
     case ANGLE_D3D11on12:
       return ANGLEImplementation::kD3D11;
     case ANGLE_OPENGL:
+    case ANGLE_OPENGL_EGL:
     case ANGLE_OPENGL_NULL:
       return ANGLEImplementation::kOpenGL;
     case ANGLE_OPENGLES:
+    case ANGLE_OPENGLES_EGL:
     case ANGLE_OPENGLES_NULL:
       return ANGLEImplementation::kOpenGLES;
     case ANGLE_NULL:
@@ -456,13 +458,6 @@
   }
 }
 
-void AddInitDisplay(std::vector<DisplayType>* init_displays,
-                    DisplayType display_type) {
-  // Make sure to not add the same display type twice.
-  if (!base::Contains(*init_displays, display_type))
-    init_displays->push_back(display_type);
-}
-
 const char* GetDebugMessageTypeString(EGLint source) {
   switch (source) {
     case EGL_DEBUG_MSG_CRITICAL_KHR:
@@ -506,165 +501,8 @@
   }
 }
 
-void GetEGLInitDisplays(bool supports_angle_d3d,
-                        bool supports_angle_opengl,
-                        bool supports_angle_null,
-                        bool supports_angle_vulkan,
-                        bool supports_angle_swiftshader,
-                        bool supports_angle_egl,
-                        bool supports_angle_metal,
-                        const base::CommandLine* command_line,
-                        std::vector<DisplayType>* init_displays) {
-  // Check which experiment groups we're in. Check these early in the function
-  // so that finch assigns a group before the final decision to use the API is
-  // made. If we check too late, it will appear that some users are missing from
-  // the group if they are falling back to another path due to crashes or
-  // missing support.
-  bool default_angle_opengl =
-      base::FeatureList::IsEnabled(features::kDefaultANGLEOpenGL);
-  bool default_angle_metal =
-      base::FeatureList::IsEnabled(features::kDefaultANGLEMetal);
-  bool default_angle_vulkan = features::IsDefaultANGLEVulkan();
-
-  // If we're already requesting software GL, make sure we don't fallback to the
-  // GPU
-  bool forceSoftwareGL = IsSoftwareGLImplementation(GetGLImplementationParts());
-
-  std::string requested_renderer =
-      forceSoftwareGL ? kANGLEImplementationSwiftShaderName
-                      : command_line->GetSwitchValueASCII(switches::kUseANGLE);
-
-  bool use_angle_default =
-      !forceSoftwareGL &&
-      (!command_line->HasSwitch(switches::kUseANGLE) ||
-       requested_renderer == kANGLEImplementationDefaultName);
-
-  if (supports_angle_null &&
-      requested_renderer == kANGLEImplementationNullName) {
-    AddInitDisplay(init_displays, ANGLE_NULL);
-    return;
-  }
-
-  // If no display has been explicitly requested and the DefaultANGLEOpenGL
-  // experiment is enabled, try creating OpenGL displays first.
-  // TODO(oetuaho@nvidia.com): Only enable this path on specific GPUs with a
-  // blocklist entry. http://crbug.com/693090
-  if (supports_angle_opengl && use_angle_default && default_angle_opengl) {
-    AddInitDisplay(init_displays, ANGLE_OPENGL);
-    AddInitDisplay(init_displays, ANGLE_OPENGLES);
-  }
-
-  if (supports_angle_metal && use_angle_default && default_angle_metal) {
-    AddInitDisplay(init_displays, ANGLE_METAL);
-  }
-
-  if (supports_angle_vulkan && use_angle_default && default_angle_vulkan) {
-    AddInitDisplay(init_displays, ANGLE_VULKAN);
-  }
-
-  if (supports_angle_d3d) {
-    if (use_angle_default) {
-      // Default mode for ANGLE - try D3D11, else try D3D9
-      if (!command_line->HasSwitch(switches::kDisableD3D11)) {
-        AddInitDisplay(init_displays, ANGLE_D3D11);
-      }
-      AddInitDisplay(init_displays, ANGLE_D3D9);
-    } else {
-      if (requested_renderer == kANGLEImplementationD3D11Name) {
-        AddInitDisplay(init_displays, ANGLE_D3D11);
-      } else if (requested_renderer == kANGLEImplementationD3D9Name) {
-        AddInitDisplay(init_displays, ANGLE_D3D9);
-      } else if (requested_renderer == kANGLEImplementationD3D11NULLName) {
-        AddInitDisplay(init_displays, ANGLE_D3D11_NULL);
-      } else if (requested_renderer == kANGLEImplementationD3D11on12Name) {
-        AddInitDisplay(init_displays, ANGLE_D3D11on12);
-      }
-    }
-  }
-
-  if (supports_angle_opengl) {
-    if (use_angle_default && !supports_angle_d3d) {
-#if BUILDFLAG(IS_ANDROID)
-      // Don't request desktopGL on android
-      AddInitDisplay(init_displays, ANGLE_OPENGLES);
-#else
-      AddInitDisplay(init_displays, ANGLE_OPENGL);
-      AddInitDisplay(init_displays, ANGLE_OPENGLES);
-#endif  // BUILDFLAG(IS_ANDROID)
-    } else {
-      if (requested_renderer == kANGLEImplementationOpenGLName) {
-        AddInitDisplay(init_displays, ANGLE_OPENGL);
-      } else if (requested_renderer == kANGLEImplementationOpenGLESName) {
-        AddInitDisplay(init_displays, ANGLE_OPENGLES);
-      } else if (requested_renderer == kANGLEImplementationOpenGLNULLName) {
-        AddInitDisplay(init_displays, ANGLE_OPENGL_NULL);
-      } else if (requested_renderer == kANGLEImplementationOpenGLESNULLName) {
-        AddInitDisplay(init_displays, ANGLE_OPENGLES_NULL);
-      } else if (requested_renderer == kANGLEImplementationOpenGLEGLName &&
-                 supports_angle_egl) {
-        AddInitDisplay(init_displays, ANGLE_OPENGL_EGL);
-      } else if (requested_renderer == kANGLEImplementationOpenGLESEGLName &&
-                 supports_angle_egl) {
-        AddInitDisplay(init_displays, ANGLE_OPENGLES_EGL);
-      }
-    }
-  }
-
-  if (supports_angle_vulkan) {
-    if (use_angle_default) {
-      if (!supports_angle_d3d && !supports_angle_opengl) {
-        AddInitDisplay(init_displays, ANGLE_VULKAN);
-      }
-    } else if (requested_renderer == kANGLEImplementationVulkanName) {
-      AddInitDisplay(init_displays, ANGLE_VULKAN);
-    } else if (requested_renderer == kANGLEImplementationVulkanNULLName) {
-      AddInitDisplay(init_displays, ANGLE_VULKAN_NULL);
-    }
-  }
-
-  if (supports_angle_swiftshader) {
-    if (requested_renderer == kANGLEImplementationSwiftShaderName ||
-        requested_renderer == kANGLEImplementationSwiftShaderForWebGLName) {
-      AddInitDisplay(init_displays, ANGLE_SWIFTSHADER);
-    }
-  }
-
-  if (supports_angle_metal) {
-    if (use_angle_default) {
-      if (!supports_angle_opengl) {
-        AddInitDisplay(init_displays, ANGLE_METAL);
-      }
-    } else if (requested_renderer == kANGLEImplementationMetalName) {
-      AddInitDisplay(init_displays, ANGLE_METAL);
-    } else if (requested_renderer == kANGLEImplementationMetalNULLName) {
-      AddInitDisplay(init_displays, ANGLE_METAL_NULL);
-    }
-  }
-
-  // If no displays are available due to missing angle extensions or invalid
-  // flags, request the default display.
-  if (init_displays->empty()) {
-    init_displays->push_back(DEFAULT);
-  }
-}
-
 }  // namespace
 
-void GetEGLInitDisplaysForTesting(bool supports_angle_d3d,
-                                  bool supports_angle_opengl,
-                                  bool supports_angle_null,
-                                  bool supports_angle_vulkan,
-                                  bool supports_angle_swiftshader,
-                                  bool supports_angle_egl,
-                                  bool supports_angle_metal,
-                                  const base::CommandLine* command_line,
-                                  std::vector<DisplayType>* init_displays) {
-  GetEGLInitDisplays(supports_angle_d3d, supports_angle_opengl,
-                     supports_angle_null, supports_angle_vulkan,
-                     supports_angle_swiftshader, supports_angle_egl,
-                     supports_angle_metal, command_line, init_displays);
-}
-
 GLDisplay::GLDisplay(uint64_t system_device_id, DisplayPlatform type)
     : system_device_id_(system_device_id), type_(type) {}
 
@@ -780,12 +618,15 @@
   return this->ext->b_EGL_ANGLE_external_context_and_surface;
 }
 
-bool GLDisplayEGL::Initialize(EGLDisplayPlatform native_display) {
+bool GLDisplayEGL::Initialize(bool supports_angle,
+                              std::vector<DisplayType> init_displays,
+                              EGLDisplayPlatform native_display) {
   if (display_ != EGL_NO_DISPLAY)
     return true;
 
-  if (!InitializeDisplay(native_display))
+  if (!InitializeDisplay(supports_angle, init_displays, native_display)) {
     return false;
+  }
   InitializeCommon();
 
   if (ext->b_EGL_ANGLE_power_preference) {
@@ -812,7 +653,9 @@
 
 // InitializeDisplay is necessary because the static binding code
 // needs a full Display init before it can query the Display extensions.
-bool GLDisplayEGL::InitializeDisplay(EGLDisplayPlatform native_display) {
+bool GLDisplayEGL::InitializeDisplay(bool supports_angle,
+                                     std::vector<DisplayType> init_displays,
+                                     EGLDisplayPlatform native_display) {
   if (display_ != EGL_NO_DISPLAY)
     return true;
 
@@ -836,41 +679,7 @@
     eglDebugMessageControlKHR(&LogEGLDebugMessage, controls);
   }
 
-  bool supports_angle_d3d = false;
-  bool supports_angle_opengl = false;
-  bool supports_angle_null = false;
-  bool supports_angle_vulkan = false;
-  bool supports_angle_swiftshader = false;
-  bool supports_angle_egl = false;
-  bool supports_angle_metal = false;
-  // Check for availability of ANGLE extensions.
-  if (g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle) {
-    supports_angle_d3d = g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle_d3d;
-    supports_angle_opengl =
-        g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle_opengl;
-    supports_angle_null =
-        g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle_null;
-    supports_angle_vulkan =
-        g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle_vulkan;
-    supports_angle_swiftshader =
-        g_driver_egl.client_ext
-            .b_EGL_ANGLE_platform_angle_device_type_swiftshader;
-    supports_angle_egl = g_driver_egl.client_ext
-                             .b_EGL_ANGLE_platform_angle_device_type_egl_angle;
-    supports_angle_metal =
-        g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle_metal;
-  }
-
-  bool supports_angle = supports_angle_d3d || supports_angle_opengl ||
-                        supports_angle_null || supports_angle_vulkan ||
-                        supports_angle_swiftshader || supports_angle_metal;
-
-  std::vector<DisplayType> init_displays;
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  GetEGLInitDisplays(supports_angle_d3d, supports_angle_opengl,
-                     supports_angle_null, supports_angle_vulkan,
-                     supports_angle_swiftshader, supports_angle_egl,
-                     supports_angle_metal, command_line, &init_displays);
 
   std::vector<std::string> enabled_angle_features =
       GetStringVectorFromCommandLine(command_line,
diff --git a/ui/gl/gl_display.h b/ui/gl/gl_display.h
index 42dd29c..ae04b6a1 100644
--- a/ui/gl/gl_display.h
+++ b/ui/gl/gl_display.h
@@ -22,10 +22,6 @@
 #include "components/metal_util/types.h"
 #endif
 
-namespace base {
-class CommandLine;
-}  // namespace base
-
 namespace gl {
 struct DisplayExtensionsEGL;
 template <typename GLDisplayPlatform>
@@ -80,17 +76,6 @@
   EGL = 1,
 };
 
-GL_EXPORT void GetEGLInitDisplaysForTesting(
-    bool supports_angle_d3d,
-    bool supports_angle_opengl,
-    bool supports_angle_null,
-    bool supports_angle_vulkan,
-    bool supports_angle_swiftshader,
-    bool supports_angle_egl,
-    bool supports_angle_metal,
-    const base::CommandLine* command_line,
-    std::vector<DisplayType>* init_displays);
-
 class GL_EXPORT GLDisplay {
  public:
   GLDisplay(const GLDisplay&) = delete;
@@ -137,7 +122,9 @@
   bool IsAndroidNativeFenceSyncSupported();
   bool IsANGLEExternalContextAndSurfaceSupported();
 
-  bool Initialize(EGLDisplayPlatform native_display);
+  bool Initialize(bool supports_angle,
+                  std::vector<DisplayType> init_displays,
+                  EGLDisplayPlatform native_display);
   void InitializeForTesting();
   bool InitializeExtensionSettings();
 
@@ -173,7 +160,9 @@
 
   explicit GLDisplayEGL(uint64_t system_device_id);
 
-  bool InitializeDisplay(EGLDisplayPlatform native_display);
+  bool InitializeDisplay(bool supports_angle,
+                         std::vector<DisplayType> init_displays,
+                         EGLDisplayPlatform native_display);
   void InitializeCommon();
 
   EGLDisplay display_ = EGL_NO_DISPLAY;
diff --git a/ui/gl/gl_display_manager.h b/ui/gl/gl_display_manager.h
index 5d066a55..cd38dc3 100644
--- a/ui/gl/gl_display_manager.h
+++ b/ui/gl/gl_display_manager.h
@@ -16,6 +16,7 @@
 #include "base/thread_annotations.h"
 #include "ui/gl/gl_display.h"
 #include "ui/gl/gl_export.h"
+#include "ui/gl/gl_switches.h"
 #include "ui/gl/gpu_preference.h"
 
 namespace gl {
@@ -42,9 +43,80 @@
     gpu_preference_map_[preference] = system_device_id;
   }
 
+  // This should be called if display creation is failed on the specified
+  // system_device_id display. This way, we will no longer attempt to use this
+  // display, but instead use the default display.
+  void RemoveGpuPreference(GpuPreference preference) {
+    uint64_t system_device_id = GetSystemDeviceId(preference);
+    for (auto iter = gpu_preference_map_.begin();
+         iter != gpu_preference_map_.end();
+         /* no increment */) {
+      if (iter->second == system_device_id) {
+        gpu_preference_map_.erase(iter++);
+      } else {
+        iter++;
+      }
+    }
+
+    auto iter = gpu_preference_map_.find(GpuPreference::kDefault);
+    if (iter == gpu_preference_map_.end()) {
+      gpu_preference_map_[GpuPreference::kDefault] =
+          gpu_preference_map_.begin()->second;
+    }
+
+    base::AutoLock auto_lock(lock_);
+    for (size_t i = 0; i < displays_.size(); i++) {
+      if (displays_[i]->system_device_id() == system_device_id) {
+        displays_.erase(displays_.begin() + i);
+        i--;
+      }
+    }
+  }
+
+  uint64_t GetSystemDeviceId(GpuPreference preference) {
+    uint64_t system_device_id = 0;
+    auto iter = gpu_preference_map_.find(preference);
+    if (!SupportsEGLDualGPURendering() ||
+        (iter == gpu_preference_map_.end() &&
+         preference != GpuPreference::kDefault)) {
+      // If kLowPower or kHighPerformance is queried but they are not set in the
+      // map, default to the kDefault GPU.
+      // Also do this if EGLDualGPURendering is not enabled.
+      iter = gpu_preference_map_.find(GpuPreference::kDefault);
+    }
+    if (iter != gpu_preference_map_.end()) {
+      system_device_id = iter->second;
+    }
+    return system_device_id;
+  }
+
   GLDisplayManager(const GLDisplayManager&) = delete;
   GLDisplayManager& operator=(const GLDisplayManager&) = delete;
 
+  GLDisplayPlatform* GetDisplay(GpuPreference preference) {
+    return GetDisplay(GetSystemDeviceId(preference));
+  }
+
+  bool IsEmpty() {
+    base::AutoLock auto_lock(lock_);
+    return displays_.empty();
+  }
+
+  void OverrideEGLDualGPURenderingSupportForTests(bool value) {
+    override_egl_dual_gpu_rendering_support_for_tests_ = value;
+  }
+
+ private:
+  friend class base::NoDestructor<GLDisplayManager<GLDisplayPlatform>>;
+#if defined(USE_EGL)
+  friend class GLDisplayManagerEGLTest;
+#endif
+
+  // Don't delete these functions for testing purpose.
+  // Each test constructs a scoped GLDisplayManager directly.
+  GLDisplayManager() = default;
+  virtual ~GLDisplayManager() = default;
+
   GLDisplayPlatform* GetDisplay(uint64_t system_device_id) {
     base::AutoLock auto_lock(lock_);
     for (const auto& display : displays_) {
@@ -59,40 +131,17 @@
     return displays_.back().get();
   }
 
-  GLDisplayPlatform* GetDisplay(GpuPreference preference) {
-    uint64_t system_device_id = 0;
-    auto iter = gpu_preference_map_.find(preference);
-    if (iter == gpu_preference_map_.end() &&
-        preference != GpuPreference::kDefault) {
-      // If kLowPower or kHighPerformance is queried but they are not set in the
-      // map, default to the kDefault GPU.
-      iter = gpu_preference_map_.find(GpuPreference::kDefault);
-    }
-    if (iter != gpu_preference_map_.end())
-      system_device_id = iter->second;
-    return GetDisplay(system_device_id);
+  bool SupportsEGLDualGPURendering() {
+    return features::SupportsEGLDualGPURendering() ||
+           override_egl_dual_gpu_rendering_support_for_tests_;
   }
 
-  bool IsEmpty() {
-    base::AutoLock auto_lock(lock_);
-    return displays_.empty();
-  }
-
- private:
-  friend class base::NoDestructor<GLDisplayManager<GLDisplayPlatform>>;
-#if defined(USE_EGL)
-  friend class GLDisplayManagerEGLTest;
-#endif
-
-  // Don't delete these functions for testing purpose.
-  // Each test constructs a scoped GLDisplayManager directly.
-  GLDisplayManager() = default;
-  virtual ~GLDisplayManager() = default;
-
   mutable base::Lock lock_;
   std::vector<std::unique_ptr<GLDisplayPlatform>> displays_ GUARDED_BY(lock_);
 
   std::map<GpuPreference, uint64_t> gpu_preference_map_;
+
+  bool override_egl_dual_gpu_rendering_support_for_tests_ = false;
 };
 
 #if defined(USE_EGL)
diff --git a/ui/gl/gl_display_manager_unittest.cc b/ui/gl/gl_display_manager_unittest.cc
index 26bedca..b6744a4 100644
--- a/ui/gl/gl_display_manager_unittest.cc
+++ b/ui/gl/gl_display_manager_unittest.cc
@@ -45,10 +45,6 @@
   GLDisplayEGL* display_2 = manager->GetDisplay(GpuPreference::kDefault);
   EXPECT_EQ(display, display_2);
 
-  // Query with the system device id.
-  display_2 = manager->GetDisplay(kSingleGpu);
-  EXPECT_EQ(display, display_2);
-
   // Query the low power display. It should be the same as the default.
   GLDisplayEGL* display_low_power =
       manager->GetDisplay(GpuPreference::kLowPower);
@@ -67,6 +63,7 @@
 
   // Set up.
   ScopedGLDisplayManagerEGL manager;
+  manager->OverrideEGLDualGPURenderingSupportForTests(true);
   manager->SetGpuPreference(GpuPreference::kDefault, kDefaultGpu);
   manager->SetGpuPreference(GpuPreference::kLowPower, kIntegratedGpu);
   manager->SetGpuPreference(GpuPreference::kHighPerformance, kDiscreteGpu);
@@ -82,9 +79,38 @@
       manager->GetDisplay(GpuPreference::kLowPower);
   EXPECT_EQ(display_low_power, display_low_power_2);
 
-  // Query with the system device id.
-  display_low_power_2 = manager->GetDisplay(kIntegratedGpu);
-  EXPECT_EQ(display_low_power, display_low_power_2);
+  // Query the high performance display.
+  GLDisplayEGL* display_high_performance =
+      manager->GetDisplay(GpuPreference::kHighPerformance);
+  EXPECT_NE(nullptr, display_high_performance);
+  EXPECT_EQ(kDiscreteGpu, display_high_performance->system_device_id());
+
+  // Query the default display.
+  // Due to the set up, it should be the same as the low power display.
+  GLDisplayEGL* display_default = manager->GetDisplay(GpuPreference::kDefault);
+  EXPECT_EQ(display_low_power, display_default);
+}
+
+TEST_F(GLDisplayManagerEGLTest, RemoveDefaultGPU) {
+  constexpr uint64_t kIntegratedGpu = 18;
+  constexpr uint64_t kDiscreteGpu = 76;
+  constexpr uint64_t kDefaultGpu = kIntegratedGpu;
+
+  // Set up.
+  ScopedGLDisplayManagerEGL manager;
+  manager->OverrideEGLDualGPURenderingSupportForTests(true);
+  manager->SetGpuPreference(GpuPreference::kDefault, kDefaultGpu);
+  manager->SetGpuPreference(GpuPreference::kLowPower, kIntegratedGpu);
+  manager->SetGpuPreference(GpuPreference::kHighPerformance, kDiscreteGpu);
+  // Remove the low power GPU, which should change the default to the high
+  // performance GPU.
+  manager->RemoveGpuPreference(GpuPreference::kLowPower);
+
+  // Query the low power display. Expect it to return the high performance GPU
+  GLDisplayEGL* display_low_power =
+      manager->GetDisplay(GpuPreference::kLowPower);
+  EXPECT_NE(nullptr, display_low_power);
+  EXPECT_EQ(kDiscreteGpu, display_low_power->system_device_id());
 
   // Query the high performance display.
   GLDisplayEGL* display_high_performance =
@@ -92,9 +118,38 @@
   EXPECT_NE(nullptr, display_high_performance);
   EXPECT_EQ(kDiscreteGpu, display_high_performance->system_device_id());
 
-  // Query with the system device id.
-  GLDisplayEGL* display_high_performance_2 = manager->GetDisplay(kDiscreteGpu);
-  EXPECT_EQ(display_high_performance, display_high_performance_2);
+  // Query the default display.
+  // Due to the set up, it should be the same as the high performance display.
+  GLDisplayEGL* display_default = manager->GetDisplay(GpuPreference::kDefault);
+  EXPECT_EQ(display_high_performance, display_default);
+}
+
+TEST_F(GLDisplayManagerEGLTest, RemoveNonDefaultGPU) {
+  constexpr uint64_t kIntegratedGpu = 18;
+  constexpr uint64_t kDiscreteGpu = 76;
+  constexpr uint64_t kDefaultGpu = kIntegratedGpu;
+
+  // Set up.
+  ScopedGLDisplayManagerEGL manager;
+  manager->OverrideEGLDualGPURenderingSupportForTests(true);
+  manager->SetGpuPreference(GpuPreference::kDefault, kDefaultGpu);
+  manager->SetGpuPreference(GpuPreference::kLowPower, kIntegratedGpu);
+  manager->SetGpuPreference(GpuPreference::kHighPerformance, kDiscreteGpu);
+  // Remove the high performance GPU, which shouldn't affect the default or low
+  // power preference.
+  manager->RemoveGpuPreference(GpuPreference::kHighPerformance);
+
+  // Query the low power display.
+  GLDisplayEGL* display_low_power =
+      manager->GetDisplay(GpuPreference::kLowPower);
+  EXPECT_NE(nullptr, display_low_power);
+  EXPECT_EQ(kIntegratedGpu, display_low_power->system_device_id());
+
+  // Query the high performance display. Expect it to return the low power GPU.
+  GLDisplayEGL* display_high_performance =
+      manager->GetDisplay(GpuPreference::kHighPerformance);
+  EXPECT_NE(nullptr, display_high_performance);
+  EXPECT_EQ(kIntegratedGpu, display_high_performance->system_device_id());
 
   // Query the default display.
   // Due to the set up, it should be the same as the low power display.
diff --git a/ui/gl/gl_implementation.cc b/ui/gl/gl_implementation.cc
index 1dfa751..c45ea6e 100644
--- a/ui/gl/gl_implementation.cc
+++ b/ui/gl/gl_implementation.cc
@@ -39,13 +39,18 @@
 bool GLImplementationParts::IsAllowed(
     const std::vector<GLImplementationParts>& allowed_impls) const {
   // Given a vector of GLImplementationParts, this function checks if "this"
-  // GLImplementation is found in the list, with a special case where if the
-  // list contains ANGLE/kDefault, "this" may be any ANGLE implementation.
+  // GLImplementation is found in the list, with a special case where if "this"
+  // implementation is kDefault, and we see any ANGLE implementation in the
+  // list, then we allow "this" implementation, or vice versa, if "this" is
+  // any ANGLE implementation, and we see kDefault in the list, "this" is
+  // allowed.
   for (const GLImplementationParts& impl_iter : allowed_impls) {
     if (gl == kGLImplementationEGLANGLE &&
         impl_iter.gl == kGLImplementationEGLANGLE) {
       if (impl_iter.angle == ANGLEImplementation::kDefault) {
         return true;
+      } else if (angle == ANGLEImplementation::kDefault) {
+        return true;
       } else if (angle == impl_iter.angle) {
         return true;
       }
diff --git a/ui/gl/gl_utils.cc b/ui/gl/gl_utils.cc
index fa9e6b0..e03cf24c 100644
--- a/ui/gl/gl_utils.cc
+++ b/ui/gl/gl_utils.cc
@@ -198,22 +198,20 @@
                                                        system_device_id);
 }
 
+void RemoveGpuPreferenceEGL(GpuPreference preference) {
+  GLDisplayManagerEGL::GetInstance()->RemoveGpuPreference(preference);
+}
+
 GLDisplayEGL* GetDefaultDisplayEGL() {
   return GLDisplayManagerEGL::GetInstance()->GetDisplay(
       GpuPreference::kDefault);
 }
 
-GLDisplayEGL* GetDisplayEGL(uint64_t system_device_id) {
-  return GLDisplayManagerEGL::GetInstance()->GetDisplay(system_device_id);
+GLDisplayEGL* GetDisplayEGL(GpuPreference gpu_preference) {
+  return GLDisplayManagerEGL::GetInstance()->GetDisplay(gpu_preference);
 }
 #endif  // USE_EGL
 
-#if defined(USE_GLX)
-GLDisplayX11* GetDisplayX11(uint64_t system_device_id) {
-  return GLDisplayManagerX11::GetInstance()->GetDisplay(system_device_id);
-}
-#endif  // USE_GLX
-
 #if BUILDFLAG(IS_MAC)
 
 ScopedEnableTextureRectangleInShaderCompiler::
diff --git a/ui/gl/gl_utils.h b/ui/gl/gl_utils.h
index d2846ed..6e656c6 100644
--- a/ui/gl/gl_utils.h
+++ b/ui/gl/gl_utils.h
@@ -71,6 +71,9 @@
 GL_EXPORT void SetGpuPreferenceEGL(GpuPreference preference,
                                    uint64_t system_device_id);
 
+// Remove the entry at <preference> from GLDisplayManagerEGL.
+GL_EXPORT void RemoveGpuPreferenceEGL(GpuPreference preference);
+
 // Query the default GLDisplay. May return either a GLDisplayEGL or
 // GLDisplayX11.
 GL_EXPORT GLDisplay* GetDefaultDisplay();
@@ -82,15 +85,10 @@
 // Query the default GLDisplayEGL.
 GL_EXPORT GLDisplayEGL* GetDefaultDisplayEGL();
 
-// Query the GLDisplayEGL by |system_device_id|.
-GL_EXPORT GLDisplayEGL* GetDisplayEGL(uint64_t system_device_id);
+// Query the GLDisplayEGL by |gpu_preference|.
+GL_EXPORT GLDisplayEGL* GetDisplayEGL(GpuPreference gpu_preference);
 #endif  // USE_EGL
 
-#if defined(USE_GLX)
-// Query the GLDisplayX11 by |system_device_id|.
-GL_EXPORT GLDisplayX11* GetDisplayX11(uint64_t system_device_id);
-#endif  // USE_GLX
-
 // Temporarily allows compilation of shaders that use the
 // ARB_texture_rectangle/ANGLE_texture_rectangle extension. We don't want to
 // expose the extension to WebGL user shaders but we still need to use it for
diff --git a/ui/gl/init/BUILD.gn b/ui/gl/init/BUILD.gn
index c5f0f49..f6b4cf9 100644
--- a/ui/gl/init/BUILD.gn
+++ b/ui/gl/init/BUILD.gn
@@ -10,12 +10,14 @@
 
   public = [
     "create_gr_gl_interface.h",
+    "gl_display_initializer.h",
     "gl_factory.h",
   ]
 
   sources = [
     "create_gr_gl_interface.cc",
     "create_gr_gl_interface.h",
+    "gl_display_initializer.cc",
     "gl_factory.cc",
     "gl_factory.h",
     "gl_init_export.h",
@@ -68,6 +70,7 @@
       "gl_initializer_ozone.cc",
       "ozone_util.h",
     ]
+
     deps += [ "//ui/ozone" ]
   }
 }
diff --git a/ui/gl/init/gl_display_initializer.cc b/ui/gl/init/gl_display_initializer.cc
new file mode 100644
index 0000000..cbfa8ab
--- /dev/null
+++ b/ui/gl/init/gl_display_initializer.cc
@@ -0,0 +1,263 @@
+// 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 "ui/gl/init/gl_display_initializer.h"
+
+#include "base/command_line.h"
+#include "base/containers/contains.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/init/gl_factory.h"
+
+namespace gl::init {
+
+namespace {
+
+void AddInitDisplay(std::vector<DisplayType>* init_displays,
+                    DisplayType display_type) {
+  // Make sure to not add the same display type twice.
+  if (!base::Contains(*init_displays, display_type)) {
+    init_displays->push_back(display_type);
+  }
+}
+
+void GetEGLInitDisplays(bool supports_angle_d3d,
+                        bool supports_angle_opengl,
+                        bool supports_angle_null,
+                        bool supports_angle_vulkan,
+                        bool supports_angle_swiftshader,
+                        bool supports_angle_opengl_egl,
+                        bool supports_angle_metal,
+                        const base::CommandLine* command_line,
+                        std::vector<DisplayType>* init_displays) {
+  // Check which experiment groups we're in. Check these early in the function
+  // so that finch assigns a group before the final decision to use the API is
+  // made. If we check too late, it will appear that some users are missing from
+  // the group if they are falling back to another path due to crashes or
+  // missing support.
+  bool default_angle_opengl =
+      base::FeatureList::IsEnabled(features::kDefaultANGLEOpenGL);
+  bool default_angle_metal =
+      base::FeatureList::IsEnabled(features::kDefaultANGLEMetal);
+  bool default_angle_vulkan = features::IsDefaultANGLEVulkan();
+
+  // If we're already requesting software GL, make sure we don't fallback to the
+  // GPU
+  bool forceSoftwareGL = IsSoftwareGLImplementation(GetGLImplementationParts());
+
+  std::string requested_renderer =
+      forceSoftwareGL ? kANGLEImplementationSwiftShaderName
+                      : command_line->GetSwitchValueASCII(switches::kUseANGLE);
+
+  bool use_angle_default =
+      !forceSoftwareGL &&
+      (!command_line->HasSwitch(switches::kUseANGLE) ||
+       requested_renderer == kANGLEImplementationDefaultName);
+
+  // If we're already requesting an ANGLE implementation, use it instead of the
+  // default.
+  // if ((requested_renderer.empty() ||
+  //      requested_renderer == kANGLEImplementationDefaultName) &&
+  //     gl::GetGLImplementationParts().gl == gl::kGLImplementationEGLANGLE) {
+  //   use_angle_default = false;
+  //   requested_renderer =
+  //       GetGLImplementationANGLEName(gl::GetGLImplementationParts());
+  // }
+
+  if (supports_angle_null &&
+      requested_renderer == kANGLEImplementationNullName) {
+    AddInitDisplay(init_displays, ANGLE_NULL);
+    return;
+  }
+
+  // If no display has been explicitly requested and the DefaultANGLEOpenGL
+  // experiment is enabled, try creating OpenGL displays first.
+  // TODO(oetuaho@nvidia.com): Only enable this path on specific GPUs with a
+  // blocklist entry. http://crbug.com/693090
+  if (supports_angle_opengl && use_angle_default && default_angle_opengl) {
+    AddInitDisplay(init_displays, ANGLE_OPENGL);
+    AddInitDisplay(init_displays, ANGLE_OPENGLES);
+  }
+
+  if (supports_angle_metal && use_angle_default && default_angle_metal) {
+    AddInitDisplay(init_displays, ANGLE_METAL);
+  }
+
+  if (supports_angle_vulkan && use_angle_default && default_angle_vulkan) {
+    AddInitDisplay(init_displays, ANGLE_VULKAN);
+  }
+
+  if (supports_angle_d3d) {
+    if (use_angle_default) {
+      // Default mode for ANGLE - try D3D11, else try D3D9
+      if (!command_line->HasSwitch(switches::kDisableD3D11)) {
+        AddInitDisplay(init_displays, ANGLE_D3D11);
+      }
+      AddInitDisplay(init_displays, ANGLE_D3D9);
+    } else {
+      if (requested_renderer == kANGLEImplementationD3D11Name) {
+        AddInitDisplay(init_displays, ANGLE_D3D11);
+      } else if (requested_renderer == kANGLEImplementationD3D9Name) {
+        AddInitDisplay(init_displays, ANGLE_D3D9);
+      } else if (requested_renderer == kANGLEImplementationD3D11NULLName) {
+        AddInitDisplay(init_displays, ANGLE_D3D11_NULL);
+      } else if (requested_renderer == kANGLEImplementationD3D11on12Name) {
+        AddInitDisplay(init_displays, ANGLE_D3D11on12);
+      }
+    }
+  }
+
+  if (supports_angle_opengl) {
+    if (use_angle_default && !supports_angle_d3d) {
+#if BUILDFLAG(IS_ANDROID)
+      // Don't request desktopGL on android
+      AddInitDisplay(init_displays, ANGLE_OPENGLES);
+#else
+      AddInitDisplay(init_displays, ANGLE_OPENGL);
+      AddInitDisplay(init_displays, ANGLE_OPENGLES);
+#endif  // BUILDFLAG(IS_ANDROID)
+    } else {
+      if (requested_renderer == kANGLEImplementationOpenGLName) {
+        AddInitDisplay(init_displays, ANGLE_OPENGL);
+      } else if (requested_renderer == kANGLEImplementationOpenGLESName) {
+        AddInitDisplay(init_displays, ANGLE_OPENGLES);
+      } else if (requested_renderer == kANGLEImplementationOpenGLNULLName) {
+        AddInitDisplay(init_displays, ANGLE_OPENGL_NULL);
+      } else if (requested_renderer == kANGLEImplementationOpenGLESNULLName) {
+        AddInitDisplay(init_displays, ANGLE_OPENGLES_NULL);
+      } else if (requested_renderer == kANGLEImplementationOpenGLEGLName &&
+                 supports_angle_opengl_egl) {
+        AddInitDisplay(init_displays, ANGLE_OPENGL_EGL);
+      } else if (requested_renderer == kANGLEImplementationOpenGLESEGLName &&
+                 supports_angle_opengl_egl) {
+        AddInitDisplay(init_displays, ANGLE_OPENGLES_EGL);
+      }
+    }
+  }
+
+  if (supports_angle_vulkan) {
+    if (use_angle_default) {
+      if (!supports_angle_d3d && !supports_angle_opengl) {
+        AddInitDisplay(init_displays, ANGLE_VULKAN);
+      }
+    } else if (requested_renderer == kANGLEImplementationVulkanName) {
+      AddInitDisplay(init_displays, ANGLE_VULKAN);
+    } else if (requested_renderer == kANGLEImplementationVulkanNULLName) {
+      AddInitDisplay(init_displays, ANGLE_VULKAN_NULL);
+    }
+  }
+
+  if (supports_angle_swiftshader) {
+    if (requested_renderer == kANGLEImplementationSwiftShaderName ||
+        requested_renderer == kANGLEImplementationSwiftShaderForWebGLName) {
+      AddInitDisplay(init_displays, ANGLE_SWIFTSHADER);
+    }
+  }
+
+  if (supports_angle_metal) {
+    if (use_angle_default) {
+      if (!supports_angle_opengl) {
+        AddInitDisplay(init_displays, ANGLE_METAL);
+      }
+    } else if (requested_renderer == kANGLEImplementationMetalName) {
+      AddInitDisplay(init_displays, ANGLE_METAL);
+    } else if (requested_renderer == kANGLEImplementationMetalNULLName) {
+      AddInitDisplay(init_displays, ANGLE_METAL_NULL);
+    }
+  }
+
+  // If no displays are available due to missing angle extensions or invalid
+  // flags, request the default display.
+  if (init_displays->empty()) {
+    init_displays->push_back(DEFAULT);
+  }
+}
+
+}  // namespace
+
+void GetEGLInitDisplaysForTesting(bool supports_angle_d3d,  // IN-TEST
+                                  bool supports_angle_opengl,
+                                  bool supports_angle_null,
+                                  bool supports_angle_vulkan,
+                                  bool supports_angle_swiftshader,
+                                  bool supports_angle_opengl_egl,
+                                  bool supports_angle_metal,
+                                  const base::CommandLine* command_line,
+                                  std::vector<DisplayType>* init_displays) {
+  GetEGLInitDisplays(supports_angle_d3d, supports_angle_opengl,
+                     supports_angle_null, supports_angle_vulkan,
+                     supports_angle_swiftshader, supports_angle_opengl_egl,
+                     supports_angle_metal, command_line, init_displays);
+}
+
+void GetDisplayInitializationParams(bool* supports_angle,
+                                    std::vector<DisplayType>* init_displays) {
+  std::vector<GLImplementationParts> allowed_impls =
+      GetAllowedGLImplementations();
+
+  bool supports_angle_d3d = false;
+  bool supports_angle_opengl = false;
+  bool supports_angle_null = false;
+  bool supports_angle_vulkan = false;
+  bool supports_angle_swiftshader = false;
+  bool supports_angle_opengl_egl = false;
+  bool supports_angle_metal = false;
+  // Check for availability of ANGLE extensions.
+  if (g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle) {
+    supports_angle_d3d =
+        g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle_d3d &&
+        (gl::GLImplementationParts(gl::ANGLEImplementation::kD3D9)
+             .IsAllowed(allowed_impls) ||
+         gl::GLImplementationParts(gl::ANGLEImplementation::kD3D11)
+             .IsAllowed(allowed_impls));
+    supports_angle_opengl =
+        g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle_opengl &&
+        (gl::GLImplementationParts(gl::ANGLEImplementation::kOpenGL)
+             .IsAllowed(allowed_impls) ||
+         gl::GLImplementationParts(gl::ANGLEImplementation::kOpenGLES)
+             .IsAllowed(allowed_impls));
+    supports_angle_null =
+        g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle_null;
+    supports_angle_vulkan =
+        g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle_vulkan &&
+        gl::GLImplementationParts(gl::ANGLEImplementation::kVulkan)
+            .IsAllowed(allowed_impls);
+    supports_angle_swiftshader =
+        g_driver_egl.client_ext
+            .b_EGL_ANGLE_platform_angle_device_type_swiftshader &&
+        gl::GLImplementationParts(gl::ANGLEImplementation::kSwiftShader)
+            .IsAllowed(allowed_impls);
+    supports_angle_opengl_egl =
+        g_driver_egl.client_ext
+            .b_EGL_ANGLE_platform_angle_device_type_egl_angle;
+    supports_angle_metal =
+        g_driver_egl.client_ext.b_EGL_ANGLE_platform_angle_metal &&
+        gl::GLImplementationParts(gl::ANGLEImplementation::kMetal)
+            .IsAllowed(allowed_impls);
+  }
+
+  *supports_angle = supports_angle_d3d || supports_angle_opengl ||
+                    supports_angle_null || supports_angle_vulkan ||
+                    supports_angle_swiftshader || supports_angle_metal;
+
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  GetEGLInitDisplays(supports_angle_d3d, supports_angle_opengl,
+                     supports_angle_null, supports_angle_vulkan,
+                     supports_angle_swiftshader, supports_angle_opengl_egl,
+                     supports_angle_metal, command_line, init_displays);
+}
+
+bool InitializeDisplay(GLDisplayEGL* display,
+                       EGLDisplayPlatform native_display) {
+  if (display->GetDisplay() != nullptr) {
+    return true;
+  }
+
+  bool supports_angle = false;
+  std::vector<DisplayType> init_displays;
+  GetDisplayInitializationParams(&supports_angle, &init_displays);
+  return display->Initialize(supports_angle, init_displays, native_display);
+}
+
+}  // namespace gl::init
diff --git a/ui/gl/init/gl_display_initializer.h b/ui/gl/init/gl_display_initializer.h
new file mode 100644
index 0000000..e56c2ea
--- /dev/null
+++ b/ui/gl/init/gl_display_initializer.h
@@ -0,0 +1,39 @@
+// 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 UI_GL_INIT_GL_DISPLAY_INITIALIZER_H_
+#define UI_GL_INIT_GL_DISPLAY_INITIALIZER_H_
+
+#include <vector>
+
+#include "ui/gl/gl_display.h"
+#include "ui/gl/init/gl_init_export.h"
+
+namespace base {
+class CommandLine;
+}  // namespace base
+
+namespace gl::init {
+
+GL_INIT_EXPORT void GetEGLInitDisplaysForTesting(
+    bool supports_angle_d3d,
+    bool supports_angle_opengl,
+    bool supports_angle_null,
+    bool supports_angle_vulkan,
+    bool supports_angle_swiftshader,
+    bool supports_angle_opengl_egl,
+    bool supports_angle_metal,
+    const base::CommandLine* command_line,
+    std::vector<DisplayType>* init_displays);
+
+GL_INIT_EXPORT void GetDisplayInitializationParams(
+    bool* supports_angle,
+    std::vector<DisplayType>* init_displays);
+
+GL_INIT_EXPORT bool InitializeDisplay(GLDisplayEGL* display,
+                                      EGLDisplayPlatform native_display);
+
+}  // namespace gl::init
+
+#endif  // UI_GL_INIT_GL_DISPLAY_INITIALIZER_H_
diff --git a/ui/gl/init/gl_factory.cc b/ui/gl/init/gl_factory.cc
index 797ee45..7c875437 100644
--- a/ui/gl/init/gl_factory.cc
+++ b/ui/gl/init/gl_factory.cc
@@ -132,7 +132,7 @@
 }
 
 GLDisplay* InitializeGLOneOffPlatformHelper(bool init_extensions,
-                                            uint64_t system_device_id) {
+                                            gl::GpuPreference gpu_preference) {
   TRACE_EVENT1("gpu,startup", "gl::init::InitializeGLOneOffPlatformHelper",
                "init_extensions", init_extensions);
 
@@ -142,12 +142,12 @@
 
   return InitializeGLOneOffPlatformImplementation(
       fallback_to_software_gl, disable_gl_drawing, init_extensions,
-      system_device_id);
+      gpu_preference);
 }
 
 }  // namespace
 
-GLDisplay* InitializeGLOneOff(uint64_t system_device_id) {
+GLDisplay* InitializeGLOneOff(gl::GpuPreference gpu_preference) {
   TRACE_EVENT0("gpu,startup", "gl::init::InitializeOneOff");
 
   if (!InitializeStaticGLBindingsOneOff())
@@ -156,11 +156,11 @@
     return GetDefaultDisplayEGL();
   }
 
-  return InitializeGLOneOffPlatformHelper(true, system_device_id);
+  return InitializeGLOneOffPlatformHelper(true, gpu_preference);
 }
 
 GLDisplay* InitializeGLNoExtensionsOneOff(bool init_bindings,
-                                          uint64_t system_device_id) {
+                                          gl::GpuPreference gpu_preference) {
   TRACE_EVENT1("gpu,startup", "gl::init::InitializeNoExtensionsOneOff",
                "init_bindings", init_bindings);
   if (init_bindings) {
@@ -171,7 +171,7 @@
     }
   }
 
-  return InitializeGLOneOffPlatformHelper(false, system_device_id);
+  return InitializeGLOneOffPlatformHelper(false, gpu_preference);
 }
 
 bool InitializeStaticGLBindingsOneOff() {
@@ -212,16 +212,24 @@
     bool fallback_to_software_gl,
     bool disable_gl_drawing,
     bool init_extensions,
-    uint64_t system_device_id) {
+    gl::GpuPreference gpu_preference) {
   if (IsSoftwareGLImplementation(GetGLImplementationParts()))
     fallback_to_software_gl = false;
 
-  GLDisplay* display = InitializeGLOneOffPlatform(system_device_id);
+  GLDisplay* display = InitializeGLOneOffPlatform(gpu_preference);
   bool initialized = !!display;
+
+  if (!initialized) {
+    DVLOG(1) << "Initialization failed. Attempting to initialize default "
+                "GLDisplayEGL.";
+    RemoveGpuPreferenceEGL(gpu_preference);
+    display = InitializeGLOneOffPlatform(gl::GpuPreference::kDefault);
+    initialized = !!display;
+  }
   if (!initialized && fallback_to_software_gl) {
     ShutdownGL(nullptr, /*due_to_fallback=*/true);
     if (InitializeStaticGLBindings(GetSoftwareGLImplementation())) {
-      display = InitializeGLOneOffPlatform(system_device_id);
+      display = InitializeGLOneOffPlatform(gpu_preference);
       initialized = !!display;
     }
   }
@@ -240,6 +248,26 @@
   return display;
 }
 
+GLDisplay* GetOrInitializeGLOneOffPlatformImplementation(
+    bool fallback_to_software_gl,
+    bool disable_gl_drawing,
+    bool init_extensions,
+    gl::GpuPreference gpu_preference) {
+  gl::GLDisplay* display = gl::GetDisplay(gpu_preference);
+  DCHECK(display);
+
+  if (display->IsInitialized()) {
+    return display;
+  }
+
+  display = gl::init::InitializeGLOneOffPlatformImplementation(
+      /*fallback_to_software_gl=*/false, /*disable_gl_drawing=*/false,
+      /*init_extensions=*/true,
+      /*gpu_preference=*/gpu_preference);
+
+  return display;
+}
+
 void ShutdownGL(GLDisplay* display, bool due_to_fallback) {
   ShutdownGLPlatform(display);
 
diff --git a/ui/gl/init/gl_factory.h b/ui/gl/init/gl_factory.h
index 0685262..ecf40db 100644
--- a/ui/gl/init/gl_factory.h
+++ b/ui/gl/init/gl_factory.h
@@ -36,16 +36,16 @@
 GL_INIT_EXPORT std::vector<GLImplementationParts> GetAllowedGLImplementations();
 
 // Initializes GL bindings and extension settings.
-// |system_device_id| specifies which GPU to use on a multi-GPU system.
-// If its value is 0, use the default GPU of the system.
-GL_INIT_EXPORT GLDisplay* InitializeGLOneOff(uint64_t system_device_id);
+// |gpu_preference| specifies which GPU to use on a multi-GPU system.
+// If its value is kDefault, use the default GPU of the system.
+GL_INIT_EXPORT GLDisplay* InitializeGLOneOff(gl::GpuPreference gpu_preference);
 
 // Initializes GL bindings without initializing extension settings.
-// |system_device_id| specifies which GPU to use on a multi-GPU system.
-// If its value is 0, use the default GPU of the system.
+// |gpu_preference| specifies which GPU to use on a multi-GPU system.
+// If its value is kDefault, use the default GPU of the system.
 GL_INIT_EXPORT GLDisplay* InitializeGLNoExtensionsOneOff(
     bool init_bindings,
-    uint64_t system_device_id);
+    gl::GpuPreference gpu_preference);
 
 // Initializes GL bindings - load dlls and get proc address according to gl
 // command line switch.
@@ -65,13 +65,21 @@
 // Initializes GL platform using the provided parameters. This might be required
 // for use in tests. This should be called only after GL bindings are initilzed
 // successfully.
-// |system_device_id| specifies which GPU to use on a multi-GPU system.
-// If its value is 0, use the default GPU of the system.
+// |gpu_preference| specifies which GPU to use on a multi-GPU system.
+// If its value is kDefault, use the default GPU of the system.
 GL_INIT_EXPORT GLDisplay* InitializeGLOneOffPlatformImplementation(
     bool fallback_to_software_gl,
     bool disable_gl_drawing,
     bool init_extensions,
-    uint64_t system_device_id);
+    gl::GpuPreference gpu_preference);
+
+// Does the same as the above, but returns a cached display if one is already
+// initialized for the requested GPU.
+GL_INIT_EXPORT GLDisplay* GetOrInitializeGLOneOffPlatformImplementation(
+    bool fallback_to_software_gl,
+    bool disable_gl_drawing,
+    bool init_extensions,
+    gl::GpuPreference gpu_preference);
 
 // Clears GL bindings and resets GL implementation.
 // Calling this function a second time on the same |display| is a no-op.
diff --git a/ui/gl/init/gl_factory_android.cc b/ui/gl/init/gl_factory_android.cc
index 58ab5f5..4005aca 100644
--- a/ui/gl/init/gl_factory_android.cc
+++ b/ui/gl/init/gl_factory_android.cc
@@ -73,8 +73,8 @@
 
 std::vector<GLImplementationParts> GetAllowedGLImplementations() {
   std::vector<GLImplementationParts> impls;
-  impls.emplace_back(GLImplementationParts(kGLImplementationEGLGLES2));
-  impls.emplace_back(GLImplementationParts(kGLImplementationEGLANGLE));
+  impls.emplace_back(kGLImplementationEGLGLES2);
+  impls.emplace_back(kGLImplementationEGLANGLE);
   return impls;
 }
 
diff --git a/ui/gl/init/gl_factory_mac.cc b/ui/gl/init/gl_factory_mac.cc
index 30c0e68..a03416d 100644
--- a/ui/gl/init/gl_factory_mac.cc
+++ b/ui/gl/init/gl_factory_mac.cc
@@ -26,16 +26,9 @@
 
 std::vector<GLImplementationParts> GetAllowedGLImplementations() {
   std::vector<GLImplementationParts> impls;
-  impls.emplace_back(GLImplementationParts(gl::ANGLEImplementation::kDefault));
-  impls.emplace_back(GLImplementationParts(gl::ANGLEImplementation::kOpenGL));
-  impls.emplace_back(GLImplementationParts(gl::ANGLEImplementation::kMetal));
-  // crbug.com/1378476: LLVM 10 is used as the JIT compiler for SwiftShader,
-  // which doesn't properly support ARM. Disable Swiftshader on ARM CPUs until
-  // LLVM is upgraded.
-  if (base::mac::GetCPUType() != base::mac::CPUType::kArm) {
-    impls.emplace_back(
-        GLImplementationParts(gl::ANGLEImplementation::kSwiftShader));
-  }
+  impls.emplace_back(gl::ANGLEImplementation::kOpenGL);
+  impls.emplace_back(gl::ANGLEImplementation::kMetal);
+  impls.emplace_back(gl::ANGLEImplementation::kSwiftShader);
   return impls;
 }
 
diff --git a/ui/gl/init/gl_factory_win.cc b/ui/gl/init/gl_factory_win.cc
index cebb6f4..4a35cae 100644
--- a/ui/gl/init/gl_factory_win.cc
+++ b/ui/gl/init/gl_factory_win.cc
@@ -23,7 +23,7 @@
 
 std::vector<GLImplementationParts> GetAllowedGLImplementations() {
   std::vector<GLImplementationParts> impls;
-  impls.emplace_back(GLImplementationParts(kGLImplementationEGLANGLE));
+  impls.emplace_back(kGLImplementationEGLANGLE);
   return impls;
 }
 
diff --git a/ui/gl/init/gl_initializer.h b/ui/gl/init/gl_initializer.h
index 9f83859..5da42a7a 100644
--- a/ui/gl/init/gl_initializer.h
+++ b/ui/gl/init/gl_initializer.h
@@ -19,9 +19,9 @@
 // InitializeGLNoExtensionsOneOff(). For tests possibly
 // InitializeStaticGLBindingsImplementation() +
 // InitializeGLOneOffPlatformImplementation() instead.
-// |system_device_id| specifies which GPU to use on a multi-GPU system.
-// If its value is 0, use the default GPU of the system.
-GLDisplay* InitializeGLOneOffPlatform(uint64_t system_device_id);
+// |gpu_preference| specifies which GPU to use on a multi-GPU system.
+// If its value is kDefault, use the default GPU of the system.
+GLDisplay* InitializeGLOneOffPlatform(gl::GpuPreference gpu_preference);
 
 // Initializes a particular GL implementation.
 bool InitializeStaticGLBindings(GLImplementationParts implementation);
diff --git a/ui/gl/init/gl_initializer_android.cc b/ui/gl/init/gl_initializer_android.cc
index 72e3acd..140b7c92 100644
--- a/ui/gl/init/gl_initializer_android.cc
+++ b/ui/gl/init/gl_initializer_android.cc
@@ -14,6 +14,7 @@
 #include "ui/gl/gl_egl_api_implementation.h"
 #include "ui/gl/gl_gl_api_implementation.h"
 #include "ui/gl/gl_utils.h"
+#include "ui/gl/init/gl_display_initializer.h"
 
 namespace gl {
 namespace init {
@@ -76,12 +77,13 @@
 
 }  // namespace
 
-GLDisplay* InitializeGLOneOffPlatform(uint64_t system_device_id) {
-  GLDisplayEGL* display = GetDisplayEGL(system_device_id);
+GLDisplay* InitializeGLOneOffPlatform(gl::GpuPreference gpu_preference) {
+  GLDisplayEGL* display = GetDisplayEGL(gpu_preference);
   switch (GetGLImplementation()) {
     case kGLImplementationEGLGLES2:
     case kGLImplementationEGLANGLE:
-      if (!display->Initialize(EGLDisplayPlatform(EGL_DEFAULT_DISPLAY))) {
+      if (!InitializeDisplay(display,
+                             EGLDisplayPlatform(EGL_DEFAULT_DISPLAY))) {
         LOG(ERROR) << "GLDisplayEGL::Initialize failed.";
         return nullptr;
       }
diff --git a/ui/gl/init/gl_initializer_mac.cc b/ui/gl/init/gl_initializer_mac.cc
index 3185c622..e7bf812 100644
--- a/ui/gl/init/gl_initializer_mac.cc
+++ b/ui/gl/init/gl_initializer_mac.cc
@@ -24,6 +24,7 @@
 #include "ui/gl/gl_surface.h"
 #include "ui/gl/gl_utils.h"
 #include "ui/gl/gpu_switching_manager.h"
+#include "ui/gl/init/gl_display_initializer.h"
 
 #if defined(USE_EGL)
 #include "ui/gl/gl_egl_api_implementation.h"
@@ -165,8 +166,8 @@
 
 }  // namespace
 
-GLDisplay* InitializeGLOneOffPlatform(uint64_t system_device_id) {
-  GLDisplayEGL* display = GetDisplayEGL(system_device_id);
+GLDisplay* InitializeGLOneOffPlatform(gl::GpuPreference gpu_preference) {
+  GLDisplayEGL* display = GetDisplayEGL(gpu_preference);
   switch (GetGLImplementation()) {
     case kGLImplementationDesktopGL:
     case kGLImplementationDesktopGLCoreProfile:
@@ -177,7 +178,7 @@
 #if defined(USE_EGL)
     case kGLImplementationEGLGLES2:
     case kGLImplementationEGLANGLE:
-      if (!display->Initialize(EGLDisplayPlatform(0))) {
+      if (!InitializeDisplay(display, EGLDisplayPlatform(0))) {
         LOG(ERROR) << "GLDisplayEGL::Initialize failed.";
         return nullptr;
       }
diff --git a/ui/gl/init/gl_initializer_ozone.cc b/ui/gl/init/gl_initializer_ozone.cc
index 0d1c500..6a2df8f 100644
--- a/ui/gl/init/gl_initializer_ozone.cc
+++ b/ui/gl/init/gl_initializer_ozone.cc
@@ -11,22 +11,27 @@
 #include "ui/gl/gl_surface.h"
 #include "ui/gl/gl_utils.h"
 #include "ui/gl/init/gl_display_egl_util_ozone.h"
+#include "ui/gl/init/gl_display_initializer.h"
 #include "ui/gl/init/ozone_util.h"
 #include "ui/ozone/public/ozone_platform.h"
 
 namespace gl {
 namespace init {
 
-GLDisplay* InitializeGLOneOffPlatform(uint64_t system_device_id) {
+GLDisplay* InitializeGLOneOffPlatform(gl::GpuPreference gpu_preference) {
   if (HasGLOzone()) {
     gl::GLDisplayEglUtil::SetInstance(gl::GLDisplayEglUtilOzone::GetInstance());
-    return GetGLOzone()->InitializeGLOneOffPlatform(system_device_id);
+    bool supports_angle = false;
+    std::vector<gl::DisplayType> init_displays;
+    GetDisplayInitializationParams(&supports_angle, &init_displays);
+    return GetGLOzone()->InitializeGLOneOffPlatform(
+        supports_angle, init_displays, gpu_preference);
   }
 
   switch (GetGLImplementation()) {
     case kGLImplementationMockGL:
     case kGLImplementationStubGL:
-      return GetDisplayEGL(system_device_id);
+      return GetDisplayEGL(gpu_preference);
     default:
       NOTREACHED();
   }
diff --git a/ui/gl/init/gl_initializer_win.cc b/ui/gl/init/gl_initializer_win.cc
index 7b702e8..23378d8 100644
--- a/ui/gl/init/gl_initializer_win.cc
+++ b/ui/gl/init/gl_initializer_win.cc
@@ -22,6 +22,7 @@
 #include "ui/gl/gl_egl_api_implementation.h"
 #include "ui/gl/gl_gl_api_implementation.h"
 #include "ui/gl/gl_utils.h"
+#include "ui/gl/init/gl_display_initializer.h"
 #include "ui/gl/vsync_provider_win.h"
 
 namespace gl {
@@ -123,13 +124,13 @@
 
 }  // namespace
 
-GLDisplay* InitializeGLOneOffPlatform(uint64_t system_device_id) {
+GLDisplay* InitializeGLOneOffPlatform(gl::GpuPreference gpu_preference) {
   VSyncProviderWin::InitializeOneOff();
 
-  GLDisplayEGL* display = GetDisplayEGL(system_device_id);
+  GLDisplayEGL* display = GetDisplayEGL(gpu_preference);
   switch (GetGLImplementation()) {
     case kGLImplementationEGLANGLE:
-      if (!display->Initialize(EGLDisplayPlatform(GetDC(nullptr)))) {
+      if (!InitializeDisplay(display, EGLDisplayPlatform(GetDC(nullptr)))) {
         LOG(ERROR) << "GLDisplayEGL::Initialize failed.";
         return nullptr;
       }
diff --git a/ui/gl/test/egl_initialization_displays_unittest.cc b/ui/gl/test/egl_initialization_displays_unittest.cc
index f108d7f..05aa030 100644
--- a/ui/gl/test/egl_initialization_displays_unittest.cc
+++ b/ui/gl/test/egl_initialization_displays_unittest.cc
@@ -7,6 +7,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gl/gl_display.h"
 #include "ui/gl/gl_switches.h"
+#include "ui/gl/init/gl_display_initializer.h"
 
 namespace {
 
@@ -19,8 +20,8 @@
   // using --disable-d3d11 with the default --use-angle should never return
   // D3D11.
   command_line->AppendSwitch(switches::kDisableD3D11);
-  GetEGLInitDisplaysForTesting(true, true, true, true, true, true, true,
-                               command_line.get(), &displays);
+  gl::init::GetEGLInitDisplaysForTesting(true, true, true, true, true, true,
+                                         true, command_line.get(), &displays);
   EXPECT_FALSE(base::Contains(displays, gl::ANGLE_D3D11));
 
   // Specifically requesting D3D11 should always return it if the extension is
@@ -28,16 +29,16 @@
   command_line->AppendSwitchASCII(switches::kUseANGLE,
                                   gl::kANGLEImplementationD3D11Name);
   displays.clear();
-  GetEGLInitDisplaysForTesting(true, true, true, true, true, true, true,
-                               command_line.get(), &displays);
+  gl::init::GetEGLInitDisplaysForTesting(true, true, true, true, true, true,
+                                         true, command_line.get(), &displays);
   EXPECT_TRUE(base::Contains(displays, gl::ANGLE_D3D11));
   EXPECT_EQ(displays.size(), 1u);
 
   // Specifically requesting D3D11 should not return D3D11 if the extension is
   // not available
   displays.clear();
-  GetEGLInitDisplaysForTesting(false, true, true, true, true, true, true,
-                               command_line.get(), &displays);
+  gl::init::GetEGLInitDisplaysForTesting(false, true, true, true, true, true,
+                                         true, command_line.get(), &displays);
   EXPECT_FALSE(base::Contains(displays, gl::ANGLE_D3D11));
 }
 
@@ -47,16 +48,18 @@
 
   // Default without --use-angle flag
   std::vector<gl::DisplayType> default_no_flag_displays;
-  GetEGLInitDisplaysForTesting(true, true, true, true, true, true, true,
-                               command_line.get(), &default_no_flag_displays);
+  gl::init::GetEGLInitDisplaysForTesting(true, true, true, true, true, true,
+                                         true, command_line.get(),
+                                         &default_no_flag_displays);
   EXPECT_FALSE(default_no_flag_displays.empty());
 
   // Default with --use-angle flag
   command_line->AppendSwitchASCII(switches::kUseANGLE,
                                   gl::kANGLEImplementationDefaultName);
   std::vector<gl::DisplayType> default_with_flag_displays;
-  GetEGLInitDisplaysForTesting(true, true, true, true, true, true, true,
-                               command_line.get(), &default_with_flag_displays);
+  gl::init::GetEGLInitDisplaysForTesting(true, true, true, true, true, true,
+                                         true, command_line.get(),
+                                         &default_with_flag_displays);
   EXPECT_FALSE(default_with_flag_displays.empty());
 
   // Make sure the same results are returned
@@ -73,8 +76,8 @@
   command_line->AppendSwitchASCII(switches::kUseANGLE,
                                   gl::kANGLEImplementationOpenGLName);
   displays.clear();
-  GetEGLInitDisplaysForTesting(true, true, true, true, true, true, true,
-                               command_line.get(), &displays);
+  gl::init::GetEGLInitDisplaysForTesting(true, true, true, true, true, true,
+                                         true, command_line.get(), &displays);
   EXPECT_TRUE(base::Contains(displays, gl::ANGLE_OPENGL));
   EXPECT_EQ(displays.size(), 1u);
 
@@ -82,8 +85,8 @@
   command_line->AppendSwitchASCII(switches::kUseANGLE,
                                   gl::kANGLEImplementationOpenGLESName);
   displays.clear();
-  GetEGLInitDisplaysForTesting(true, true, true, true, true, true, true,
-                               command_line.get(), &displays);
+  gl::init::GetEGLInitDisplaysForTesting(true, true, true, true, true, true,
+                                         true, command_line.get(), &displays);
   EXPECT_TRUE(base::Contains(displays, gl::ANGLE_OPENGLES));
   EXPECT_EQ(displays.size(), 1u);
 
@@ -91,8 +94,8 @@
   command_line->AppendSwitchASCII(switches::kUseANGLE,
                                   gl::kANGLEImplementationNullName);
   displays.clear();
-  GetEGLInitDisplaysForTesting(true, true, true, true, true, true, true,
-                               command_line.get(), &displays);
+  gl::init::GetEGLInitDisplaysForTesting(true, true, true, true, true, true,
+                                         true, command_line.get(), &displays);
   EXPECT_TRUE(base::Contains(displays, gl::ANGLE_NULL));
   EXPECT_EQ(displays.size(), 1u);
 
@@ -100,8 +103,8 @@
   command_line->AppendSwitchASCII(switches::kUseANGLE,
                                   gl::kANGLEImplementationVulkanName);
   displays.clear();
-  GetEGLInitDisplaysForTesting(true, true, true, true, true, true, true,
-                               command_line.get(), &displays);
+  gl::init::GetEGLInitDisplaysForTesting(true, true, true, true, true, true,
+                                         true, command_line.get(), &displays);
   EXPECT_TRUE(base::Contains(displays, gl::ANGLE_VULKAN));
   EXPECT_EQ(displays.size(), 1u);
 
@@ -109,8 +112,8 @@
   command_line->AppendSwitchASCII(switches::kUseANGLE,
                                   gl::kANGLEImplementationSwiftShaderName);
   displays.clear();
-  GetEGLInitDisplaysForTesting(true, true, true, true, true, true, true,
-                               command_line.get(), &displays);
+  gl::init::GetEGLInitDisplaysForTesting(true, true, true, true, true, true,
+                                         true, command_line.get(), &displays);
   EXPECT_TRUE(base::Contains(displays, gl::ANGLE_SWIFTSHADER));
   EXPECT_EQ(displays.size(), 1u);
 
@@ -118,8 +121,8 @@
   command_line->AppendSwitchASCII(switches::kUseANGLE,
                                   gl::kANGLEImplementationOpenGLEGLName);
   displays.clear();
-  GetEGLInitDisplaysForTesting(true, true, true, true, true, true, true,
-                               command_line.get(), &displays);
+  gl::init::GetEGLInitDisplaysForTesting(true, true, true, true, true, true,
+                                         true, command_line.get(), &displays);
   EXPECT_TRUE(base::Contains(displays, gl::ANGLE_OPENGL_EGL));
   EXPECT_EQ(displays.size(), 1u);
 
@@ -127,8 +130,8 @@
   command_line->AppendSwitchASCII(switches::kUseANGLE,
                                   gl::kANGLEImplementationOpenGLESEGLName);
   displays.clear();
-  GetEGLInitDisplaysForTesting(true, true, true, true, true, true, true,
-                               command_line.get(), &displays);
+  gl::init::GetEGLInitDisplaysForTesting(true, true, true, true, true, true,
+                                         true, command_line.get(), &displays);
   EXPECT_TRUE(base::Contains(displays, gl::ANGLE_OPENGLES_EGL));
   EXPECT_EQ(displays.size(), 1u);
 
@@ -136,8 +139,8 @@
   command_line->AppendSwitchASCII(switches::kUseANGLE,
                                   gl::kANGLEImplementationMetalName);
   displays.clear();
-  GetEGLInitDisplaysForTesting(true, true, true, true, true, true, true,
-                               command_line.get(), &displays);
+  gl::init::GetEGLInitDisplaysForTesting(true, true, true, true, true, true,
+                                         true, command_line.get(), &displays);
   EXPECT_TRUE(base::Contains(displays, gl::ANGLE_METAL));
   EXPECT_EQ(displays.size(), 1u);
 }
@@ -148,8 +151,9 @@
 
   // With no angle platform extensions, only DEFAULT should be available
   std::vector<gl::DisplayType> displays;
-  GetEGLInitDisplaysForTesting(false, false, false, false, false, false, false,
-                               command_line.get(), &displays);
+  gl::init::GetEGLInitDisplaysForTesting(false, false, false, false, false,
+                                         false, false, command_line.get(),
+                                         &displays);
   EXPECT_TRUE(base::Contains(displays, gl::DEFAULT));
   EXPECT_EQ(displays.size(), 1u);
 }
diff --git a/ui/gl/test/gl_surface_test_support.cc b/ui/gl/test/gl_surface_test_support.cc
index 43dd9e6..673e3e7 100644
--- a/ui/gl/test/gl_surface_test_support.cc
+++ b/ui/gl/test/gl_surface_test_support.cc
@@ -72,7 +72,7 @@
       impl, fallback_to_software_gl));
   GLDisplay* display = gl::init::InitializeGLOneOffPlatformImplementation(
       fallback_to_software_gl, disable_gl_drawing, init_extensions,
-      /*system_device_id=*/0);
+      /*gpu_preference=*/gl::GpuPreference::kDefault);
   CHECK(display);
   return display;
 }
@@ -102,7 +102,7 @@
       impl, fallback_to_software_gl));
   GLDisplay* display = gl::init::InitializeGLOneOffPlatformImplementation(
       fallback_to_software_gl, disable_gl_drawing, init_extensions,
-      /*system_device_id=*/0);
+      /*gpu_preference=*/gl::GpuPreference::kDefault);
   CHECK(display);
   return display;
 }
diff --git a/ui/ozone/common/gl_ozone_egl.cc b/ui/ozone/common/gl_ozone_egl.cc
index e745dd7..ec1493e 100644
--- a/ui/ozone/common/gl_ozone_egl.cc
+++ b/ui/ozone/common/gl_ozone_egl.cc
@@ -18,9 +18,11 @@
 namespace ui {
 
 gl::GLDisplay* GLOzoneEGL::InitializeGLOneOffPlatform(
-    uint64_t system_device_id) {
-  gl::GLDisplayEGL* display = gl::GetDisplayEGL(system_device_id);
-  if (!display->Initialize(GetNativeDisplay())) {
+    bool supports_angle,
+    std::vector<gl::DisplayType> init_displays,
+    gl::GpuPreference gpu_preference) {
+  gl::GLDisplayEGL* display = gl::GetDisplayEGL(gpu_preference);
+  if (!display->Initialize(supports_angle, init_displays, GetNativeDisplay())) {
     LOG(ERROR) << "GLDisplayEGL::Initialize failed.";
     return nullptr;
   }
diff --git a/ui/ozone/common/gl_ozone_egl.h b/ui/ozone/common/gl_ozone_egl.h
index b533b70..5503ea1 100644
--- a/ui/ozone/common/gl_ozone_egl.h
+++ b/ui/ozone/common/gl_ozone_egl.h
@@ -24,7 +24,10 @@
   ~GLOzoneEGL() override {}
 
   // GLOzone:
-  gl::GLDisplay* InitializeGLOneOffPlatform(uint64_t system_device_id) override;
+  gl::GLDisplay* InitializeGLOneOffPlatform(
+      bool supports_angle,
+      std::vector<gl::DisplayType> init_displays,
+      gl::GpuPreference gpu_preference) override;
   bool InitializeStaticGLBindings(
       const gl::GLImplementationParts& implementation) override;
   void SetDisabledExtensionsPlatform(
diff --git a/ui/ozone/demo/simple_renderer_factory.cc b/ui/ozone/demo/simple_renderer_factory.cc
index ff5c26f..e090bb8 100644
--- a/ui/ozone/demo/simple_renderer_factory.cc
+++ b/ui/ozone/demo/simple_renderer_factory.cc
@@ -75,7 +75,8 @@
   }
 #endif
   if (!command_line->HasSwitch(kDisableGpu)) {
-    display_ = gl::init::InitializeGLOneOff(/*system_device_id=*/0);
+    display_ = gl::init::InitializeGLOneOff(
+        /*gpu_preference=*/gl::GpuPreference::kDefault);
     if (display_) {
       type_ = GL;
     } else {
diff --git a/ui/ozone/demo/skia/skia_renderer_factory.cc b/ui/ozone/demo/skia/skia_renderer_factory.cc
index ab6f651..efef629c 100644
--- a/ui/ozone/demo/skia/skia_renderer_factory.cc
+++ b/ui/ozone/demo/skia/skia_renderer_factory.cc
@@ -46,7 +46,8 @@
 }
 
 bool SkiaRendererFactory::Initialize() {
-  display_ = gl::init::InitializeGLOneOff(/*system_device_id=*/0);
+  display_ = gl::init::InitializeGLOneOff(
+      /*gpu_preference=*/gl::GpuPreference::kDefault);
   if (!display_) {
     LOG(FATAL) << "Failed to initialize GL";
   }
diff --git a/ui/ozone/platform/flatland/flatland_surface_factory.cc b/ui/ozone/platform/flatland/flatland_surface_factory.cc
index f34d567..31592bd5 100644
--- a/ui/ozone/platform/flatland/flatland_surface_factory.cc
+++ b/ui/ozone/platform/flatland/flatland_surface_factory.cc
@@ -122,7 +122,6 @@
 FlatlandSurfaceFactory::GetAllowedGLImplementations() {
   return std::vector<gl::GLImplementationParts>{
       gl::GLImplementationParts(gl::kGLImplementationEGLANGLE),
-      gl::GLImplementationParts(gl::ANGLEImplementation::kSwiftShader),
       gl::GLImplementationParts(gl::kGLImplementationEGLGLES2),
       gl::GLImplementationParts(gl::kGLImplementationStubGL),
   };
diff --git a/ui/ozone/platform/headless/headless_surface_factory.cc b/ui/ozone/platform/headless/headless_surface_factory.cc
index 580e1f86..8907421 100644
--- a/ui/ozone/platform/headless/headless_surface_factory.cc
+++ b/ui/ozone/platform/headless/headless_surface_factory.cc
@@ -232,9 +232,8 @@
 std::vector<gl::GLImplementationParts>
 HeadlessSurfaceFactory::GetAllowedGLImplementations() {
   return std::vector<gl::GLImplementationParts>{
-      gl::GLImplementationParts(gl::ANGLEImplementation::kSwiftShader),
+      gl::GLImplementationParts(gl::kGLImplementationEGLANGLE),
       gl::GLImplementationParts(gl::kGLImplementationEGLGLES2),
-      gl::GLImplementationParts(gl::ANGLEImplementation::kDefault),
   };
 }
 
diff --git a/ui/ozone/platform/scenic/scenic_surface_factory.cc b/ui/ozone/platform/scenic/scenic_surface_factory.cc
index e179c71..c35b0063 100644
--- a/ui/ozone/platform/scenic/scenic_surface_factory.cc
+++ b/ui/ozone/platform/scenic/scenic_surface_factory.cc
@@ -131,7 +131,6 @@
 ScenicSurfaceFactory::GetAllowedGLImplementations() {
   return std::vector<gl::GLImplementationParts>{
       gl::GLImplementationParts(gl::kGLImplementationEGLANGLE),
-      gl::GLImplementationParts(gl::ANGLEImplementation::kSwiftShader),
       gl::GLImplementationParts(gl::kGLImplementationEGLGLES2),
       gl::GLImplementationParts(gl::kGLImplementationStubGL),
   };
diff --git a/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc b/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc
index ab19a324..5d27a97 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc
+++ b/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc
@@ -197,20 +197,15 @@
 WaylandSurfaceFactory::GetAllowedGLImplementations() {
   std::vector<gl::GLImplementationParts> impls;
   if (egl_implementation_) {
-    impls.emplace_back(
-        gl::GLImplementationParts(gl::kGLImplementationEGLGLES2));
+    // TODO(crbug.com/1231934): Ensure the passthrough is supported on Lacros
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
     // Add only supported ANGLE implementations. Otherwise, angle-vulkan might
     // be requested, which is not supported with this backend yet.
-    impls.emplace_back(
-        gl::GLImplementationParts(gl::ANGLEImplementation::kSwiftShader));
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-    // TODO(crbug.com/1231934): --use-angle=gl results in gles, resolve that and
-    // use the correct config/testsuite on Lacros-like Linux bots.
-    impls.emplace_back(
-        gl::GLImplementationParts(gl::ANGLEImplementation::kOpenGL));
-    impls.emplace_back(
-        gl::GLImplementationParts(gl::ANGLEImplementation::kOpenGLES));
-#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
+    impls.emplace_back(gl::ANGLEImplementation::kOpenGL);
+    impls.emplace_back(gl::ANGLEImplementation::kOpenGLES);
+#endif
+    impls.emplace_back(gl::ANGLEImplementation::kSwiftShader);
+    impls.emplace_back(gl::kGLImplementationEGLGLES2);
   }
   return impls;
 }
diff --git a/ui/ozone/platform/x11/x11_surface_factory.cc b/ui/ozone/platform/x11/x11_surface_factory.cc
index d0cf654..d957fee 100644
--- a/ui/ozone/platform/x11/x11_surface_factory.cc
+++ b/ui/ozone/platform/x11/x11_surface_factory.cc
@@ -130,9 +130,9 @@
 std::vector<gl::GLImplementationParts>
 X11SurfaceFactory::GetAllowedGLImplementations() {
   return std::vector<gl::GLImplementationParts>{
-      gl::GLImplementationParts(gl::kGLImplementationEGLGLES2),
       gl::GLImplementationParts(gl::kGLImplementationEGLANGLE),
-      gl::GLImplementationParts(gl::ANGLEImplementation::kSwiftShader)};
+      gl::GLImplementationParts(gl::kGLImplementationEGLGLES2),
+  };
 }
 
 GLOzone* X11SurfaceFactory::GetGLOzone(
diff --git a/ui/ozone/public/gl_ozone.h b/ui/ozone/public/gl_ozone.h
index edc082b6..960d2d2 100644
--- a/ui/ozone/public/gl_ozone.h
+++ b/ui/ozone/public/gl_ozone.h
@@ -46,7 +46,9 @@
 
   // Performs any one off initialization for GL implementation.
   virtual gl::GLDisplay* InitializeGLOneOffPlatform(
-      uint64_t system_device_id) = 0;
+      bool supports_angle,
+      std::vector<gl::DisplayType> init_displays,
+      gl::GpuPreference gpu_preference) = 0;
 
   // Disables the specified extensions in the window system bindings,
   // e.g., GLX, EGL, etc. This is part of the GPU driver bug workarounds
diff --git a/ui/views/animation/ink_drop_mask.cc b/ui/views/animation/ink_drop_mask.cc
index b8e005e..3289cd0 100644
--- a/ui/views/animation/ink_drop_mask.cc
+++ b/ui/views/animation/ink_drop_mask.cc
@@ -31,7 +31,7 @@
 
 void PathInkDropMask::OnPaintLayer(const ui::PaintContext& context) {
   cc::PaintFlags flags;
-  flags.setAlpha(255);
+  flags.setAlphaf(1.0f);
   flags.setStyle(cc::PaintFlags::kFill_Style);
   flags.setAntiAlias(true);
 
diff --git a/ui/views/controls/button/label_button_border.cc b/ui/views/controls/button/label_button_border.cc
index 367001d9079..9d16738 100644
--- a/ui/views/controls/button/label_button_border.cc
+++ b/ui/views/controls/button/label_button_border.cc
@@ -113,7 +113,7 @@
 
     // Then modulate the foreground by alpha, and blend using kPlus_Mode.
     cc::PaintFlags flags;
-    flags.setAlpha(fg_alpha);
+    flags.setAlphaf(fg_alpha / 255.0f);
     flags.setBlendMode(SkBlendMode::kPlus);
     canvas->sk_canvas()->saveLayer(sk_rect, flags);
     state = native_theme_delegate->GetForegroundThemeState(&extra);
diff --git a/ui/views/examples/examples_main_proc.cc b/ui/views/examples/examples_main_proc.cc
index 7bc3c52d..254dab2 100644
--- a/ui/views/examples/examples_main_proc.cc
+++ b/ui/views/examples/examples_main_proc.cc
@@ -106,7 +106,7 @@
   ui::OzonePlatform::InitializeForGPU(params);
 #endif
 
-  gl::init::InitializeGLOneOff(/*system_device_id=*/0);
+  gl::init::InitializeGLOneOff(/*gpu_preference=*/gl::GpuPreference::kDefault);
 
   // Viz depends on the task environment to correctly tear down.
   base::test::TaskEnvironment task_environment(
diff --git a/ui/views/view.cc b/ui/views/view.cc
index b51b3ed..fa4bcc83c 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -198,7 +198,7 @@
 
 void ViewMaskLayer::OnPaintLayer(const ui::PaintContext& context) {
   cc::PaintFlags flags;
-  flags.setAlpha(255);
+  flags.setAlphaf(1.0f);
   flags.setStyle(cc::PaintFlags::kFill_Style);
   flags.setAntiAlias(true);
 
diff --git a/ui/views/window/frame_caption_button.cc b/ui/views/window/frame_caption_button.cc
index f036248..cb4621c 100644
--- a/ui/views/window/frame_caption_button.cc
+++ b/ui/views/window/frame_caption_button.cc
@@ -289,7 +289,7 @@
     // maximized state or vice versa. https://crbug.com/840901.
     cc::PaintFlags flags;
     flags.setColor(InkDrop::Get(this)->GetBaseColor());
-    flags.setAlpha(highlight_alpha);
+    flags.setAlphaf(highlight_alpha / 255.0f);
     DrawHighlight(canvas, flags);
   }
 
@@ -308,11 +308,11 @@
   if (crossfade_icon_alpha > 0 && !crossfade_icon_image_.isNull()) {
     canvas->SaveLayerAlpha(GetAlphaForIcon(alpha_));
     cc::PaintFlags flags;
-    flags.setAlpha(icon_alpha);
+    flags.setAlphaf(icon_alpha / 255.0f);
     DrawIconContents(canvas, icon_image_, centered_origin_x, centered_origin_y,
                      flags);
 
-    flags.setAlpha(crossfade_icon_alpha);
+    flags.setAlphaf(crossfade_icon_alpha / 255.0f);
     flags.setBlendMode(SkBlendMode::kPlus);
     DrawIconContents(canvas, crossfade_icon_image_, centered_origin_x,
                      centered_origin_y, flags);
@@ -321,7 +321,7 @@
     if (!swap_images_animation_->is_animating())
       icon_alpha = alpha_;
     cc::PaintFlags flags;
-    flags.setAlpha(GetAlphaForIcon(icon_alpha));
+    flags.setAlphaf(GetAlphaForIcon(icon_alpha) / 255.0f);
     DrawIconContents(canvas, icon_image_, centered_origin_x, centered_origin_y,
                      flags);
   }
diff --git a/ui/webui/resources/BUILD.gn b/ui/webui/resources/BUILD.gn
index 1a9db87..ec036c9 100644
--- a/ui/webui/resources/BUILD.gn
+++ b/ui/webui/resources/BUILD.gn
@@ -4,7 +4,6 @@
 
 import("//build/config/chromeos/ui_mode.gni")
 import("//crypto/features.gni")
-import("//tools/typescript/ts_definitions.gni")
 import("//tools/typescript/ts_library.gni")
 import("//ui/webui/resources/include_polymer.gni")
 import("//ui/webui/resources/tools/generate_grd.gni")
@@ -33,7 +32,6 @@
     "css:build_grdp",
     "images:build_grdp",
     "js:build_grdp",
-    "js:build_grdp_deprecated",
     "js/metrics_reporter:build_grdp",
     "//third_party/jstemplate:build_grdp",
   ]
@@ -42,7 +40,6 @@
     "$target_gen_dir/images/resources.grdp",
     "$target_gen_dir/js/metrics_reporter/resources.grdp",
     "$target_gen_dir/js/resources.grdp",
-    "$target_gen_dir/js/resources_deprecated.grdp",
     "$target_gen_dir/resources_ts.grdp",
     "$root_gen_dir/third_party/jstemplate/resources.grdp",
   ]
@@ -146,11 +143,6 @@
 
 preprocessed_folder = "$target_gen_dir/preprocessed"
 
-# Files for which .d.ts files will be auto-generated with ts_definitions().
-if (is_ios) {
-  generate_definitions_js_files = [ "js/ios/web_ui.js" ]
-}
-
 ts_library("library") {
   root_dir = preprocessed_folder
   out_dir = preprocessed_folder
@@ -165,23 +157,12 @@
     "//tools/typescript/definitions/settings_private.d.ts",
   ]
 
-  # Auto-generated .d.ts files.
-  if (is_ios) {
-    foreach(_file, generate_definitions_js_files) {
-      definitions += [ "$root_dir/" + string_replace(_file, ".js", ".d.ts") ]
-    }
-  }
-
   deps = [ "//third_party/polymer/v3_0:library" ]
   extra_deps += [
     ":preprocess",
     "js:build_ts",
     "mojo:library",
   ]
-
-  if (is_ios) {
-    extra_deps += [ ":generate_definitions" ]
-  }
 }
 
 generate_grd("build_ts_grdp") {
@@ -191,12 +172,3 @@
   manifest_files =
       filter_include(get_target_outputs(":library"), [ "*.manifest" ])
 }
-
-if (is_ios) {
-  ts_definitions("generate_definitions") {
-    root_dir = preprocessed_folder
-    out_dir = preprocessed_folder
-    js_files = generate_definitions_js_files
-    extra_deps = [ "js:preprocess_src" ]
-  }
-}
diff --git a/ui/webui/resources/cr_components/omnibox/BUILD.gn b/ui/webui/resources/cr_components/omnibox/BUILD.gn
index 192fe3f..78d082a 100644
--- a/ui/webui/resources/cr_components/omnibox/BUILD.gn
+++ b/ui/webui/resources/cr_components/omnibox/BUILD.gn
@@ -2,66 +2,35 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//mojo/public/tools/bindings/mojom.gni")
-import("//tools/polymer/css_to_wrapper.gni")
-import("//tools/polymer/html_to_wrapper.gni")
-import("//tools/typescript/ts_library.gni")
-import("//ui/webui/resources/tools/generate_grd.gni")
-import("//ui/webui/webui_features.gni")
-import("omnibox.gni")
+import("../../tools/build_cr_component.gni")
 
 assert(!is_android && !is_ios)
 
-preprocess_folder =
-    "$root_gen_dir/ui/webui/resources/preprocessed/cr_components/omnibox"
+build_cr_component("build") {
+  grd_prefix = "cr_components_omnibox"
+  web_component_files = [
+    "realbox_action.ts",
+    "realbox_dropdown.ts",
+    "realbox_icon.ts",
+    "realbox_match.ts",
+  ]
+  non_web_component_files = [
+    "realbox_browser_proxy.ts",
+    "utils.ts",
+  ]
+  css_files = [ "realbox_dropdown_shared_style.css" ]
 
-html_to_wrapper("html_wrapper_files") {
-  in_files = html_files
-  minify = optimize_webui
-}
-
-css_to_wrapper("css_wrapper_files") {
-  in_files = css_files
-  minify = optimize_webui
-}
-
-copy("copy_mojom") {
-  deps = [ "//components/omnibox/browser:mojo_bindings_ts__generator" ]
-  sources =
+  mojo_files_deps =
+      [ "//components/omnibox/browser:mojo_bindings_ts__generator" ]
+  mojo_files =
       [ "$root_gen_dir/components/omnibox/browser/omnibox.mojom-webui.ts" ]
-  outputs = [ "$target_gen_dir/{{source_file_part}}" ]
-}
 
-copy("copy_src") {
-  sources = ts_files
-  outputs = [ "$target_gen_dir/{{source_file_part}}" ]
-}
-
-ts_library("build_ts") {
-  root_dir = target_gen_dir
-  out_dir = preprocess_folder
-  composite = true
-  tsconfig_base = "tsconfig_base.json"
-  in_files = ts_files + html_wrapper_files + css_wrapper_files + mojo_files
-  deps = [
+  tsc_dir =
+      "$root_gen_dir/ui/webui/resources/preprocessed/cr_components/omnibox"
+  ts_deps = [
     "//third_party/polymer/v3_0:library",
     "//ui/webui/resources:library",
     "//ui/webui/resources/js/metrics_reporter:build_ts",
     "//ui/webui/resources/mojo:library",
   ]
-  extra_deps = [
-    ":copy_mojom",
-    ":copy_src",
-    ":css_wrapper_files",
-    ":html_wrapper_files",
-  ]
-}
-
-generate_grd("build_grdp") {
-  grd_prefix = "omnibox"
-  out_grd = "$target_gen_dir/resources.grdp"
-  public_deps = [ ":build_ts" ]
-  manifest_files =
-      filter_include(get_target_outputs(":build_ts"), [ "*.manifest" ])
-  resource_path_prefix = "cr_components/omnibox"
 }
diff --git a/ui/webui/resources/cr_components/omnibox/omnibox.gni b/ui/webui/resources/cr_components/omnibox/omnibox.gni
deleted file mode 100644
index 36b85053..0000000
--- a/ui/webui/resources/cr_components/omnibox/omnibox.gni
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright 2022 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Files holding a Polymer element definition AND have an equivalent .html file.
-_web_component_files = [
-  "realbox_action.ts",
-  "realbox_dropdown.ts",
-  "realbox_icon.ts",
-  "realbox_match.ts",
-]
-
-# Files that are passed as input to html_to_wrapper().
-html_files = []
-foreach(f, _web_component_files) {
-  html_files += [ string_replace(f, ".ts", ".html") ]
-}
-
-# Files that are generated by html_to_wrapper().
-html_wrapper_files = []
-foreach(f, html_files) {
-  html_wrapper_files += [ f + ".ts" ]
-}
-
-# Files that don't need to be passed to html_to_wrapper().
-_non_web_component_files = [
-  "realbox_browser_proxy.ts",
-  "utils.ts",
-]
-
-# Files that are passed as input to css_to_wrapper().
-css_files = [ "realbox_dropdown_shared_style.css" ]
-
-# Files that are generated by css_to_wrapper().
-css_wrapper_files = []
-foreach(f, css_files) {
-  css_wrapper_files += [ f + ".ts" ]
-}
-
-mojo_files = [ "omnibox.mojom-webui.ts" ]
-
-ts_files = _web_component_files + _non_web_component_files
diff --git a/ui/webui/resources/cr_elements/cr_grid/cr_grid.html b/ui/webui/resources/cr_elements/cr_grid/cr_grid.html
index 9c5fb4c..a62eb2a 100644
--- a/ui/webui/resources/cr_elements/cr_grid/cr_grid.html
+++ b/ui/webui/resources/cr_elements/cr_grid/cr_grid.html
@@ -2,13 +2,14 @@
   :host {
     --cr-grid-gap: 0px;
     --cr-column-width: auto;
+    --cr-grid-width: fit-content;
   }
 
   #grid {
     display: grid;
     grid-gap: var(--cr-grid-gap);
     grid-template-columns: repeat(var(--cr-grid-columns), var(--cr-column-width));
-    width: fit-content;
+    width: var(--cr-grid-width);
   }
 
   ::slotted(*) {
diff --git a/ui/webui/resources/cr_elements/cr_lottie/cr_lottie.ts b/ui/webui/resources/cr_elements/cr_lottie/cr_lottie.ts
index 4bf7ec9..b93a5aa 100644
--- a/ui/webui/resources/cr_elements/cr_lottie/cr_lottie.ts
+++ b/ui/webui/resources/cr_elements/cr_lottie/cr_lottie.ts
@@ -48,11 +48,6 @@
   return workerLoaderPolicy.createScriptURL('');
 }
 
-interface OffscreenCanvas {
-  width: number;
-  height: number;
-}
-
 interface MessageData {
   animationData: object|null|string;
   drawSize: {width: number, height: number};
diff --git a/ui/webui/resources/js/BUILD.gn b/ui/webui/resources/js/BUILD.gn
index aa6ec41..0dd03081 100644
--- a/ui/webui/resources/js/BUILD.gn
+++ b/ui/webui/resources/js/BUILD.gn
@@ -3,8 +3,6 @@
 # found in the LICENSE file.
 
 import("//build/config/chromeos/ui_mode.gni")
-import("//tools/grit/preprocess_if_expr.gni")
-
 import("../tools/build_cr_component.gni")
 
 include_polymer = !is_android && !is_ios
@@ -26,6 +24,7 @@
     "icon.ts",
     "keyboard_shortcut_list.ts",
     "load_time_data.ts",
+    "load_time_data_deprecated.js",
     "parse_html_subset.ts",
     "platform.ts",
     "plural_string_proxy.ts",
@@ -42,6 +41,18 @@
     non_web_component_files += [ "os_about.ts" ]
   }
 
+  if (is_ios) {
+    non_web_component_files += [
+      "ios/mojo_api.js",
+      "ios/web_ui.js",
+    ]
+  }
+
+  if (is_chromeos_ash || is_ios) {
+    # Used by ChromeOS UIs and ios inspect and omaha UIs
+    non_web_component_files += [ "util_deprecated.js" ]
+  }
+
   if (include_polymer) {
     non_web_component_files += [
       "focus_row_mixin.ts",
@@ -53,33 +64,3 @@
   ts_deps = [ "../mojo:library" ]
   ts_definitions = [ "//tools/typescript/definitions/chrome_send.d.ts" ]
 }
-
-preprocess_folder = "$root_gen_dir/ui/webui/resources/preprocessed/js"
-preprocess_src_manifest = "preprocessed_src_manifest.json"
-
-generate_grd("build_grdp_deprecated") {
-  grd_prefix = "webui_js"
-  out_grd = "$target_gen_dir/resources_deprecated.grdp"
-  public_deps = [ ":preprocess_src" ]
-  manifest_files = [ "$target_gen_dir/$preprocess_src_manifest" ]
-  resource_path_prefix = "js"
-}
-
-preprocess_if_expr("preprocess_src") {
-  in_folder = "."
-  out_folder = preprocess_folder
-  out_manifest = "$target_gen_dir/$preprocess_src_manifest"
-  in_files = [ "load_time_data_deprecated.js" ]
-
-  if (is_chromeos_ash || is_ios) {
-    # Used by ChromeOS UIs and ios inspect and omaha UIs
-    in_files += [ "util_deprecated.js" ]
-  }
-
-  if (is_ios) {
-    in_files += [
-      "ios/mojo_api.js",
-      "ios/web_ui.js",
-    ]
-  }
-}
diff --git a/ui/webui/resources/js/ios/mojo_api.js b/ui/webui/resources/js/ios/mojo_api.js
index 6dc099b9..1c65001e 100644
--- a/ui/webui/resources/js/ios/mojo_api.js
+++ b/ui/webui/resources/js/ios/mojo_api.js
@@ -61,157 +61,159 @@
   });
 };
 
-/**
- * @constructor
- * @param {?number=} nativeHandle An opaque number representing the underlying
- *     Mojo system resource.
- */
-const MojoHandle = function(nativeHandle) {
-  if (nativeHandle === undefined) {
-    nativeHandle = null;
+class MojoHandle {
+  /*
+   * @param {?number=} nativeHandle An opaque number representing the underlying
+   *     Mojo system resource.
+   */
+  constructor(nativeHandle) {
+    if (nativeHandle === undefined) {
+      nativeHandle = null;
+    }
+
+    /**
+     * @type {number|null}
+     */
+    this.nativeHandle_ = nativeHandle;
   }
 
   /**
-   * @type {number|null}
+   * Takes the native handle value. This is not part of the public API.
+   * @return {?number}
    */
-  this.nativeHandle_ = nativeHandle;
-};
-
-/**
- * Takes the native handle value. This is not part of the public API.
- * @return {?number}
- */
-MojoHandle.prototype.takeNativeHandle_ = function() {
-  const nativeHandle = this.nativeHandle_;
-  this.nativeHandle_ = null;
-  return nativeHandle;
-};
-
-/**
- * Closes the handle.
- */
-MojoHandle.prototype.close = function() {
-  if (this.nativeHandle_ === null) {
-    return;
+  takeNativeHandle_() {
+    const nativeHandle = this.nativeHandle_;
+    this.nativeHandle_ = null;
+    return nativeHandle;
   }
 
-  const nativeHandle = this.nativeHandle_;
-  this.nativeHandle_ = null;
-  Mojo.internal.sendMessage(
-      {name: 'MojoHandle.close', args: {handle: nativeHandle}});
-};
+  /**
+   * Closes the handle.
+   */
+  close() {
+    if (this.nativeHandle_ === null) {
+      return;
+    }
 
-/**
- * Begins watching the handle for |signals| to be satisfied or unsatisfiable.
- *
- * @param {readable: boolean=, writable: boolean=, peerClosed: boolean=} signals
- *     The signals to watch.
- * @param {!function(!MojoResult)} calback Called with a result any time
- *     the watched signals become satisfied or unsatisfiable.
- *
- * @return {!MojoWatcher} A MojoWatcher instance that could be used to cancel
- *     the watch.
- */
-MojoHandle.prototype.watch = function(signals, callback) {
-  const HANDLE_SIGNAL_NONE = 0;
-  const HANDLE_SIGNAL_READABLE = 1;
-  const HANDLE_SIGNAL_WRITABLE = 2;
-  const HANDLE_SIGNAL_PEER_CLOSED = 4;
-
-  let signalsValue = HANDLE_SIGNAL_NONE;
-  if (signals.readable) {
-    signalsValue |= HANDLE_SIGNAL_READABLE;
-  }
-  if (signals.writable) {
-    signalsValue |= HANDLE_SIGNAL_WRITABLE;
-  }
-  if (signalsValue.peerClosed) {
-    signalsValue |= HANDLE_SIGNAL_PEER_CLOSED;
+    const nativeHandle = this.nativeHandle_;
+    this.nativeHandle_ = null;
+    Mojo.internal.sendMessage(
+        {name: 'MojoHandle.close', args: {handle: nativeHandle}});
   }
 
-  const watchId = Mojo.internal.sendMessage({
-    name: 'MojoHandle.watch',
-    args: {
-      handle: this.nativeHandle_,
-      signals: signalsValue,
-      callbackId: Mojo.internal.watchCallbacksHolder.getNextCallbackId(),
-    },
-  });
-  Mojo.internal.watchCallbacksHolder.addWatchCallback(watchId, callback);
+  /**
+   * Begins watching the handle for |signals| to be satisfied or unsatisfiable.
+   *
+   * @param {readable: boolean=, writable: boolean=, peerClosed: boolean=}
+   *     signals The signals to watch.
+   * @param {!function(!MojoResult)} callback Called with a result any time
+   *     the watched signals become satisfied or unsatisfiable.
+   *
+   * @return {!MojoWatcher} A MojoWatcher instance that could be used to cancel
+   *     the watch.
+   */
+  watch(signals, callback) {
+    const HANDLE_SIGNAL_NONE = 0;
+    const HANDLE_SIGNAL_READABLE = 1;
+    const HANDLE_SIGNAL_WRITABLE = 2;
+    const HANDLE_SIGNAL_PEER_CLOSED = 4;
 
-  return new MojoWatcher(watchId);
-};
+    let signalsValue = HANDLE_SIGNAL_NONE;
+    if (signals.readable) {
+      signalsValue |= HANDLE_SIGNAL_READABLE;
+    }
+    if (signals.writable) {
+      signalsValue |= HANDLE_SIGNAL_WRITABLE;
+    }
+    if (signalsValue.peerClosed) {
+      signalsValue |= HANDLE_SIGNAL_PEER_CLOSED;
+    }
 
-/**
- * Writes a message to the message pipe.
- *
- * @param {!ArrayBufferView} buffer The message data. May be empty.
- * @param {!Array<!MojoHandle>} handles Any handles to attach. Handles are
- *     transferred and will no longer be valid. May be empty.
- * @return {!MojoResult} Result code.
- */
-MojoHandle.prototype.writeMessage = function(buffer, handles) {
-  let base64EncodedBuffer;
-  if (buffer instanceof Uint8Array) {
-    // calls from mojo_bindings.js
-    base64EncodedBuffer = _Uint8ArrayToBase64(buffer);
-  } else if (buffer instanceof ArrayBuffer) {
-    // calls from mojo/public/js/bindings.js
-    base64EncodedBuffer = _arrayBufferToBase64(buffer);
+    const watchId = Mojo.internal.sendMessage({
+      name: 'MojoHandle.watch',
+      args: {
+        handle: this.nativeHandle_,
+        signals: signalsValue,
+        callbackId: Mojo.internal.watchCallbacksHolder.getNextCallbackId(),
+      },
+    });
+    Mojo.internal.watchCallbacksHolder.addWatchCallback(watchId, callback);
+
+    return new MojoWatcher(watchId);
   }
-  const nativeHandles = handles.map(function(handle) {
-    return handle.takeNativeHandle_();
-  });
-  return Mojo.internal.sendMessage({
-    name: 'MojoHandle.writeMessage',
-    args: {
-      handle: this.nativeHandle_,
-      buffer: base64EncodedBuffer,
-      handles: nativeHandles,
-    },
-  });
-};
 
-/**
- * Reads a message from the message pipe.
- *
- * @return {result: !MojoResult,
- *          buffer: !ArrayBufferView=,
- *          handles: !Array<!MojoHandle>=}
- *     Result code and (on success) the data and handles received.
- */
-MojoHandle.prototype.readMessage = function() {
-  const result = Mojo.internal.sendMessage(
-      {name: 'MojoHandle.readMessage', args: {handle: this.nativeHandle_}});
-
-  if (result.result === Mojo.RESULT_OK) {
-    result.buffer = new Uint8Array(result.buffer).buffer;
-    result.handles = result.handles.map(function(handle) {
-      return new MojoHandle(handle);
+  /**
+   * Writes a message to the message pipe.
+   *
+   * @param {!ArrayBufferView} buffer The message data. May be empty.
+   * @param {!Array<!MojoHandle>} handles Any handles to attach. Handles are
+   *     transferred and will no longer be valid. May be empty.
+   * @return {!MojoResult} Result code.
+   */
+  writeMessage(buffer, handles) {
+    let base64EncodedBuffer;
+    if (buffer instanceof Uint8Array) {
+      // calls from mojo_bindings.js
+      base64EncodedBuffer = _Uint8ArrayToBase64(buffer);
+    } else if (buffer instanceof ArrayBuffer) {
+      // calls from mojo/public/js/bindings.js
+      base64EncodedBuffer = _arrayBufferToBase64(buffer);
+    }
+    const nativeHandles = handles.map(function(handle) {
+      return handle.takeNativeHandle_();
+    });
+    return Mojo.internal.sendMessage({
+      name: 'MojoHandle.writeMessage',
+      args: {
+        handle: this.nativeHandle_,
+        buffer: base64EncodedBuffer,
+        handles: nativeHandles,
+      },
     });
   }
-  return result;
-};
+
+  /**
+   * Reads a message from the message pipe.
+   *
+   * @return {result: !MojoResult,
+   *          buffer: !ArrayBufferView=,
+   *          handles: !Array<!MojoHandle>=}
+   *     Result code and (on success) the data and handles received.
+   */
+  readMessage() {
+    const result = Mojo.internal.sendMessage(
+        {name: 'MojoHandle.readMessage', args: {handle: this.nativeHandle_}});
+
+    if (result.result === Mojo.RESULT_OK) {
+      result.buffer = new Uint8Array(result.buffer).buffer;
+      result.handles = result.handles.map(function(handle) {
+        return new MojoHandle(handle);
+      });
+    }
+    return result;
+  }
+}
+
 
 /**
  * MojoWatcher identifies a watch on a MojoHandle and can be used to cancel the
  * watch.
- *
- * @constructor
- * @param {number} An opaque id representing the watch.
  */
-const MojoWatcher = function(watchId) {
-  this.watchId_ = watchId;
-};
+class MojoWatcher {
+  /** @param {number} An opaque id representing the watch. */
+  constructor(watchId) {
+    this.watchId_ = watchId;
+  }
 
-/*
- * Cancels a handle watch.
- */
-MojoWatcher.prototype.cancel = function() {
-  Mojo.internal.sendMessage(
-      {name: 'MojoWatcher.cancel', args: {watchId: this.watchId_}});
-  Mojo.internal.watchCallbacksHolder.removeWatchCallback(this.watchId_);
-};
+  /*
+   * Cancels a handle watch.
+   */
+  cancel() {
+    Mojo.internal.sendMessage(
+        {name: 'MojoWatcher.cancel', args: {watchId: this.watchId_}});
+    Mojo.internal.watchCallbacksHolder.removeWatchCallback(this.watchId_);
+  }
+}
 
 // -----------------------------------------------------------------------------
 // Mojo API implementation details. It is not part of the public API.
@@ -329,4 +331,4 @@
     binary += String.fromCharCode(bytes[i]);
   }
   return window.btoa(binary);
-}
\ No newline at end of file
+}
diff --git a/ui/webui/resources/js/tsconfig_base.json b/ui/webui/resources/js/tsconfig_base.json
index e5c5b62..362119d6 100644
--- a/ui/webui/resources/js/tsconfig_base.json
+++ b/ui/webui/resources/js/tsconfig_base.json
@@ -1,6 +1,7 @@
 {
   "extends": "../../../../tools/typescript/tsconfig_base.json",
   "compilerOptions": {
+    "allowJs": true,
     "strictPropertyInitialization": false
   }
 }
diff --git a/ui/wm/core/cursor_loader.cc b/ui/wm/core/cursor_loader.cc
index d2f93fa..20a96a3 100644
--- a/ui/wm/core/cursor_loader.cc
+++ b/ui/wm/core/cursor_loader.cc
@@ -19,7 +19,6 @@
 #include "ui/base/cursor/platform_cursor.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/wm/core/cursor_util.h"
-#include "ui/wm/core/cursors_aura.h"
 
 namespace wm {
 
@@ -27,9 +26,6 @@
 
 using ::ui::mojom::CursorType;
 
-constexpr CursorType kAnimatedCursorTypes[] = {CursorType::kWait,
-                                               CursorType::kProgress};
-
 constexpr base::TimeDelta kAnimatedCursorFrameDelay = base::Milliseconds(25);
 
 }  // namespace
@@ -42,7 +38,6 @@
 
 CursorLoader::~CursorLoader() {
   factory_->RemoveObserver(this);
-  UnloadCursors();
 }
 
 void CursorLoader::OnThemeLoaded() {
@@ -93,24 +88,18 @@
   if (type == CursorType::kCustom)
     return ui::CursorData({cursor.custom_bitmap()}, cursor.custom_hotspot());
 
-  return ui::CursorData({GetDefaultBitmap(cursor)}, GetDefaultHotspot(cursor));
-}
-
-void CursorLoader::LoadImageCursor(CursorType type,
-                                   int resource_id,
-                                   const gfx::Point& hot) {
-  gfx::Point hotspot = hot;
-  if (base::ranges::count(kAnimatedCursorTypes, type) == 0) {
-    SkBitmap bitmap;
-    GetImageCursorBitmap(resource_id, scale(), rotation(), &hotspot, &bitmap);
-    image_cursors_[type] = factory_->CreateImageCursor(type, bitmap, hotspot);
-  } else {
-    std::vector<SkBitmap> bitmaps;
-    GetAnimatedCursorBitmaps(resource_id, scale(), rotation(), &hotspot,
-                             &bitmaps);
-    image_cursors_[type] = factory_->CreateAnimatedCursor(
-        type, bitmaps, hotspot, kAnimatedCursorFrameDelay);
+  if (use_platform_cursors_) {
+    auto cursor_data = factory_->GetCursorData(type);
+    if (cursor_data) {
+      return cursor_data;
+    }
   }
+
+  // TODO(https://crbug.com/1193775): use the actual `size_` and `rotation_`
+  // if that makes sense for the current use cases of `GetCursorData` (e.g.
+  // Chrome Remote Desktop, WebRTC and VideoRecordingWatcher).
+  return wm::GetCursorData(type, ui::CursorSize::kNormal, scale_,
+                           display::Display::ROTATE_0);
 }
 
 scoped_refptr<ui::PlatformCursor> CursorLoader::CursorFromType(
@@ -146,13 +135,21 @@
 
 scoped_refptr<ui::PlatformCursor> CursorLoader::LoadCursorFromAsset(
     CursorType type) {
-  int resource_id;
-  gfx::Point hotspot;
-  if (GetCursorDataFor(size(), type, scale(), &resource_id, &hotspot)) {
-    LoadImageCursor(type, resource_id, hotspot);
-    return image_cursors_[type];
+  absl::optional<ui::CursorData> cursor_data =
+      wm::GetCursorData(type, size_, scale_, rotation_);
+  if (!cursor_data) {
+    return nullptr;
   }
-  return nullptr;
+
+  if (cursor_data->bitmaps.size() == 1) {
+    image_cursors_[type] = factory_->CreateImageCursor(
+        type, cursor_data->bitmaps[0], cursor_data->hotspot);
+  } else {
+    image_cursors_[type] = factory_->CreateAnimatedCursor(
+        type, cursor_data->bitmaps, cursor_data->hotspot,
+        kAnimatedCursorFrameDelay);
+  }
+  return image_cursors_[type];
 }
 
 }  // namespace wm
diff --git a/ui/wm/core/cursor_loader.h b/ui/wm/core/cursor_loader.h
index 417e624..146347a 100644
--- a/ui/wm/core/cursor_loader.h
+++ b/ui/wm/core/cursor_loader.h
@@ -18,10 +18,6 @@
 #include "ui/base/cursor/mojom/cursor_type.mojom-forward.h"
 #include "ui/display/display.h"
 
-namespace gfx {
-class Point;
-}
-
 namespace ui {
 class PlatformCursor;
 }
@@ -64,9 +60,6 @@
  private:
   // Resets the cursor cache.
   void UnloadCursors();
-  void LoadImageCursor(ui::mojom::CursorType id,
-                       int resource_id,
-                       const gfx::Point& hot);
   scoped_refptr<ui::PlatformCursor> CursorFromType(ui::mojom::CursorType type);
   scoped_refptr<ui::PlatformCursor> LoadCursorFromAsset(
       ui::mojom::CursorType type);
diff --git a/ui/wm/core/cursor_loader_unittest.cc b/ui/wm/core/cursor_loader_unittest.cc
index 69763d7..3f222a6 100644
--- a/ui/wm/core/cursor_loader_unittest.cc
+++ b/ui/wm/core/cursor_loader_unittest.cc
@@ -14,9 +14,10 @@
 #include "ui/base/cursor/cursor_factory.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
 #include "ui/base/cursor/platform_cursor.h"
+#include "ui/display/display.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/skia_util.h"
-#include "ui/wm/core/cursors_aura.h"
+#include "ui/wm/core/cursor_util.h"
 
 namespace wm {
 
@@ -31,7 +32,7 @@
   return bitmap;
 }
 
-SkBitmap GetCursorBitmap(const ui::Cursor& cursor) {
+std::vector<SkBitmap> GetCursorBitmaps(const ui::Cursor& cursor) {
   auto* cursor_shape_client = aura::client::GetCursorShapeClient();
   EXPECT_NE(cursor_shape_client, nullptr);
 
@@ -39,7 +40,7 @@
       cursor_shape_client->GetCursorData(cursor);
   EXPECT_TRUE(cursor_data);
   // CursorData guarantees that bitmaps has at least 1 element.
-  return cursor_data->bitmaps[0];
+  return cursor_data->bitmaps;
 }
 
 gfx::Point GetCursorHotspot(const ui::Cursor& cursor) {
@@ -66,29 +67,53 @@
 }
 
 TEST_F(CursorLoaderTest, GetCursorData) {
+  // Make sure we always use the fallback cursors, so the test works the same
+  // in all platforms.
+  CursorLoader cursor_loader(/*use_platform_cursors=*/false);
+  aura::client::SetCursorShapeClient(&cursor_loader);
+
+  const ui::CursorSize kDefaultSize = ui::CursorSize::kNormal;
+  const float kDefaultScale = 1.0f;
+  const display::Display::Rotation kDefaultRotation =
+      display::Display::ROTATE_0;
+
   const ui::Cursor invisible_cursor = CursorType::kNone;
-  EXPECT_TRUE(GetCursorBitmap(invisible_cursor).isNull());
+  EXPECT_TRUE(GetCursorBitmaps(invisible_cursor)[0].isNull());
   EXPECT_TRUE(GetCursorHotspot(invisible_cursor).IsOrigin());
 
   const ui::Cursor pointer_cursor = CursorType::kPointer;
-  EXPECT_FALSE(GetCursorBitmap(pointer_cursor).isNull());
-  EXPECT_TRUE(gfx::BitmapsAreEqual(GetCursorBitmap(pointer_cursor),
-                                   GetDefaultBitmap(pointer_cursor)));
-  EXPECT_EQ(GetCursorHotspot(pointer_cursor),
-            GetDefaultHotspot(pointer_cursor));
+  EXPECT_EQ(GetCursorBitmaps(pointer_cursor).size(), 1u);
+  EXPECT_FALSE(GetCursorBitmaps(pointer_cursor)[0].isNull());
+  const auto pointer_cursor_data = GetCursorData(
+      CursorType::kPointer, kDefaultSize, kDefaultScale, kDefaultRotation);
+  ASSERT_TRUE(pointer_cursor_data);
+  ASSERT_EQ(pointer_cursor_data->bitmaps.size(), 1u);
+  EXPECT_TRUE(gfx::BitmapsAreEqual(GetCursorBitmaps(pointer_cursor)[0],
+                                   pointer_cursor_data->bitmaps[0]));
+  EXPECT_FALSE(GetCursorHotspot(pointer_cursor).IsOrigin());
+  EXPECT_EQ(GetCursorHotspot(pointer_cursor), pointer_cursor_data->hotspot);
 
-  const ui::Cursor wait_cursor = CursorType::kPointer;
-  EXPECT_FALSE(GetCursorBitmap(wait_cursor).isNull());
-  EXPECT_TRUE(gfx::BitmapsAreEqual(GetCursorBitmap(wait_cursor),
-                                   GetDefaultBitmap(wait_cursor)));
-  EXPECT_EQ(GetCursorHotspot(wait_cursor), GetDefaultHotspot(wait_cursor));
+  const ui::Cursor wait_cursor = CursorType::kWait;
+  EXPECT_FALSE(GetCursorBitmaps(wait_cursor)[0].isNull());
+  const auto wait_cursor_data = GetCursorData(CursorType::kWait, kDefaultSize,
+                                              kDefaultScale, kDefaultRotation);
+  ASSERT_TRUE(wait_cursor_data);
+  ASSERT_GT(wait_cursor_data->bitmaps.size(), 1u);
+  ASSERT_EQ(GetCursorBitmaps(wait_cursor).size(),
+            wait_cursor_data->bitmaps.size());
+  for (size_t i = 0; i < wait_cursor_data->bitmaps.size(); i++) {
+    EXPECT_TRUE(gfx::BitmapsAreEqual(GetCursorBitmaps(wait_cursor)[i],
+                                     wait_cursor_data->bitmaps[i]));
+  }
+  EXPECT_FALSE(GetCursorHotspot(wait_cursor).IsOrigin());
+  EXPECT_EQ(GetCursorHotspot(wait_cursor), wait_cursor_data->hotspot);
 
   ui::Cursor custom_cursor(CursorType::kCustom);
   const SkBitmap kBitmap = GetTestBitmap();
   constexpr gfx::Point kHotspot = gfx::Point(10, 10);
   custom_cursor.set_custom_bitmap(kBitmap);
   custom_cursor.set_custom_hotspot(kHotspot);
-  EXPECT_EQ(GetCursorBitmap(custom_cursor).getGenerationID(),
+  EXPECT_EQ(GetCursorBitmaps(custom_cursor)[0].getGenerationID(),
             kBitmap.getGenerationID());
   EXPECT_EQ(GetCursorHotspot(custom_cursor), kHotspot);
 }
diff --git a/ui/wm/core/cursor_util.cc b/ui/wm/core/cursor_util.cc
index 6f1b51f..0a43a09 100644
--- a/ui/wm/core/cursor_util.cc
+++ b/ui/wm/core/cursor_util.cc
@@ -6,7 +6,10 @@
 
 #include "base/check_op.h"
 #include "base/notreached.h"
+#include "base/ranges/algorithm.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/cursor/cursor.h"
+#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/point_conversions.h"
@@ -16,11 +19,17 @@
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/image/image_skia_rep.h"
 #include "ui/gfx/skbitmap_operations.h"
+#include "ui/wm/core/cursors_aura.h"
 
 namespace wm {
 
 namespace {
 
+using ::ui::mojom::CursorType;
+
+constexpr CursorType kAnimatedCursorTypes[] = {CursorType::kWait,
+                                               CursorType::kProgress};
+
 // Converts the SkBitmap to use a different alpha type. Returns true if bitmap
 // was modified, otherwise returns false.
 bool ConvertSkBitmapAlphaType(SkBitmap* bitmap, SkAlphaType alpha_type) {
@@ -43,8 +52,84 @@
   return true;
 }
 
+void GetImageCursorBitmap(int resource_id,
+                          float scale,
+                          display::Display::Rotation rotation,
+                          gfx::Point* hotspot,
+                          SkBitmap* bitmap) {
+  const gfx::ImageSkia* image =
+      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
+  const gfx::ImageSkiaRep& image_rep = image->GetRepresentation(scale);
+  // TODO(oshima): The cursor should use resource scale factor when
+  // fractional scale factor is enabled. crbug.com/372212
+  (*bitmap) = image_rep.GetBitmap();
+  ScaleAndRotateCursorBitmapAndHotpoint(scale / image_rep.scale(), rotation,
+                                        bitmap, hotspot);
+  // |image_rep| is owned by the resource bundle. So we do not need to free it.
+}
+
+void GetAnimatedCursorBitmaps(int resource_id,
+                              float scale,
+                              display::Display::Rotation rotation,
+                              gfx::Point* hotspot,
+                              std::vector<SkBitmap>* bitmaps) {
+  // TODO(oshima|tdanderson): Support rotation and fractional scale factor.
+  const gfx::ImageSkia* image =
+      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
+  const gfx::ImageSkiaRep& image_rep = image->GetRepresentation(scale);
+  SkBitmap bitmap = image_rep.GetBitmap();
+
+  // The image is assumed to be a concatenation of animation frames from left to
+  // right. Also, each frame is assumed to be square (width == height).
+  int frame_width = bitmap.height();
+  int frame_height = frame_width;
+  int total_width = bitmap.width();
+  DCHECK_EQ(total_width % frame_width, 0);
+  int frame_count = total_width / frame_width;
+  DCHECK_GT(frame_count, 0);
+
+  bitmaps->resize(frame_count);
+
+  for (int frame = 0; frame < frame_count; ++frame) {
+    int x_offset = frame_width * frame;
+    DCHECK_LE(x_offset + frame_width, total_width);
+
+    SkBitmap cropped = SkBitmapOperations::CreateTiledBitmap(
+        bitmap, x_offset, 0, frame_width, frame_height);
+    DCHECK_EQ(frame_width, cropped.width());
+    DCHECK_EQ(frame_height, cropped.height());
+
+    (*bitmaps)[frame] = cropped;
+  }
+}
+
 }  // namespace
 
+absl::optional<ui::CursorData> GetCursorData(
+    CursorType type,
+    ui::CursorSize size,
+    float scale,
+    display::Display::Rotation rotation) {
+  DCHECK_NE(type, CursorType::kNone);
+  DCHECK_NE(type, CursorType::kCustom);
+
+  int resource_id;
+  gfx::Point hotspot;
+  if (!GetCursorDataFor(size, type, scale, &resource_id, &hotspot)) {
+    return absl::nullopt;
+  }
+
+  std::vector<SkBitmap> bitmaps;
+  if (base::ranges::count(kAnimatedCursorTypes, type) == 0) {
+    SkBitmap bitmap;
+    GetImageCursorBitmap(resource_id, scale, rotation, &hotspot, &bitmap);
+    bitmaps.push_back(std::move(bitmap));
+  } else {
+    GetAnimatedCursorBitmaps(resource_id, scale, rotation, &hotspot, &bitmaps);
+  }
+  return ui::CursorData(std::move(bitmaps), std::move(hotspot));
+}
+
 void ScaleAndRotateCursorBitmapAndHotpoint(float scale,
                                            display::Display::Rotation rotation,
                                            SkBitmap* bitmap,
@@ -109,55 +194,4 @@
   *hotpoint = gfx::ScaleToFlooredPoint(*hotpoint, scale);
 }
 
-void GetImageCursorBitmap(int resource_id,
-                          float scale,
-                          display::Display::Rotation rotation,
-                          gfx::Point* hotspot,
-                          SkBitmap* bitmap) {
-  const gfx::ImageSkia* image =
-      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
-  const gfx::ImageSkiaRep& image_rep = image->GetRepresentation(scale);
-  // TODO(oshima): The cursor should use resource scale factor when
-  // fractional scale factor is enabled. crbug.com/372212
-  (*bitmap) = image_rep.GetBitmap();
-  ScaleAndRotateCursorBitmapAndHotpoint(
-      scale / image_rep.scale(), rotation, bitmap, hotspot);
-  // |image_rep| is owned by the resource bundle. So we do not need to free it.
-}
-
-void GetAnimatedCursorBitmaps(int resource_id,
-                              float scale,
-                              display::Display::Rotation rotation,
-                              gfx::Point* hotspot,
-                              std::vector<SkBitmap>* bitmaps) {
-  // TODO(oshima|tdanderson): Support rotation and fractional scale factor.
-  const gfx::ImageSkia* image =
-      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
-  const gfx::ImageSkiaRep& image_rep = image->GetRepresentation(scale);
-  SkBitmap bitmap = image_rep.GetBitmap();
-
-  // The image is assumed to be a concatenation of animation frames from left to
-  // right. Also, each frame is assumed to be square (width == height).
-  int frame_width = bitmap.height();
-  int frame_height = frame_width;
-  int total_width = bitmap.width();
-  DCHECK_EQ(total_width % frame_width, 0);
-  int frame_count = total_width / frame_width;
-  DCHECK_GT(frame_count, 0);
-
-  bitmaps->resize(frame_count);
-
-  for (int frame = 0; frame < frame_count; ++frame) {
-    int x_offset = frame_width * frame;
-    DCHECK_LE(x_offset + frame_width, total_width);
-
-    SkBitmap cropped = SkBitmapOperations::CreateTiledBitmap(
-        bitmap, x_offset, 0, frame_width, frame_height);
-    DCHECK_EQ(frame_width, cropped.width());
-    DCHECK_EQ(frame_height, cropped.height());
-
-    (*bitmaps)[frame] = cropped;
-  }
-}
-
 }  // namespace wm
diff --git a/ui/wm/core/cursor_util.h b/ui/wm/core/cursor_util.h
index fc71e4a..922641a 100644
--- a/ui/wm/core/cursor_util.h
+++ b/ui/wm/core/cursor_util.h
@@ -5,9 +5,9 @@
 #ifndef UI_WM_CORE_CURSOR_UTIL_H_
 #define UI_WM_CORE_CURSOR_UTIL_H_
 
-#include <vector>
-
 #include "base/component_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
 #include "ui/display/display.h"
 
 class SkBitmap;
@@ -16,8 +16,20 @@
 class Point;
 }
 
+namespace ui {
+enum class CursorSize;
+struct CursorData;
+}  // namespace ui
+
 namespace wm {
 
+COMPONENT_EXPORT(UI_WM)
+absl::optional<ui::CursorData> GetCursorData(
+    ui::mojom::CursorType id,
+    ui::CursorSize size,
+    float scale,
+    display::Display::Rotation rotation);
+
 // Scale and rotate the cursor's bitmap and hotpoint.
 // |bitmap_in_out| and |hotpoint_in_out| are used as
 // both input and output.
@@ -27,18 +39,6 @@
                                            SkBitmap* bitmap_in_out,
                                            gfx::Point* hotpoint_in_out);
 
-// Helpers for CursorLoader.
-void GetImageCursorBitmap(int resource_id,
-                          float scale,
-                          display::Display::Rotation rotation,
-                          gfx::Point* hotspot,
-                          SkBitmap* bitmap);
-void GetAnimatedCursorBitmaps(int resource_id,
-                              float scale,
-                              display::Display::Rotation rotation,
-                              gfx::Point* hotspot,
-                              std::vector<SkBitmap>* bitmaps);
-
 }  // namespace wm
 
 #endif  // UI_WM_CORE_CURSOR_UTIL_H_
diff --git a/ui/wm/core/cursor_util_unittest.cc b/ui/wm/core/cursor_util_unittest.cc
index 9c1b819..c8971d65 100644
--- a/ui/wm/core/cursor_util_unittest.cc
+++ b/ui/wm/core/cursor_util_unittest.cc
@@ -5,12 +5,19 @@
 #include "ui/wm/core/cursor_util.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/cursor/cursor.h"
+#include "ui/base/cursor/cursor_size.h"
+#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
+#include "ui/display/display.h"
 #include "ui/gfx/geometry/point.h"
 
 namespace wm {
 namespace {
 
+using ::ui::mojom::CursorType;
+
 // Parameterized test for cursor bitmaps with premultiplied and unpremultiplied
 // alpha.
 class CursorUtilTest : public testing::TestWithParam<bool> {
@@ -66,5 +73,23 @@
 
 INSTANTIATE_TEST_SUITE_P(All, CursorUtilTest, testing::Bool());
 
+TEST(CursorUtil, GetCursorData) {
+  const auto kDefaultSize = ui::CursorSize::kNormal;
+  const float kDefaultScale = 1.0f;
+  const auto kDefaultRotation = display::Display::ROTATE_0;
+
+  const auto pointer_cursor_data = GetCursorData(
+      CursorType::kPointer, kDefaultSize, kDefaultScale, kDefaultRotation);
+  ASSERT_TRUE(pointer_cursor_data);
+  EXPECT_EQ(pointer_cursor_data->bitmaps.size(), 1u);
+  EXPECT_FALSE(pointer_cursor_data->hotspot.IsOrigin());
+
+  const auto wait_cursor_data = GetCursorData(CursorType::kWait, kDefaultSize,
+                                              kDefaultScale, kDefaultRotation);
+  ASSERT_TRUE(wait_cursor_data);
+  EXPECT_GT(wait_cursor_data->bitmaps.size(), 1u);
+  EXPECT_FALSE(wait_cursor_data->hotspot.IsOrigin());
+}
+
 }  // namespace
 }  // namespace wm
diff --git a/ui/wm/core/cursors_aura.cc b/ui/wm/core/cursors_aura.cc
index 3c8604d9..0dc6882 100644
--- a/ui/wm/core/cursors_aura.cc
+++ b/ui/wm/core/cursors_aura.cc
@@ -4,25 +4,12 @@
 
 #include "ui/wm/core/cursors_aura.h"
 
-#include <stddef.h>
-
-#include "build/build_config.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/base/cursor/cursor.h"
 #include "ui/base/cursor/cursor_size.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/geometry/point.h"
-#include "ui/gfx/image/image_skia.h"
-#include "ui/gfx/image/image_skia_rep.h"
 #include "ui/resources/grit/ui_resources.h"
 
-#if BUILDFLAG(IS_WIN)
-#include "ui/base/win/win_cursor.h"
-#include "ui/gfx/icon_util.h"
-#include "ui/wm/core/cursor_loader.h"
-#endif
-
 namespace wm {
 
 namespace {
@@ -282,7 +269,7 @@
       return &kCursorSizes[i];
   }
 
-  return NULL;
+  return nullptr;
 }
 
 bool SearchTable(const CursorData* table,
@@ -329,43 +316,4 @@
                      resource_id, point);
 }
 
-SkBitmap GetDefaultBitmap(const ui::Cursor& cursor) {
-#if BUILDFLAG(IS_WIN)
-  ui::Cursor cursor_copy = cursor;
-  CursorLoader cursor_loader;
-  cursor_loader.SetPlatformCursor(&cursor_copy);
-  return IconUtil::CreateSkBitmapFromHICON(
-      ui::WinCursor::FromPlatformCursor(cursor_copy.platform())->hcursor());
-#else
-  int resource_id;
-  gfx::Point hotspot;
-  if (!GetCursorDataFor(ui::CursorSize::kNormal, cursor.type(),
-                        cursor.image_scale_factor(), &resource_id, &hotspot)) {
-    return SkBitmap();
-  }
-  return ui::ResourceBundle::GetSharedInstance()
-      .GetImageSkiaNamed(resource_id)
-      ->GetRepresentation(cursor.image_scale_factor())
-      .GetBitmap();
-#endif
-}
-
-gfx::Point GetDefaultHotspot(const ui::Cursor& cursor) {
-#if BUILDFLAG(IS_WIN)
-  ui::Cursor cursor_copy = cursor;
-  CursorLoader cursor_loader;
-  cursor_loader.SetPlatformCursor(&cursor_copy);
-  return IconUtil::GetHotSpotFromHICON(
-      ui::WinCursor::FromPlatformCursor(cursor_copy.platform())->hcursor());
-#else
-  int resource_id;
-  gfx::Point hotspot;
-  if (!GetCursorDataFor(ui::CursorSize::kNormal, cursor.type(),
-                        cursor.image_scale_factor(), &resource_id, &hotspot)) {
-    return gfx::Point();
-  }
-  return hotspot;
-#endif
-}
-
 }  // namespace wm
diff --git a/ui/wm/core/cursors_aura.h b/ui/wm/core/cursors_aura.h
index d1f89de..a40bc4b 100644
--- a/ui/wm/core/cursors_aura.h
+++ b/ui/wm/core/cursors_aura.h
@@ -8,16 +8,13 @@
 #include "base/component_export.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-forward.h"
 
-class SkBitmap;
-
 namespace gfx {
 class Point;
 }
 
 namespace ui {
-class Cursor;
 enum class CursorSize;
-}  // namespace ui
+}
 
 namespace wm {
 
@@ -32,12 +29,6 @@
                       int* resource_id,
                       gfx::Point* point);
 
-COMPONENT_EXPORT(UI_WM)
-SkBitmap GetDefaultBitmap(const ui::Cursor& cursor);
-
-COMPONENT_EXPORT(UI_WM)
-gfx::Point GetDefaultHotspot(const ui::Cursor& cursor);
-
 }  // namespace wm
 
 #endif  // UI_WM_CORE_CURSORS_AURA_H_
diff --git a/url/BUILD.gn b/url/BUILD.gn
index 0e4ef8f..5614b464 100644
--- a/url/BUILD.gn
+++ b/url/BUILD.gn
@@ -303,6 +303,7 @@
 
   android_library("android_test_helper_java") {
     testonly = true
+    annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
     sources = [
       "android/javatests/src/org/chromium/url/GURLJavaTestHelper.java",
       "android/javatests/src/org/chromium/url/OriginJavaTestHelper.java",
diff --git a/url/android/javatests/src/org/chromium/url/GURLJavaTestHelper.java b/url/android/javatests/src/org/chromium/url/GURLJavaTestHelper.java
index 74834414..975b009 100644
--- a/url/android/javatests/src/org/chromium/url/GURLJavaTestHelper.java
+++ b/url/android/javatests/src/org/chromium/url/GURLJavaTestHelper.java
@@ -6,6 +6,7 @@
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
 
 /**
  * Helpers for GURLJavaTest that need to call into native code.
@@ -17,6 +18,17 @@
         return new GURL(uri);
     }
 
-    public static native void nativeInitializeICU();
-    public static native void nativeTestGURLEquivalence();
+    public static void nativeInitializeICU() {
+        GURLJavaTestHelperJni.get().initializeICU();
+    }
+
+    public static void nativeTestGURLEquivalence() {
+        GURLJavaTestHelperJni.get().testGURLEquivalence();
+    }
+
+    @NativeMethods
+    interface Natives {
+        void initializeICU();
+        void testGURLEquivalence();
+    }
 }
diff --git a/url/android/javatests/src/org/chromium/url/OriginJavaTest.java b/url/android/javatests/src/org/chromium/url/OriginJavaTest.java
index d32318f..3a4665a 100644
--- a/url/android/javatests/src/org/chromium/url/OriginJavaTest.java
+++ b/url/android/javatests/src/org/chromium/url/OriginJavaTest.java
@@ -32,7 +32,7 @@
     @SmallTest
     @Test
     public void testOriginEquivalence() {
-        OriginJavaTestHelper.nativeTestOriginEquivalence();
+        OriginJavaTestHelper.testOriginEquivalence();
     }
 
     @SmallTest
diff --git a/url/android/javatests/src/org/chromium/url/OriginJavaTestHelper.java b/url/android/javatests/src/org/chromium/url/OriginJavaTestHelper.java
index d6a361e..2eb9550 100644
--- a/url/android/javatests/src/org/chromium/url/OriginJavaTestHelper.java
+++ b/url/android/javatests/src/org/chromium/url/OriginJavaTestHelper.java
@@ -5,11 +5,19 @@
 package org.chromium.url;
 
 import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
 
 /**
  * Helpers for OriginJavaTest that need to call into native code.
  */
 @JNINamespace("url")
 public class OriginJavaTestHelper {
-    public static native void nativeTestOriginEquivalence();
+    public static void testOriginEquivalence() {
+        OriginJavaTestHelperJni.get().testOriginEquivalence();
+    }
+
+    @NativeMethods
+    interface Natives {
+        void testOriginEquivalence();
+    }
 }