diff --git a/AUTHORS b/AUTHORS
index 594a0df9..78d0d45d 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -725,6 +725,7 @@
 Josh Triplett <josh.triplett@intel.com>
 Josh Triplett <josh@joshtriplett.org>
 Joshua Lock <joshua.lock@intel.com>
+Joshua Olaoye <joshuaolaoye46@gmail.com>
 Joshua Roesslein <jroesslein@gmail.com>
 Josué Ratelle <jorat1346@gmail.com>
 Josyula Venkat Narasimham <venkat.nj@samsung.com>
diff --git a/DEPS b/DEPS
index efcfd7c..f33ffea 100644
--- a/DEPS
+++ b/DEPS
@@ -276,19 +276,19 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'src_internal_revision': '1f13466bea73c6280adba142e7bed8f95d04499b',
+  'src_internal_revision': '6f4b9ae57761436c222a02facc36f260e7b08ed8',
   # 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': '477c83cf10f8323dcedbab72185db74d8292e505',
+  'skia_revision': '77524387094192e4639253eeabca6ed3fb46dfc0',
   # 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': 'd1e6b9bb90ea666c31170f6e6688d7d5fc3690e2',
+  'v8_revision': '77ca46aba3bd91f1cc8d43051ab651747b10242c',
   # 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': '6b6837324b784c4c68408606af2cdb6930166186',
+  'angle_revision': '95756ae2acbe88a57cc33cff02eeb5e7eb127876',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -300,7 +300,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
-  'boringssl_revision': '9559c4566a6d12194c42db5f3dbbcb5de35cfec2',
+  'boringssl_revision': 'b6eec48a579eff1abe70ce6d480a017d6ca3a32c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Fuchsia sdk
   # and whatever else without interference from each other.
@@ -348,7 +348,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '4899cc831cb18f58428eca4e2467c40e5f452dee',
+  'catapult_revision': '350ba7c712c9e1af86954eea7db34d2a6fad294c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling chromium_variations
   # and whatever else without interference from each other.
@@ -356,7 +356,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling CrossBench
   # and whatever else without interference from each other.
-  'crossbench_revision': '64db7a195af090ae97ef2803b1a76c5741b10e4b',
+  'crossbench_revision': '93a7369e66a419ceede2a0124d95d42243533832',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -372,7 +372,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': '426f32c6fba501cb47b7086c3574ab69402c0995',
+  'devtools_frontend_revision': '3c18d9b9ab9158565e4378e9899f66b020030b63',
   # 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.
@@ -396,7 +396,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '22a8762fea90d2d9fbfc592d2bf2a438b66f22f4',
+  'dawn_revision': 'bb1dbd8ad562999d1e142b519d49075ae9bc0253',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -428,7 +428,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling crabbyavif
   # and whatever else without interference from each other.
-  'crabbyavif_revision': 'c3548280e0a516ed7cad7ff1591b5807cef64aa4',
+  'crabbyavif_revision': '879ca873d6648a01de65e4cb0b86336b581aa513',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Speedometer v3.0
   # and whatever else without interference from each other.
@@ -468,7 +468,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'libcxxabi_revision':    '1bf83572723e3cb921345f9f80d1e462c4b9745b',
+  'libcxxabi_revision':    '61ad6ef5b6c7ac8328370742323f171dd42ae7c8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -496,11 +496,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling llvm-libc
   # and whatever else without interference from each other.
-  'llvm_libc_revision':    'ab4e0ad95354c43a8afbcb3f19b4bee6066a90c5',
+  'llvm_libc_revision':    '4d75039545cf1c121eddfb9636e4d19dfbb7fe29',
 
   # If you change this, also update the libc++ revision in
   # //buildtools/deps_revisions.gni.
-  'libcxx_revision':       '619ccf05152d4612fac76ba5899094704f3661dd',
+  'libcxx_revision':       '60a3e1838767d557822e90f2671135a79a62c5d0',
 
   # GN CIPD package version.
   'gn_version': 'git_revision:468c6128db7fabe32a29d4753460ef53594406fc',
@@ -1304,7 +1304,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    'b043bc0a6aded7bdc2d9633940caeeafa3c7f42c',
+    '21940795d0716914166441b2043aae2ec64086f1',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -1463,7 +1463,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'w6ABIi35Hbkb4RHJCx4sSWDpt7W9rBvJFkcPVufgZMIC',
+          'version': 'htV4MvGlfVbpqGSk_BC6R-OR2p5JKa7M1TmDGgIgSioC',
       },
     ],
     'condition': 'checkout_android and non_git_source',
@@ -1534,7 +1534,7 @@
       'packages': [
           {
                'package': 'chromium/third_party/android_build_tools/error_prone',
-               'version': 'ClNqEKjHuNFTgplEe3HujivpADFDjRs0H0ijhyVUg2gC',
+               'version': 'AYoMbR1EWdl0sGTYnDZkWcRZOQnKpArFh-Mq-qpoq3gC',
           },
       ],
       'condition': 'checkout_android and non_git_source',
@@ -1556,7 +1556,7 @@
       'packages': [
           {
                'package': 'chromium/third_party/android_build_tools/lint',
-               'version': 'cT8yPkyndEa0cfkhFyY2CeNOFEeA970ZXJtbtfU_QhcC',
+               'version': 'ogvoJt-5sfVvPmkufyujLCkY4ZsHBN3VIirNJGSH0mUC',
           },
       ],
       'condition': 'checkout_android and non_git_source',
@@ -1567,7 +1567,7 @@
       'packages': [
           {
                'package': 'chromium/third_party/android_build_tools/manifest_merger',
-               'version': 'ltqylfWRbafoft_Pjhfb4NciQwCb3J4PAkpcTZA7lW0C',
+               'version': 'hyODeowQwjjxMHe11I3-FOtBGbTg6MQdr3Uh9ZUUHA4C',
           },
       ],
       'condition': 'checkout_android and non_git_source',
@@ -1805,7 +1805,7 @@
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '428d340fc49509e0ce9bf58048c6f258ace6b260',
+      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + 'd568021d39553f3923662cb2e7badb114fea980b',
     'condition': 'checkout_src_internal',
   },
 
@@ -2012,7 +2012,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/jdk',
-              'version': 'U-h0kbYoIUjL__n_sfiudzFLH7-C9vKVsLSOA2XHkBEC',
+              'version': 'G-WIGWdFIBTPPhv2xPK_lTfI5N7WmfCBh0oTKqX-c5sC',
           },
       ],
       # Needed on Linux for use on chromium_presubmit (for checkstyle).
@@ -2046,7 +2046,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/kotlin_stdlib',
-              'version': 'O9XlYa2GU1tlWmQ40OrK2Bekxjt372NtG5pMD-QyNaYC',
+              'version': 'VqqnQS2oBxM8b3Q7CDJaGfa-QQoOPx9weNRX1avHGNoC',
           },
       ],
       'condition': 'checkout_android and non_git_source',
@@ -2280,7 +2280,7 @@
     Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '478e5ab3eca30e600006d5a0a08b176fd34d3bd1',
 
   'src/third_party/openscreen/src':
-    Var('chromium_git') + '/openscreen' + '@' + '36b3244c4fa36166c3f165a79826a2dcc8011c2e',
+    Var('chromium_git') + '/openscreen' + '@' + '6b69ff0c0eb4ac177ea2971088e756b6be3391b2',
 
   'src/third_party/openxr/src': {
     'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '781f2eab3698d653c804ecbd11e0aed47eaad1c6',
@@ -2306,7 +2306,7 @@
     Var('pdfium_git') + '/pdfium.git' + '@' +  Var('pdfium_revision'),
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'd3990a1c9d27761d8de4290aeadb879a60ecbc90',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '1a0d053d2f0d440bd8cfd1fc6421bccd63dd4041',
 
   'src/base/tracing/test/data': {
     'bucket': 'perfetto',
@@ -2422,7 +2422,14 @@
         'size_bytes': 18887098,
         'generation': 1730148514067154,
         'output_file': 'scroll_m132_with_atrace.pftrace'
-      }
+      },
+      {
+        'object_name': 'test_data/scroll_with_input_not_forwarded_to_renderer.pftrace-ceb2ff3cb64c99ddb28a29867bc82f1491c4b413bfacd8638551b80936240faf',
+        'sha256sum': 'ceb2ff3cb64c99ddb28a29867bc82f1491c4b413bfacd8638551b80936240faf',
+        'size_bytes': 729606,
+        'generation': 1732902685002882,
+        'output_file': 'scroll_with_input_not_forwarded_to_renderer.pftrace'
+      },
     ],
     'dep_type': 'gcs'
   },
@@ -2481,7 +2488,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/r8',
-              'version': 'hmRsAQA2HG0DR196Odv3OKZYk-2Ul43tCtzrCyfWpEQC',
+              'version': 'BkjdEJg2icSYHSYeOMbEI4Kf_1Zn4-fkpg6vqgvFkAEC',
           },
       ],
       'condition': 'checkout_android and non_git_source',
@@ -2667,7 +2674,7 @@
     Var('chromium_git') + '/webpagereplay.git' + '@' + Var('webpagereplay_revision'),
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '2ca8f15991ba593509aae828d8ab28cb763ee1a1',
+    Var('webrtc_git') + '/src.git' + '@' + '93f5f9e8677d61eff3e8669ade6224195a421ebf',
 
   # Wuffs' canonical repository is at github.com/google/wuffs, but we use
   # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file.
@@ -2804,7 +2811,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': '_E_lCXluW4-iKUy6rGLqqrEf2VTo3LQu5VHGND0Mq1AC',
+        'version': '9RMYLuakWu97IKHukfXlKD-VYbEKRN4kFu_pRD9eoiIC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -2815,7 +2822,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'I5Wah9phv0ti6aSUPUIpIPodApvjXQNby42zp1CvPl8C',
+        'version': 'L2iAuTSjceNIbqsI5sppJ5LSno52tg1IFH49doWkQQkC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -4407,7 +4414,7 @@
 
   'src/components/optimization_guide/internal': {
       'url': Var('chrome_git') + '/chrome/components/optimization_guide.git' + '@' +
-        'a60bdae9e30c3d6090711ab3d76e79fb3652fa0c',
+        'fe7e9f241e165bb9fada55d320b6646e6ffa4a5f',
       'condition': 'checkout_src_internal',
   },
 
@@ -4473,7 +4480,7 @@
 
   'src/ios_internal':  {
       'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' +
-        '6291d21f3b65625b40e468f413e4d4671a264163',
+        '0ab8b51d63a6a0a658d209f18df69058aa201007',
       'condition': 'checkout_ios and checkout_src_internal',
   },
 
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 21df42b..3a62b69 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -833,9 +833,6 @@
              "FastPairHandshakeLongTermRefactor",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-// Enables prototype support for Fast Pair HID (non-keyboard).
-BASE_FEATURE(kFastPairHID, "FastPairHID", base::FEATURE_ENABLED_BY_DEFAULT);
-
 // Enables prototype support for Fast Pair for keyboards.
 BASE_FEATURE(kFastPairKeyboards,
              "FastPairKeyboards",
@@ -3401,10 +3398,6 @@
   return base::FeatureList::IsEnabled(kCaptureModeEducationBypassLimits);
 }
 
-bool IsChangePasswordFactorSetupEnabled() {
-  return base::FeatureList::IsEnabled(kChangePasswordFactorSetup);
-}
-
 bool IsCheckPasswordsAgainstCryptohomeHelperEnabled() {
   return base::FeatureList::IsEnabled(kCheckPasswordsAgainstCryptohomeHelper);
 }
@@ -3576,10 +3569,6 @@
   return base::FeatureList::IsEnabled(kFastPairHandshakeLongTermRefactor);
 }
 
-bool IsFastPairHIDEnabled() {
-  return base::FeatureList::IsEnabled(kFastPairHID);
-}
-
 bool IsFastPairKeyboardsEnabled() {
   return base::FeatureList::IsEnabled(kFastPairKeyboards);
 }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index f9cdaca..c1d0a7f 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -268,8 +268,6 @@
 COMPONENT_EXPORT(ASH_CONSTANTS)
 BASE_DECLARE_FEATURE(kFastPairHandshakeLongTermRefactor);
 COMPONENT_EXPORT(ASH_CONSTANTS)
-BASE_DECLARE_FEATURE(kFastPairHID);
-COMPONENT_EXPORT(ASH_CONSTANTS)
 BASE_DECLARE_FEATURE(kFastPairKeyboards);
 COMPONENT_EXPORT(ASH_CONSTANTS)
 BASE_DECLARE_FEATURE(kFastPairSavedDevicesNicknames);
@@ -1052,8 +1050,6 @@
 COMPONENT_EXPORT(ASH_CONSTANTS)
 bool IsCaptureModeEducationBypassLimitsEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS)
-bool IsChangePasswordFactorSetupEnabled();
-COMPONENT_EXPORT(ASH_CONSTANTS)
 bool IsCheckPasswordsAgainstCryptohomeHelperEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsClipboardHistoryLongpressEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsClipboardHistoryUrlTitlesEnabled();
@@ -1101,7 +1097,6 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFastPairHandshakeRefactorEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS)
 bool IsFastPairHandshakeLongTermRefactorEnabled();
-COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFastPairHIDEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFastPairKeyboardsEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFastPairSavedDevicesNicknamesEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFastPairPwaCompanionEnabled();
diff --git a/ash/constants/ash_switches.cc b/ash/constants/ash_switches.cc
index 7db3af2..863d159 100644
--- a/ash/constants/ash_switches.cc
+++ b/ash/constants/ash_switches.cc
@@ -792,28 +792,6 @@
 // When this flag is set, the lacros-availability policy is ignored.
 const char kLacrosAvailabilityIgnore[] = "lacros-availability-ignore";
 
-// If this switch is set, then ash-chrome will pass additional arguments when
-// launching lacros-chrome. The string '####' is used as a delimiter. Example:
-// --lacros-chrome-additional-args="--foo=5####--bar=/tmp/dir name". Will
-// result in two arguments passed to lacros-chrome:
-//   --foo=5
-//   --bar=/tmp/dir name
-const char kLacrosChromeAdditionalArgs[] = "lacros-chrome-additional-args";
-
-// If this switch is set, then ash-chrome will read from the provided path
-// and pass additional arguments when launching lacros-chrome. Each non-empty
-// line in the file will be treated as an argument. Example file contents:
-//   --foo=5
-//   --bar=/tmp/dir name
-const char kLacrosChromeAdditionalArgsFile[] =
-    "lacros-chrome-additional-args-file";
-
-// Additional environment variables set for lacros-chrome. The string '####' is
-// used as a delimiter. For example:
-// --lacros-chrome-additional-env=WAYLAND_DEBUG=client####FOO=bar
-// will enable Wayland protocol logging and set FOO=bar.
-const char kLacrosChromeAdditionalEnv[] = "lacros-chrome-additional-env";
-
 // If this switch is set, then ash-chrome will exec the lacros-chrome binary
 // from the indicated path rather than from component updater. Note that the
 // path should be to a directory that contains a binary named 'chrome'.
diff --git a/ash/constants/ash_switches.h b/ash/constants/ash_switches.h
index 0c7dcb9b..50190539 100644
--- a/ash/constants/ash_switches.h
+++ b/ash/constants/ash_switches.h
@@ -253,10 +253,6 @@
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const char kKioskSplashScreenMinTimeSeconds[];
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kLacrosAvailabilityIgnore[];
-COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kLacrosChromeAdditionalArgs[];
-COMPONENT_EXPORT(ASH_CONSTANTS)
-extern const char kLacrosChromeAdditionalArgsFile[];
-COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kLacrosChromeAdditionalEnv[];
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kLacrosChromePath[];
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const char kLacrosSelectionPolicyIgnore[];
diff --git a/ash/quick_pair/pairing/retroactive_pairing_detector_impl.cc b/ash/quick_pair/pairing/retroactive_pairing_detector_impl.cc
index 483b710..68f6f34 100644
--- a/ash/quick_pair/pairing/retroactive_pairing_detector_impl.cc
+++ b/ash/quick_pair/pairing/retroactive_pairing_detector_impl.cc
@@ -245,12 +245,10 @@
 
   CD_LOG(VERBOSE, Feature::FP) << __func__ << ": device = " << classic_address;
 
-  // For BLE devices, check it supports Fast Pair. Then, since the message
-  // stream is optional for BLE HIDs, and the BLE address is already known, the
-  // only remaining parameter needed is the model ID, which we retrieve via GATT
-  // characteristic.
-  if (ash::features::IsFastPairHIDEnabled() &&
-      // Fast Pair HID only works on Floss.
+  // For BLE devices, since the message stream is optional for BLE HIDs, and the
+  // BLE address is already known, the only remaining parameter needed is the
+  // model ID, which we retrieve via GATT characteristic.
+  if (  // Fast Pair HID only works on Floss.
       floss::features::IsFlossEnabled() &&
       device->GetType() == device::BLUETOOTH_TRANSPORT_LE &&
       base::Contains(device->GetUUIDs(), kFastPairBluetoothUuid)) {
diff --git a/ash/quick_pair/pairing/retroactive_pairing_detector_unittest.cc b/ash/quick_pair/pairing/retroactive_pairing_detector_unittest.cc
index 297f652..faa8242 100644
--- a/ash/quick_pair/pairing/retroactive_pairing_detector_unittest.cc
+++ b/ash/quick_pair/pairing/retroactive_pairing_detector_unittest.cc
@@ -2153,7 +2153,6 @@
   feature_list.InitWithFeatures(
       /*enabled_features=*/{features::kFastPairSavedDevices,
                             features::kFastPairSavedDevicesStrictOptIn,
-                            features::kFastPairHID,
                             floss::features::kFlossEnabled},
       /*disabled_features=*/{});
   fast_pair_repository_->SetOptInStatus(
@@ -2181,7 +2180,6 @@
   feature_list.InitWithFeatures(
       /*enabled_features=*/{features::kFastPairSavedDevices,
                             features::kFastPairSavedDevicesStrictOptIn,
-                            features::kFastPairHID,
                             floss::features::kFlossEnabled},
       /*disabled_features=*/{});
   fast_pair_repository_->SetOptInStatus(
@@ -2209,7 +2207,6 @@
   feature_list.InitWithFeatures(
       /*enabled_features=*/{features::kFastPairSavedDevices,
                             features::kFastPairSavedDevicesStrictOptIn,
-                            features::kFastPairHID,
                             floss::features::kFlossEnabled},
       /*disabled_features=*/{});
   fast_pair_repository_->SetOptInStatus(
@@ -2235,7 +2232,6 @@
   feature_list.InitWithFeatures(
       /*enabled_features=*/{features::kFastPairSavedDevices,
                             features::kFastPairSavedDevicesStrictOptIn,
-                            features::kFastPairHID,
                             floss::features::kFlossEnabled},
       /*disabled_features=*/{});
   fast_pair_repository_->SetOptInStatus(
diff --git a/ash/quick_pair/scanning/fast_pair/fast_pair_discoverable_scanner_impl.cc b/ash/quick_pair/scanning/fast_pair/fast_pair_discoverable_scanner_impl.cc
index b7ebbdd..8cae2189 100644
--- a/ash/quick_pair/scanning/fast_pair/fast_pair_discoverable_scanner_impl.cc
+++ b/ash/quick_pair/scanning/fast_pair/fast_pair_discoverable_scanner_impl.cc
@@ -52,8 +52,7 @@
 bool IsValidDeviceType(const nearby::fastpair::Device& device) {
   // Fast Pair HID only works on Floss.
   if (floss::features::IsFlossEnabled()) {
-    if (ash::features::IsFastPairHIDEnabled() &&
-        device.device_type() == nearby::fastpair::DeviceType::MOUSE) {
+    if (device.device_type() == nearby::fastpair::DeviceType::MOUSE) {
       return true;
     }
     if (ash::features::IsFastPairKeyboardsEnabled() &&
diff --git a/ash/quick_pair/scanning/fast_pair/fast_pair_discoverable_scanner_impl_unittest.cc b/ash/quick_pair/scanning/fast_pair/fast_pair_discoverable_scanner_impl_unittest.cc
index f71abe3..b83a25e 100644
--- a/ash/quick_pair/scanning/fast_pair/fast_pair_discoverable_scanner_impl_unittest.cc
+++ b/ash/quick_pair/scanning/fast_pair/fast_pair_discoverable_scanner_impl_unittest.cc
@@ -379,9 +379,6 @@
 
 TEST_F(FastPairDiscoverableScannerImplTest, MouseDisallowedWhenHIDDisabled) {
   base::test::ScopedFeatureList feature_list;
-  feature_list.InitWithFeatures(
-      /*enabled_features=*/{},
-      /*disabled_features=*/{features::kFastPairHID});
   nearby::fastpair::Device metadata;
   nearby::fastpair::Status* status = metadata.mutable_status();
   status->set_status_type(nearby::fastpair::StatusType::PUBLISHED);
@@ -398,8 +395,7 @@
 TEST_F(FastPairDiscoverableScannerImplTest, MouseAllowedWhenHIDEnabled) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
-      /*enabled_features=*/{features::kFastPairHID,
-                            floss::features::kFlossEnabled},
+      /*enabled_features=*/{floss::features::kFlossEnabled},
       /*disabled_features=*/{});
   nearby::fastpair::Device metadata;
   nearby::fastpair::Status* status = metadata.mutable_status();
diff --git a/ash/session/test_pref_service_provider.cc b/ash/session/test_pref_service_provider.cc
index 54477123..5bedc6e 100644
--- a/ash/session/test_pref_service_provider.cc
+++ b/ash/session/test_pref_service_provider.cc
@@ -46,18 +46,40 @@
 void TestPrefServiceProvider::SetUserPrefs(
     const AccountId& account_id,
     std::unique_ptr<PrefService> pref_service) {
-  const auto pair =
-      user_prefs_map_.emplace(account_id, std::move(pref_service));
-  DCHECK(pair.second);
+  CHECK_EQ(GetUserPrefs(account_id), nullptr);
+
+  user_prefs_map_.emplace(account_id, std::move(pref_service));
+}
+
+void TestPrefServiceProvider::SetUnownedUserPrefs(
+    const AccountId& account_id,
+    raw_ptr<PrefService> unowned_pref_service) {
+  CHECK_EQ(GetUserPrefs(account_id), nullptr);
+
+  unowned_user_prefs_map_.emplace(account_id, std::move(unowned_pref_service));
 }
 
 PrefService* TestPrefServiceProvider::GetUserPrefs(
     const AccountId& account_id) {
   auto it = user_prefs_map_.find(account_id);
-  if (it == user_prefs_map_.end())
-    return nullptr;
+  if (it != user_prefs_map_.end()) {
+    return it->second.get();
+  }
 
-  return it->second.get();
+  auto unowned_it = unowned_user_prefs_map_.find(account_id);
+  if (unowned_it != unowned_user_prefs_map_.end()) {
+    return unowned_it->second.get();
+  }
+
+  return nullptr;
+}
+
+void TestPrefServiceProvider::ClearUnownedUserPrefs(
+    const AccountId& account_id) {
+  auto unowned_it = unowned_user_prefs_map_.find(account_id);
+  CHECK(unowned_it != unowned_user_prefs_map_.end());
+
+  unowned_user_prefs_map_.erase(unowned_it);
 }
 
 }  // namespace ash
diff --git a/ash/session/test_pref_service_provider.h b/ash/session/test_pref_service_provider.h
index 834451ec..c58cf1576 100644
--- a/ash/session/test_pref_service_provider.h
+++ b/ash/session/test_pref_service_provider.h
@@ -8,6 +8,8 @@
 #include <map>
 #include <memory>
 
+#include "base/memory/raw_ptr.h"
+
 class AccountId;
 class PrefService;
 
@@ -35,11 +37,16 @@
   void CreateUserPrefs(const AccountId& account_id);
   void SetUserPrefs(const AccountId& account_id,
                     std::unique_ptr<PrefService> pref_service);
+  void SetUnownedUserPrefs(const AccountId& account_id,
+                           raw_ptr<PrefService> unowned_pref_service);
   PrefService* GetUserPrefs(const AccountId& account_id);
 
+  void ClearUnownedUserPrefs(const AccountId& account_id);
+
  private:
   std::unique_ptr<PrefService> signin_prefs_;
   std::map<AccountId, std::unique_ptr<PrefService>> user_prefs_map_;
+  std::map<AccountId, raw_ptr<PrefService>> unowned_user_prefs_map_;
 };
 
 }  // namespace ash
diff --git a/ash/session/test_session_controller_client.cc b/ash/session/test_session_controller_client.cc
index e4ecfe7..376d5ad 100644
--- a/ash/session/test_session_controller_client.cc
+++ b/ash/session/test_session_controller_client.cc
@@ -50,7 +50,7 @@
     SessionControllerImpl* controller,
     TestPrefServiceProvider* prefs_provider)
     : controller_(controller), prefs_provider_(prefs_provider) {
-  DCHECK(controller_);
+  CHECK(controller_);
   Reset();
 }
 
@@ -139,7 +139,7 @@
 void TestSessionControllerClient::AddUserSession(
     const std::string& display_email,
     user_manager::UserType user_type,
-    bool provide_pref_service,
+    std::optional<bool> provide_pref_service,
     bool is_new_profile,
     const std::string& given_name,
     bool is_account_managed) {
@@ -154,7 +154,7 @@
     const AccountId& account_id,
     const std::string& display_email,
     user_manager::UserType user_type,
-    bool provide_pref_service,
+    std::optional<bool> provide_pref_service,
     bool is_new_profile,
     const std::string& given_name,
     bool is_account_managed) {
@@ -178,8 +178,8 @@
   session.user_info.is_managed = is_account_managed;
   controller_->UpdateUserSession(std::move(session));
 
-  if (provide_pref_service && prefs_provider_ &&
-      !controller_->GetUserPrefServiceForUser(account_id)) {
+  if (provide_pref_service.value_or(default_provide_pref_service_) &&
+      prefs_provider_ && !controller_->GetUserPrefServiceForUser(account_id)) {
     ProvidePrefServiceForUser(account_id);
   }
 
@@ -188,10 +188,10 @@
 
 void TestSessionControllerClient::ProvidePrefServiceForUser(
     const AccountId& account_id) {
-  DCHECK(!controller_->GetUserPrefServiceForUser(account_id));
+  CHECK(!controller_->GetUserPrefServiceForUser(account_id));
+
   prefs_provider_->CreateUserPrefs(account_id);
-  controller_->OnProfilePrefServiceInitialized(
-      account_id, prefs_provider_->GetUserPrefs(account_id));
+  MaybeNotifyUserPrefServiceInitialized(account_id);
 }
 
 void TestSessionControllerClient::LockScreen() {
@@ -217,12 +217,20 @@
 void TestSessionControllerClient::SetUserPrefService(
     const AccountId& account_id,
     std::unique_ptr<PrefService> pref_service) {
-  DCHECK(!controller_->GetUserPrefServiceForUser(account_id));
+  CHECK(!controller_->GetUserPrefServiceForUser(account_id));
+
   prefs_provider_->SetUserPrefs(account_id, std::move(pref_service));
-  if (controller_->IsActiveUserSessionStarted()) {
-    controller_->OnProfilePrefServiceInitialized(
-        account_id, prefs_provider_->GetUserPrefs(account_id));
-  }
+  MaybeNotifyUserPrefServiceInitialized(account_id);
+}
+
+void TestSessionControllerClient::SetUnownedUserPrefService(
+    const AccountId& account_id,
+    raw_ptr<PrefService> unowned_pref_service) {
+  CHECK(!controller_->GetUserPrefServiceForUser(account_id));
+
+  prefs_provider_->SetUnownedUserPrefs(account_id,
+                                       std::move(unowned_pref_service));
+  MaybeNotifyUserPrefServiceInitialized(account_id);
 }
 
 void TestSessionControllerClient::RequestLockScreen() {
@@ -369,4 +377,12 @@
   }
 }
 
+void TestSessionControllerClient::MaybeNotifyUserPrefServiceInitialized(
+    const AccountId& account_id) {
+  if (controller_->IsActiveUserSessionStarted()) {
+    controller_->OnProfilePrefServiceInitialized(
+        account_id, prefs_provider_->GetUserPrefs(account_id));
+  }
+}
+
 }  // namespace ash
diff --git a/ash/session/test_session_controller_client.h b/ash/session/test_session_controller_client.h
index 4bc7230..1aa5167 100644
--- a/ash/session/test_session_controller_client.h
+++ b/ash/session/test_session_controller_client.h
@@ -8,6 +8,7 @@
 #include <stdint.h>
 
 #include <memory>
+#include <optional>
 #include <string>
 
 #include "ash/public/cpp/session/session_controller_client.h"
@@ -97,7 +98,7 @@
   void AddUserSession(
       const std::string& display_email,
       user_manager::UserType user_type = user_manager::UserType::kRegular,
-      bool provide_pref_service = true,
+      std::optional<bool> provide_pref_service = std::nullopt,
       bool is_new_profile = false,
       const std::string& given_name = std::string(),
       bool is_account_managed = false);
@@ -107,7 +108,7 @@
       const AccountId& account_id,
       const std::string& display_email,
       user_manager::UserType user_type = user_manager::UserType::kRegular,
-      bool provide_pref_service = true,
+      std::optional<bool> provide_pref_service = std::nullopt,
       bool is_new_profile = false,
       const std::string& given_name = std::string(),
       bool is_account_managed = false);
@@ -133,6 +134,8 @@
   // Use |pref_service| for the user identified by |account_id|.
   void SetUserPrefService(const AccountId& account_id,
                           std::unique_ptr<PrefService> pref_service);
+  void SetUnownedUserPrefService(const AccountId& account_id,
+                                 raw_ptr<PrefService> unowned_pref_service);
 
   // ash::SessionControllerClient:
   void RequestLockScreen() override;
@@ -167,6 +170,10 @@
     existing_users_count_ = existing_users_count;
   }
 
+  void set_default_provide_pref_service(bool default_provide_pref_service) {
+    default_provide_pref_service_ = default_provide_pref_service;
+  }
+
  private:
   void DoSwitchUser(const AccountId& account_id, bool switch_user);
 
@@ -174,6 +181,9 @@
   // is at least one user session created, and session state is ACTIVE.
   void MaybeNotifyFirstSessionReady();
 
+  // Notify user prefs initialized if user session has started.
+  void MaybeNotifyUserPrefServiceInitialized(const AccountId& account_id);
+
   const raw_ptr<SessionControllerImpl, DanglingUntriaged> controller_;
   const raw_ptr<TestPrefServiceProvider> prefs_provider_;
 
@@ -181,6 +191,10 @@
   SessionInfo session_info_;
   bool first_session_ready_fired_ = false;
 
+  // Whether to auto create user prefs for `AddSession` if
+  // `provide_pref_service` is not specified.
+  bool default_provide_pref_service_ = true;
+
   bool use_lower_case_user_id_ = true;
   int request_hide_lock_screen_count_ = 0;
   int request_sign_out_count_ = 0;
diff --git a/ash/strings/ash_strings_fr-CA.xtb b/ash/strings/ash_strings_fr-CA.xtb
index 2348b0b..bbde249 100644
--- a/ash/strings/ash_strings_fr-CA.xtb
+++ b/ash/strings/ash_strings_fr-CA.xtb
@@ -470,7 +470,7 @@
 <translation id="2645435784669275700">ChromeOS</translation>
 <translation id="2653019840645008922">Capturer la fenêtre</translation>
 <translation id="2653659639078652383">Envoyer</translation>
-<translation id="2658778018866295321">Cliquez et faites glisser</translation>
+<translation id="2658778018866295321">Cliquer et faire glisser</translation>
 <translation id="2665788051462227163"><ph name="UNAVAILABLE_APPS_ONE" /> et <ph name="UNAVAILABLE_APPS_TWO" /> ne sont pas sur cet appareil.</translation>
 <translation id="2670350619068134931">Animations réduites</translation>
 <translation id="2673968385134502798">Jeux</translation>
diff --git a/ash/strings/ash_strings_ka.xtb b/ash/strings/ash_strings_ka.xtb
index e1581df..a6a6bd3 100644
--- a/ash/strings/ash_strings_ka.xtb
+++ b/ash/strings/ash_strings_ka.xtb
@@ -387,6 +387,7 @@
 <translation id="2370971919968699910">ამის გამო, შესაძლოა, მობილური ინტერნეტის საფასურის გადახდა მოგიწიოთ.
 დაკავშირებულია <ph name="DEVICECOUNT" /> მოწყობილობა.</translation>
 <translation id="2386292613071805067">ყველაფრის არჩევა გვერდზე</translation>
+<translation id="2389423187722941333">Gemini-ს გადართვა</translation>
 <translation id="2392659840443812875">ხელმისაწვდომი უსადენო ქსელი არ არის. დარწმუნდით, რომ თქვენი მოწყობილობა ახლოს არის და მასზე ჩართულია Bluetooth.</translation>
 <translation id="2397416548179033562">Chrome-ის მენიუს ჩვენება</translation>
 <translation id="240006516586367791">მედიის მართვის საშუალებები</translation>
diff --git a/ash/strings/ash_strings_lo.xtb b/ash/strings/ash_strings_lo.xtb
index d4449d3..115d5a9 100644
--- a/ash/strings/ash_strings_lo.xtb
+++ b/ash/strings/ash_strings_lo.xtb
@@ -387,6 +387,7 @@
 <translation id="2370971919968699910">ສິ່ງນີ້ອາດມີຄ່າໃຊ້ຈ່າຍຂໍ້ມູນ.
 ເຊື່ອມຕໍ່ <ph name="DEVICECOUNT" /> ອຸປະກອນແລ້ວ.</translation>
 <translation id="2386292613071805067">ເລືອກທຸກຢ່າງໃນໜ້າ</translation>
+<translation id="2389423187722941333">ເປີດ/ປິດ Gemini</translation>
 <translation id="2392659840443812875">ບໍ່ມີຮັອດສະປອດທີ່ໃຊ້ໄດ້. ກວດສອບໃຫ້ແນ່ໃຈວ່າອຸປະກອນຂອງທ່ານຢູ່ໃກ້ຄຽງ ແລະ ເປີດ Bluetooth ຢູ່.</translation>
 <translation id="2397416548179033562">ສະ​ແດງ​ເມ​ນູ​ Chrome</translation>
 <translation id="240006516586367791">ການຄວບຄຸມມີເດຍ</translation>
diff --git a/ash/strings/ash_strings_zh-HK.xtb b/ash/strings/ash_strings_zh-HK.xtb
index 675bef7..89b97279 100644
--- a/ash/strings/ash_strings_zh-HK.xtb
+++ b/ash/strings/ash_strings_zh-HK.xtb
@@ -387,6 +387,7 @@
 <translation id="2370971919968699910">這種情況可能需要支付數據費用。
 已連接 <ph name="DEVICECOUNT" /> 部裝置。</translation>
 <translation id="2386292613071805067">選取頁面上所有內容</translation>
+<translation id="2389423187722941333">切換 Gemini</translation>
 <translation id="2392659840443812875">沒有可用的熱點。請確認裝置在附近且已開啟藍牙。</translation>
 <translation id="2397416548179033562">顯示 Chrome 選單</translation>
 <translation id="240006516586367791">媒體控制項</translation>
diff --git a/ash/strings/ash_strings_zh-TW.xtb b/ash/strings/ash_strings_zh-TW.xtb
index 1d751c9..359c3507 100644
--- a/ash/strings/ash_strings_zh-TW.xtb
+++ b/ash/strings/ash_strings_zh-TW.xtb
@@ -387,6 +387,7 @@
 <translation id="2370971919968699910">這種情況可能需要支付數據傳輸費用。
 已連線到 <ph name="DEVICECOUNT" /> 部裝置。</translation>
 <translation id="2386292613071805067">選取網頁上的所有項目</translation>
+<translation id="2389423187722941333">切換 Gemini</translation>
 <translation id="2392659840443812875">沒有可用的無線基地台。請確認裝置在附近,而且藍牙已開啟。</translation>
 <translation id="2397416548179033562">顯示 Chrome 選單</translation>
 <translation id="240006516586367791">媒體控制項</translation>
diff --git a/ash/system/power/power_button_menu_curtain_view.cc b/ash/system/power/power_button_menu_curtain_view.cc
index 4082ce8..1bc1e4ea 100644
--- a/ash/system/power/power_button_menu_curtain_view.cc
+++ b/ash/system/power/power_button_menu_curtain_view.cc
@@ -61,12 +61,6 @@
 // Line height for the widget content text.
 constexpr int kContentLineHeight = 12;
 
-views::FlexSpecification FullFlex() {
-  return views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToMinimum,
-                                  views::MaximumFlexSizeRule::kUnbounded)
-      .WithWeight(1);
-}
-
 gfx::ImageSkia EnterpriseIcon(const ui::ColorProvider& color_provider) {
   return gfx::CreateVectorIcon(
       chromeos::kEnterpriseIcon,
@@ -140,53 +134,49 @@
 
 void PowerButtonMenuCurtainView::Initialize() {
   Builder<FlexLayoutView>(this)
-      .SetOrientation(views::LayoutOrientation::kHorizontal)
+      .SetOrientation(LayoutOrientation::kVertical)
       .AddChildren(
-          Builder<FlexLayoutView>()
-              .SetOrientation(LayoutOrientation::kVertical)
-              .SetProperty(views::kFlexBehaviorKey, FullFlex())
-              .AddChildren(
-                  // Enterprise icon
-                  Builder<ImageView>()
-                      .SetImageSize(kEnterpriseIconSize)
-                      .SetSize(kEnterpriseIconSize)
-                      .SetHorizontalAlignment(ImageView::Alignment::kLeading)
-                      .SetProperty(views::kFlexBehaviorKey, FullFlex())
-                      .SetProperty(views::kMarginsKey,
-                                   gfx::Insets::TLBR(
-                                       kVerticalPadding, kHorizontalPadding,
-                                       kIconBottomMargin, kHorizontalPadding))
-                      .CopyAddressTo(&enterprise_icon_),
-                  // Title
-                  Builder<views::Label>()
-                      .SetText(TitleText())
-                      .SetTextStyle(views::style::STYLE_EMPHASIZED)
-                      .SetTextContext(views::style::CONTEXT_DIALOG_TITLE)
-                      .SetHorizontalAlignment(
-                          gfx::HorizontalAlignment::ALIGN_LEFT)
-                      .SetMultiLine(true)
-                      .SetProperty(views::kFlexBehaviorKey, FullFlex())
-                      .SetProperty(views::kMarginsKey,
-                                   gfx::Insets::TLBR(0, kHorizontalPadding,
-                                                     kTitleBottomMargin,
-                                                     kHorizontalPadding))
-                      .SetMaximumWidth(kWidth)
-                      .CopyAddressTo(&title_text_),
-                  // Description
-                  Builder<views::Label>()
-                      .SetText(MessageText())
-                      .SetTextContext(views::style::CONTEXT_DIALOG_BODY_TEXT)
-                      .SetHorizontalAlignment(
-                          gfx::HorizontalAlignment::ALIGN_LEFT)
-                      .SetMultiLine(true)
-                      .SetProperty(views::kFlexBehaviorKey, FullFlex())
-                      .SetProperty(views::kMarginsKey,
-                                   gfx::Insets::TLBR(0, kHorizontalPadding,
-                                                     kVerticalPadding,
-                                                     kHorizontalPadding))
-                      .SetLineHeight(kContentLineHeight)
-                      .SetMaximumWidth(kWidth)
-                      .CopyAddressTo(&description_text_)))
+          // Enterprise icon
+          Builder<ImageView>()
+              .SetImageSize(kEnterpriseIconSize)
+              .SetSize(kEnterpriseIconSize)
+              .SetHorizontalAlignment(ImageView::Alignment::kLeading)
+              .SetProperty(
+                  views::kMarginsKey,
+                  gfx::Insets::TLBR(kVerticalPadding, kHorizontalPadding,
+                                    kIconBottomMargin, kHorizontalPadding))
+              .CopyAddressTo(&enterprise_icon_),
+          // Title
+          Builder<views::Label>()
+              .SetText(TitleText())
+              .SetTextStyle(views::style::STYLE_EMPHASIZED)
+              .SetTextContext(views::style::CONTEXT_DIALOG_TITLE)
+              .SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT)
+              .SetMultiLine(true)
+              .SetProperty(
+                  views::kMarginsKey,
+                  gfx::Insets::TLBR(0, kHorizontalPadding, kTitleBottomMargin,
+                                    kHorizontalPadding))
+              .SetMaximumWidth(kWidth)
+              .CopyAddressTo(&title_text_),
+          // Description
+          Builder<views::Label>()
+              .SetText(MessageText())
+              .SetTextContext(views::style::CONTEXT_DIALOG_BODY_TEXT)
+              .SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT)
+              .SetMultiLine(true)
+              .SetProperty(views::kFlexBehaviorKey,
+                           views::FlexSpecification(
+                               views::MinimumFlexSizeRule::kPreferred,
+                               views::MaximumFlexSizeRule::kUnbounded)
+                               .WithWeight(1))
+              .SetProperty(
+                  views::kMarginsKey,
+                  gfx::Insets::TLBR(0, kHorizontalPadding, kVerticalPadding,
+                                    kHorizontalPadding))
+              .SetLineHeight(kContentLineHeight)
+              .SetMaximumWidth(kWidth)
+              .CopyAddressTo(&description_text_))
       .BuildChildren();
 }
 
diff --git a/base/android/java/src/org/chromium/base/BundleUtils.java b/base/android/java/src/org/chromium/base/BundleUtils.java
index e8617fe..29eb49a1 100644
--- a/base/android/java/src/org/chromium/base/BundleUtils.java
+++ b/base/android/java/src/org/chromium/base/BundleUtils.java
@@ -219,23 +219,6 @@
     }
 
     /**
-     * Constructs a new instance of the given class name. If the application context class loader
-     * can load the class, that class loader will be used, otherwise the class loader from the
-     * passed in context will be used.
-     */
-    public static Object newInstance(Context context, String className) {
-        Context appContext = ContextUtils.getApplicationContext();
-        if (appContext != null && canLoadClass(appContext.getClassLoader(), className)) {
-            context = appContext;
-        }
-        try {
-            return context.getClassLoader().loadClass(className).newInstance();
-        } catch (ReflectiveOperationException e) {
-            throw JavaUtils.throwUnchecked(e);
-        }
-    }
-
-    /**
      * Constructs a new instance of the given class name. We create the classloader (or use a cached
      * copy) of the split with the name passed in.
      */
diff --git a/base/containers/fixed_flat_map.h b/base/containers/fixed_flat_map.h
index 62c9c8a..6c05d60 100644
--- a/base/containers/fixed_flat_map.h
+++ b/base/containers/fixed_flat_map.h
@@ -102,7 +102,7 @@
 // Example usage:
 //   constexpr auto kMap = base::MakeFixedFlatMap<std::string_view, int>(
 //       {{"foo", 1}, {"bar", 2}, {"baz", 3}});
-template <class Key, class Mapped, size_t N, class Compare = std::less<>>
+template <class Key, class Mapped, class Compare = std::less<>, size_t N>
 consteval fixed_flat_map<Key, Mapped, N, Compare> MakeFixedFlatMap(
     std::pair<Key, Mapped> (&&data)[N],
     const Compare& comp = Compare()) {
diff --git a/base/containers/fixed_flat_set.h b/base/containers/fixed_flat_set.h
index c6abe915..87b453c 100644
--- a/base/containers/fixed_flat_set.h
+++ b/base/containers/fixed_flat_set.h
@@ -116,7 +116,7 @@
 //
 // Note: Wrapping `Key` in `std::common_type_t` below requires callers to
 // explicitly specify `Key`, which is desired here.
-template <class Key, size_t N, class Compare = std::less<>>
+template <class Key, class Compare = std::less<>, size_t N>
 consteval fixed_flat_set<Key, N, Compare> MakeFixedFlatSet(
     std::common_type_t<Key> (&&data)[N],
     const Compare& comp = Compare()) {
diff --git a/base/debug/proc_maps_linux.cc b/base/debug/proc_maps_linux.cc
index 478e5434..ee1cb6b 100644
--- a/base/debug/proc_maps_linux.cc
+++ b/base/debug/proc_maps_linux.cc
@@ -31,6 +31,10 @@
 MappedMemoryRegion::MappedMemoryRegion() = default;
 MappedMemoryRegion::MappedMemoryRegion(const MappedMemoryRegion&) = default;
 MappedMemoryRegion::MappedMemoryRegion(MappedMemoryRegion&&) noexcept = default;
+MappedMemoryRegion& MappedMemoryRegion::operator=(MappedMemoryRegion&) =
+    default;
+MappedMemoryRegion& MappedMemoryRegion::operator=(
+    MappedMemoryRegion&&) noexcept = default;
 
 // Scans |proc_maps| starting from |pos| returning true if the gate VMA was
 // found, otherwise returns false.
diff --git a/base/debug/proc_maps_linux.h b/base/debug/proc_maps_linux.h
index 2fb43c7b..700db87 100644
--- a/base/debug/proc_maps_linux.h
+++ b/base/debug/proc_maps_linux.h
@@ -27,6 +27,8 @@
   MappedMemoryRegion();
   MappedMemoryRegion(const MappedMemoryRegion&);
   MappedMemoryRegion(MappedMemoryRegion&&) noexcept;
+  MappedMemoryRegion& operator=(MappedMemoryRegion&);
+  MappedMemoryRegion& operator=(MappedMemoryRegion&&) noexcept;
 
   // The address range [start,end) of mapped memory.
   uintptr_t start;
diff --git a/base/functional/callback_helpers.h b/base/functional/callback_helpers.h
index 9b484a0..f1aa11fe 100644
--- a/base/functional/callback_helpers.h
+++ b/base/functional/callback_helpers.h
@@ -16,7 +16,6 @@
 #include <type_traits>
 #include <utility>
 
-#include "base/atomicops.h"
 #include "base/base_export.h"
 #include "base/check.h"
 #include "base/functional/bind.h"
diff --git a/base/lazy_instance_unittest.cc b/base/lazy_instance_unittest.cc
index 89bdd5b4..1055d5d 100644
--- a/base/lazy_instance_unittest.cc
+++ b/base/lazy_instance_unittest.cc
@@ -2,19 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/lazy_instance.h"
+
 #include <stddef.h>
 
+#include <atomic>
 #include <memory>
 #include <utility>
 #include <vector>
 
 #include "base/at_exit.h"
 #include "base/atomic_sequence_num.h"
-#include "base/atomicops.h"
 #include "base/barrier_closure.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
-#include "base/lazy_instance.h"
 #include "base/memory/aligned_memory.h"
 #include "base/memory/raw_ptr.h"
 #include "base/system/sys_info.h"
@@ -208,36 +209,37 @@
  public:
   BlockingConstructor() {
     EXPECT_FALSE(WasConstructorCalled());
-    base::subtle::NoBarrier_Store(&constructor_called_, 1);
+    constructor_called_.store(true, std::memory_order_relaxed);
     EXPECT_TRUE(WasConstructorCalled());
-    while (!base::subtle::NoBarrier_Load(&complete_construction_))
+    while (!complete_construction_.load(std::memory_order_relaxed)) {
       base::PlatformThread::YieldCurrentThread();
+    }
     done_construction_ = true;
   }
   BlockingConstructor(const BlockingConstructor&) = delete;
   BlockingConstructor& operator=(const BlockingConstructor&) = delete;
   ~BlockingConstructor() {
     // Restore static state for the next test.
-    base::subtle::NoBarrier_Store(&constructor_called_, 0);
-    base::subtle::NoBarrier_Store(&complete_construction_, 0);
+    constructor_called_.store(false, std::memory_order_relaxed);
+    complete_construction_.store(false, std::memory_order_relaxed);
   }
 
   // Returns true if BlockingConstructor() was entered.
   static bool WasConstructorCalled() {
-    return base::subtle::NoBarrier_Load(&constructor_called_);
+    return constructor_called_.load(std::memory_order_relaxed);
   }
 
   // Instructs BlockingConstructor() that it may now unblock its construction.
   static void CompleteConstructionNow() {
-    base::subtle::NoBarrier_Store(&complete_construction_, 1);
+    complete_construction_.store(true, std::memory_order_relaxed);
   }
 
   bool done_construction() const { return done_construction_; }
 
  private:
   // Use Atomic32 instead of AtomicFlag for them to be trivially initialized.
-  static base::subtle::Atomic32 constructor_called_;
-  static base::subtle::Atomic32 complete_construction_;
+  static std::atomic<bool> constructor_called_;
+  static std::atomic<bool> complete_construction_;
 
   bool done_construction_ = false;
 };
@@ -269,9 +271,9 @@
 };
 
 // static
-base::subtle::Atomic32 BlockingConstructor::constructor_called_ = 0;
+std::atomic<bool> BlockingConstructor::constructor_called_ = false;
 // static
-base::subtle::Atomic32 BlockingConstructor::complete_construction_ = 0;
+std::atomic<bool> BlockingConstructor::complete_construction_ = false;
 
 base::LazyInstance<BlockingConstructor>::DestructorAtExit lazy_blocking =
     LAZY_INSTANCE_INITIALIZER;
diff --git a/base/no_destructor_unittest.cc b/base/no_destructor_unittest.cc
index 079d2d1..2f21876 100644
--- a/base/no_destructor_unittest.cc
+++ b/base/no_destructor_unittest.cc
@@ -4,12 +4,12 @@
 
 #include "base/no_destructor.h"
 
+#include <atomic>
 #include <memory>
 #include <string>
 #include <utility>
 #include <vector>
 
-#include "base/atomicops.h"
 #include "base/barrier_closure.h"
 #include "base/check.h"
 #include "base/functional/bind.h"
@@ -115,10 +115,11 @@
  public:
   BlockingConstructor() {
     EXPECT_FALSE(WasConstructorCalled());
-    subtle::NoBarrier_Store(&constructor_called_, 1);
+    constructor_called_.store(true, std::memory_order_relaxed);
     EXPECT_TRUE(WasConstructorCalled());
-    while (!subtle::NoBarrier_Load(&complete_construction_))
+    while (!complete_construction_.load(std::memory_order_relaxed)) {
       PlatformThread::YieldCurrentThread();
+    }
     done_construction_ = true;
   }
   BlockingConstructor(const BlockingConstructor&) = delete;
@@ -127,28 +128,27 @@
 
   // Returns true if BlockingConstructor() was entered.
   static bool WasConstructorCalled() {
-    return subtle::NoBarrier_Load(&constructor_called_);
+    return constructor_called_.load(std::memory_order_relaxed);
   }
 
   // Instructs BlockingConstructor() that it may now unblock its construction.
   static void CompleteConstructionNow() {
-    subtle::NoBarrier_Store(&complete_construction_, 1);
+    complete_construction_.store(true, std::memory_order_relaxed);
   }
 
   bool done_construction() const { return done_construction_; }
 
  private:
-  // Use Atomic32 instead of AtomicFlag for them to be trivially initialized.
-  static subtle::Atomic32 constructor_called_;
-  static subtle::Atomic32 complete_construction_;
+  static std::atomic<bool> constructor_called_;
+  static std::atomic<bool> complete_construction_;
 
   bool done_construction_ = false;
 };
 
 // static
-subtle::Atomic32 BlockingConstructor::constructor_called_ = 0;
+std::atomic<bool> BlockingConstructor::constructor_called_ = false;
 // static
-subtle::Atomic32 BlockingConstructor::complete_construction_ = 0;
+std::atomic<bool> BlockingConstructor::complete_construction_ = false;
 
 // A SimpleThread running at |thread_type| which invokes |before_get| (optional)
 // and then invokes thread-safe scoped-static-initializationconstruction on its
diff --git a/base/task/thread_pool/task_tracker.cc b/base/task/thread_pool/task_tracker.cc
index fecb1ca0..36204a77 100644
--- a/base/task/thread_pool/task_tracker.cc
+++ b/base/task/thread_pool/task_tracker.cc
@@ -146,28 +146,25 @@
   // Sets a flag indicating that shutdown has started. Returns true if there are
   // items blocking shutdown. Can only be called once.
   bool StartShutdown() {
-    const auto new_value =
-        subtle::NoBarrier_AtomicIncrement(&bits_, kShutdownHasStartedMask);
-
-    // Check that the "shutdown has started" bit isn't zero. This would happen
-    // if it was incremented twice.
-    DCHECK(new_value & kShutdownHasStartedMask);
+    const uint32_t old_value =
+        bits_.fetch_or(kShutdownHasStartedMask, std::memory_order_relaxed);
+    DCHECK((old_value & kShutdownHasStartedMask) == 0);
 
     const auto num_items_blocking_shutdown =
-        new_value >> kNumItemsBlockingShutdownBitOffset;
+        old_value >> kNumItemsBlockingShutdownBitOffset;
     return num_items_blocking_shutdown != 0;
   }
 
   // Returns true if shutdown has started.
   bool HasShutdownStarted() const {
-    return subtle::NoBarrier_Load(&bits_) & kShutdownHasStartedMask;
+    return bits_.load(std::memory_order_relaxed) & kShutdownHasStartedMask;
   }
 
   // Returns true if there are items blocking shutdown.
   bool AreItemsBlockingShutdown() const {
     const auto num_items_blocking_shutdown =
-        subtle::NoBarrier_Load(&bits_) >> kNumItemsBlockingShutdownBitOffset;
-    DCHECK_GE(num_items_blocking_shutdown, 0);
+        bits_.load(std::memory_order_relaxed) >>
+        kNumItemsBlockingShutdownBitOffset;
     return num_items_blocking_shutdown != 0;
   }
 
@@ -177,33 +174,34 @@
 #if DCHECK_IS_ON()
     // Verify that no overflow will occur.
     const auto num_items_blocking_shutdown =
-        subtle::NoBarrier_Load(&bits_) >> kNumItemsBlockingShutdownBitOffset;
+        bits_.load(std::memory_order_relaxed) >>
+        kNumItemsBlockingShutdownBitOffset;
     DCHECK_LT(num_items_blocking_shutdown,
-              std::numeric_limits<subtle::Atomic32>::max() -
+              std::numeric_limits<uint32_t>::max() -
                   kNumItemsBlockingShutdownIncrement);
 #endif
 
-    const auto new_bits = subtle::NoBarrier_AtomicIncrement(
-        &bits_, kNumItemsBlockingShutdownIncrement);
-    return new_bits & kShutdownHasStartedMask;
+    const uint32_t old_bits = bits_.fetch_add(
+        kNumItemsBlockingShutdownIncrement, std::memory_order_relaxed);
+    return old_bits & kShutdownHasStartedMask;
   }
 
   // Decrements the number of items blocking shutdown. Returns true if shutdown
   // has started and the number of tasks blocking shutdown becomes zero.
   bool DecrementNumItemsBlockingShutdown() {
-    const auto new_bits = subtle::NoBarrier_AtomicIncrement(
-        &bits_, -kNumItemsBlockingShutdownIncrement);
-    const bool shutdown_has_started = new_bits & kShutdownHasStartedMask;
-    const auto num_items_blocking_shutdown =
-        new_bits >> kNumItemsBlockingShutdownBitOffset;
-    DCHECK_GE(num_items_blocking_shutdown, 0);
-    return shutdown_has_started && num_items_blocking_shutdown == 0;
+    const uint32_t old_bits = bits_.fetch_sub(
+        kNumItemsBlockingShutdownIncrement, std::memory_order_relaxed);
+    const bool shutdown_has_started = old_bits & kShutdownHasStartedMask;
+    const auto old_num_items_blocking_shutdown =
+        old_bits >> kNumItemsBlockingShutdownBitOffset;
+    DCHECK_GT(old_num_items_blocking_shutdown, 0u);
+    return shutdown_has_started && old_num_items_blocking_shutdown == 1;
   }
 
  private:
-  static constexpr subtle::Atomic32 kShutdownHasStartedMask = 1;
-  static constexpr subtle::Atomic32 kNumItemsBlockingShutdownBitOffset = 1;
-  static constexpr subtle::Atomic32 kNumItemsBlockingShutdownIncrement =
+  static constexpr uint32_t kShutdownHasStartedMask = 1;
+  static constexpr uint32_t kNumItemsBlockingShutdownBitOffset = 1;
+  static constexpr uint32_t kNumItemsBlockingShutdownIncrement =
       1 << kNumItemsBlockingShutdownBitOffset;
 
   // The LSB indicates whether shutdown has started. The other bits count the
@@ -211,13 +209,13 @@
   // No barriers are required to read/write |bits_| as this class is only used
   // as an atomic state checker, it doesn't provide sequential consistency
   // guarantees w.r.t. external state. Sequencing of the TaskTracker::State
-  // operations themselves is guaranteed by the AtomicIncrement RMW (read-
+  // operations themselves is guaranteed by the fetch_add() RMW (read-
   // modify-write) semantics however. For example, if two threads are racing to
   // call IncrementNumItemsBlockingShutdown() and StartShutdown() respectively,
   // either the first thread will win and the StartShutdown() call will see the
   // blocking task or the second thread will win and
   // IncrementNumItemsBlockingShutdown() will know that shutdown has started.
-  subtle::Atomic32 bits_ = 0;
+  std::atomic<uint32_t> bits_ = 0;
 };
 
 TaskTracker::TaskTracker()
diff --git a/base/task/thread_pool/task_tracker.h b/base/task/thread_pool/task_tracker.h
index b030fc5..dcab998 100644
--- a/base/task/thread_pool/task_tracker.h
+++ b/base/task/thread_pool/task_tracker.h
@@ -14,7 +14,6 @@
 #include <string>
 
 #include "base/atomic_sequence_num.h"
-#include "base/atomicops.h"
 #include "base/base_export.h"
 #include "base/containers/circular_deque.h"
 #include "base/functional/callback_forward.h"
diff --git a/base/task/thread_pool/thread_group_impl_unittest.cc b/base/task/thread_pool/thread_group_impl_unittest.cc
index 1ea2f70..7b56fa3 100644
--- a/base/task/thread_pool/thread_group_impl_unittest.cc
+++ b/base/task/thread_pool/thread_group_impl_unittest.cc
@@ -14,7 +14,6 @@
 #include <utility>
 #include <vector>
 
-#include "base/atomicops.h"
 #include "base/barrier_closure.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
diff --git a/base/test/task_environment_unittest.cc b/base/test/task_environment_unittest.cc
index 680e5a2..28b31ee 100644
--- a/base/test/task_environment_unittest.cc
+++ b/base/test/task_environment_unittest.cc
@@ -5,10 +5,10 @@
 #include "base/test/task_environment.h"
 
 #include <atomic>
+#include <cstdint>
 #include <memory>
 #include <string_view>
 
-#include "base/atomicops.h"
 #include "base/cancelable_callback.h"
 #include "base/check.h"
 #include "base/debug/debugger.h"
@@ -186,94 +186,50 @@
   TaskEnvironment task_environment(
       time_source, TaskEnvironment::ThreadPoolExecutionMode::QUEUED);
 
-  subtle::Atomic32 counter = 0;
+  std::atomic<uint32_t> counter = 0;
+  auto post_on_single_thread_task_runner = [&counter](uint32_t increment,
+                                                      base::TimeDelta delay) {
+    SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
+        FROM_HERE, BindLambdaForTesting([increment, &counter]() {
+          counter.fetch_add(increment, std::memory_order_relaxed);
+        }),
+        delay);
+  };
+  auto post_on_thread_pool = [&counter](uint32_t increment,
+                                        base::TimeDelta delay) {
+    ThreadPool::PostDelayedTask(
+        FROM_HERE, BindLambdaForTesting([increment, &counter]() {
+          counter.fetch_add(increment, std::memory_order_relaxed);
+        }),
+        delay);
+  };
 
-  constexpr base::TimeDelta kShortTaskDelay = Days(1);
-  // Should run only in MOCK_TIME environment when time is fast-forwarded.
-  SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
-      FROM_HERE,
-      BindOnce(
-          [](subtle::Atomic32* counter) {
-            subtle::NoBarrier_AtomicIncrement(counter, 4);
-          },
-          Unretained(&counter)),
-      kShortTaskDelay);
-  ThreadPool::PostDelayedTask(FROM_HERE,
-                              BindOnce(
-                                  [](subtle::Atomic32* counter) {
-                                    subtle::NoBarrier_AtomicIncrement(counter,
-                                                                      128);
-                                  },
-                                  Unretained(&counter)),
-                              kShortTaskDelay);
+  constexpr base::TimeDelta kShortTaskDelay = base::Days(1);
+  post_on_single_thread_task_runner(4, kShortTaskDelay);
+  post_on_thread_pool(128, kShortTaskDelay);
 
   constexpr base::TimeDelta kLongTaskDelay = Days(7);
   // Same as first task, longer delays to exercise
   // FastForwardUntilNoTasksRemain().
-  SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
-      FROM_HERE,
-      BindOnce(
-          [](subtle::Atomic32* counter) {
-            subtle::NoBarrier_AtomicIncrement(counter, 8);
-          },
-          Unretained(&counter)),
-      Days(5));
-  SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
-      FROM_HERE,
-      BindOnce(
-          [](subtle::Atomic32* counter) {
-            subtle::NoBarrier_AtomicIncrement(counter, 16);
-          },
-          Unretained(&counter)),
-      kLongTaskDelay);
-  ThreadPool::PostDelayedTask(FROM_HERE,
-                              BindOnce(
-                                  [](subtle::Atomic32* counter) {
-                                    subtle::NoBarrier_AtomicIncrement(counter,
-                                                                      256);
-                                  },
-                                  Unretained(&counter)),
-                              kLongTaskDelay * 2);
-  SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
-      FROM_HERE,
-      BindOnce(
-          [](subtle::Atomic32* counter) {
-            subtle::NoBarrier_AtomicIncrement(counter, 512);
-          },
-          Unretained(&counter)),
-      kLongTaskDelay * 3);
-  ThreadPool::PostDelayedTask(FROM_HERE,
-                              BindOnce(
-                                  [](subtle::Atomic32* counter) {
-                                    subtle::NoBarrier_AtomicIncrement(counter,
-                                                                      1024);
-                                  },
-                                  Unretained(&counter)),
-                              kLongTaskDelay * 4);
+  post_on_single_thread_task_runner(8, Days(5));
+  post_on_single_thread_task_runner(16, kLongTaskDelay);
+  post_on_thread_pool(256, kLongTaskDelay * 2);
+  post_on_single_thread_task_runner(512, kLongTaskDelay * 3);
+  post_on_thread_pool(1024, kLongTaskDelay * 4);
 
-  SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
-      FROM_HERE, BindOnce(
-                     [](subtle::Atomic32* counter) {
-                       subtle::NoBarrier_AtomicIncrement(counter, 1);
-                     },
-                     Unretained(&counter)));
-  ThreadPool::PostTask(FROM_HERE, BindOnce(
-                                      [](subtle::Atomic32* counter) {
-                                        subtle::NoBarrier_AtomicIncrement(
-                                            counter, 2);
-                                      },
-                                      Unretained(&counter)));
+  post_on_single_thread_task_runner(1, TimeDelta());
+  post_on_thread_pool(2, TimeDelta());
 
   // This expectation will fail flakily if the preceding PostTask() is executed
   // asynchronously, indicating a problem with the QUEUED execution mode.
-  int expected_value = 0;
-  EXPECT_EQ(expected_value, counter);
+  uint32_t expected_value = 0;
+  EXPECT_EQ(expected_value, counter.load(std::memory_order_relaxed));
 
   // RunUntilIdle() should process non-delayed tasks only in all queues.
   task_environment.RunUntilIdle();
   expected_value += 1;
   expected_value += 2;
-  EXPECT_EQ(expected_value, counter);
+  EXPECT_EQ(expected_value, counter.load(std::memory_order_relaxed));
 
   if (time_source == TaskEnvironment::TimeSource::MOCK_TIME) {
     const TimeTicks start_time = task_environment.NowTicks();
@@ -285,7 +241,7 @@
                   "|kInferiorTaskDelay| should be "
                   "set to a value inferior to the first posted task's delay.");
     task_environment.FastForwardBy(kInferiorTaskDelay);
-    EXPECT_EQ(expected_value, counter);
+    EXPECT_EQ(expected_value, counter.load(std::memory_order_relaxed));
     // Time advances to cap even if there was no task at cap and live ticks
     // advances by the same amount.
     EXPECT_EQ(task_environment.NowTicks() - start_time, kInferiorTaskDelay);
@@ -295,7 +251,7 @@
     task_environment.FastForwardBy(kShortTaskDelay - kInferiorTaskDelay);
     expected_value += 4;
     expected_value += 128;
-    EXPECT_EQ(expected_value, counter);
+    EXPECT_EQ(expected_value, counter.load(std::memory_order_relaxed));
     EXPECT_EQ(task_environment.NowTicks() - start_time, kShortTaskDelay);
     EXPECT_EQ(task_environment.NowLiveTicks() - live_start_time,
               kShortTaskDelay);
@@ -306,7 +262,7 @@
     expected_value += 256;
     expected_value += 512;
     expected_value += 1024;
-    EXPECT_EQ(expected_value, counter);
+    EXPECT_EQ(expected_value, counter.load(std::memory_order_relaxed));
     EXPECT_EQ(task_environment.NowTicks() - start_time, kLongTaskDelay * 4);
     EXPECT_EQ(task_environment.NowLiveTicks() - live_start_time,
               kLongTaskDelay * 4);
diff --git a/base/threading/hang_watcher.h b/base/threading/hang_watcher.h
index d0576425..b1b9ca9 100644
--- a/base/threading/hang_watcher.h
+++ b/base/threading/hang_watcher.h
@@ -11,7 +11,6 @@
 #include <type_traits>
 #include <vector>
 
-#include "base/atomicops.h"
 #include "base/auto_reset.h"
 #include "base/base_export.h"
 #include "base/bits.h"
diff --git a/base/threading/thread_collision_warner.cc b/base/threading/thread_collision_warner.cc
index ee055c01..c99661e 100644
--- a/base/threading/thread_collision_warner.cc
+++ b/base/threading/thread_collision_warner.cc
@@ -4,6 +4,7 @@
 
 #include "base/threading/thread_collision_warner.h"
 
+#include <atomic>
 #include <ostream>
 
 #include "base/notreached.h"
@@ -15,51 +16,40 @@
   NOTREACHED() << "Thread Collision";
 }
 
-static subtle::Atomic32 CurrentThread() {
-  const PlatformThreadId current_thread_id = PlatformThread::CurrentId();
-  // We need to get the thread id into an atomic data type. This might be a
-  // truncating conversion, but any loss-of-information just increases the
-  // chance of a fault negative, not a false positive.
-  const subtle::Atomic32 atomic_thread_id =
-      static_cast<subtle::Atomic32>(current_thread_id);
-
-  return atomic_thread_id;
-}
-
 void ThreadCollisionWarner::EnterSelf() {
-  // If the active thread is 0 then I'll write the current thread ID
-  // if two or more threads arrive here only one will succeed to
-  // write on valid_thread_id_ the current thread ID.
-  subtle::Atomic32 current_thread_id = CurrentThread();
+  // If the active thread is kInvalidThreadId then I'll write the current thread
+  // ID if two or more threads arrive here only one will succeed to write on
+  // valid_thread_id_ the current thread ID.
+  PlatformThreadId current_thread_id = PlatformThread::CurrentId();
+  PlatformThreadId expected = kInvalidThreadId;
 
-  int previous_value = subtle::NoBarrier_CompareAndSwap(&valid_thread_id_,
-                                                        0,
-                                                        current_thread_id);
-  if (previous_value != 0 && previous_value != current_thread_id) {
+  bool ok = valid_thread_id_.compare_exchange_strong(
+      expected, current_thread_id, std::memory_order_relaxed,
+      std::memory_order_relaxed);
+  if (!ok && expected != current_thread_id) {
     // gotcha! a thread is trying to use the same class and that is
     // not current thread.
     asserter_->warn();
   }
-
-  subtle::NoBarrier_AtomicIncrement(&counter_, 1);
+  counter_.fetch_add(1, std::memory_order_relaxed);
 }
 
 void ThreadCollisionWarner::Enter() {
-  subtle::Atomic32 current_thread_id = CurrentThread();
+  PlatformThreadId current_thread_id = PlatformThread::CurrentId();
+  PlatformThreadId expected = kInvalidThreadId;
 
-  if (subtle::NoBarrier_CompareAndSwap(&valid_thread_id_,
-                                       0,
-                                       current_thread_id) != 0) {
+  if (!valid_thread_id_.compare_exchange_strong(expected, current_thread_id,
+                                                std::memory_order_relaxed,
+                                                std::memory_order_relaxed)) {
     // gotcha! another thread is trying to use the same class.
     asserter_->warn();
   }
-
-  subtle::NoBarrier_AtomicIncrement(&counter_, 1);
+  counter_.fetch_add(1, std::memory_order_relaxed);
 }
 
 void ThreadCollisionWarner::Leave() {
-  if (subtle::Barrier_AtomicIncrement(&counter_, -1) == 0) {
-    subtle::NoBarrier_Store(&valid_thread_id_, 0);
+  if (counter_.fetch_sub(1, std::memory_order_relaxed) == 1) {
+    valid_thread_id_.store(kInvalidThreadId, std::memory_order_relaxed);
   }
 }
 
diff --git a/base/threading/thread_collision_warner.h b/base/threading/thread_collision_warner.h
index 41d99b8..b6795c5 100644
--- a/base/threading/thread_collision_warner.h
+++ b/base/threading/thread_collision_warner.h
@@ -5,12 +5,14 @@
 #ifndef BASE_THREADING_THREAD_COLLISION_WARNER_H_
 #define BASE_THREADING_THREAD_COLLISION_WARNER_H_
 
-#include "base/atomicops.h"
+#include <atomic>
+
 #include "base/base_export.h"
 #include "base/compiler_specific.h"
 #include "base/dcheck_is_on.h"
 #include "base/macros/uniquify.h"
 #include "base/memory/raw_ptr.h"
+#include "base/threading/platform_thread.h"
 
 // A helper class alongside macros to be used to verify assumptions about thread
 // safety of a class.
@@ -231,11 +233,12 @@
 
   // This stores the thread id that is inside the critical section, if the
   // value is 0 then no thread is inside.
-  volatile subtle::Atomic32 valid_thread_id_;
+  std::atomic<PlatformThreadId> valid_thread_id_;
+  static_assert(std::atomic<PlatformThreadId>::is_always_lock_free, "");
 
   // Counter to trace how many time a critical section was "pinned"
   // (when allowed) in order to unpin it when counter_ reaches 0.
-  volatile subtle::Atomic32 counter_;
+  std::atomic<uint32_t> counter_;
 
   // Here only for class unit tests purpose, during the test I need to not
   // DCHECK but notify the collision with something else.
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc
index 7d505db..c4207e08 100644
--- a/base/trace_event/trace_log.cc
+++ b/base/trace_event/trace_log.cc
@@ -1990,11 +1990,14 @@
 }
 
 void TraceLog::OnStart(const perfetto::DataSourceBase::StartArgs&) {
-  ++active_track_event_sessions_;
-  // Legacy observers don't support multiple tracing sessions. So we only
-  // notify them about the first one.
-  if (active_track_event_sessions_ > 1) {
-    return;
+  {
+    AutoLock lock(track_event_lock_);
+    ++active_track_event_sessions_;
+    // Legacy observers don't support multiple tracing sessions. So we only
+    // notify them about the first one.
+    if (active_track_event_sessions_ > 1) {
+      return;
+    }
   }
 
   AutoLock lock(observers_lock_);
@@ -2020,11 +2023,14 @@
     });
   }
 
-  --active_track_event_sessions_;
-  // Legacy observers don't support multiple tracing sessions. So we only
-  // notify them when the last one stopped.
-  if (active_track_event_sessions_ > 0) {
-    return;
+  {
+    AutoLock lock(track_event_lock_);
+    --active_track_event_sessions_;
+    // Legacy observers don't support multiple tracing sessions. So we only
+    // notify them when the last one stopped.
+    if (active_track_event_sessions_ > 0) {
+      return;
+    }
   }
 
   AutoLock lock(observers_lock_);
diff --git a/base/trace_event/trace_log.h b/base/trace_event/trace_log.h
index 52b10a9..5536563d 100644
--- a/base/trace_event/trace_log.h
+++ b/base/trace_event/trace_log.h
@@ -99,17 +99,22 @@
   void SetDisabled();
   void SetDisabled(uint8_t modes_to_disable);
 
-  // Returns true if TraceLog is enabled on recording mode.
-  // Note: Returns false even if FILTERING_MODE is enabled.
+  // Returns true if TraceLog is enabled (i.e. there's an active tracing
+  // session).
   bool IsEnabled() {
-    // In SDK build we return true as soon as the datasource has been set up and
-    // we know the config. This doesn't necessarily mean that the tracing has
-    // already started.
-    // Note that TrackEvent::IsEnabled() can be true even earlier, before the
-    // OnSetup call, so we can't guarantee that we know the config by the time
-    // TrackEvent::IsEnabled() is true.
+    // We don't rely on TrackEvent::IsEnabled() because it can be true before
+    // TraceLog has processed its TrackEventSessionObserver callbacks.
+    // For example, the code
+    // if (TrackEvent::IsEnabled()) {
+    //   auto config = TraceLog::GetCurrentTrackEventDataSourceConfig();
+    //   ...
+    // }
+    // can fail in a situation when TrackEvent::IsEnabled() is already true, but
+    // TraceLog::OnSetup() hasn't been called yet, so we don't know the config.
+    // Instead, we make sure that both OnSetup() and OnStart() have been called
+    // by tracking the number of active sessions that TraceLog has seen.
     AutoLock lock(track_event_lock_);
-    return track_event_sessions_.size() > 0;
+    return active_track_event_sessions_ > 0;
   }
 
   // The number of times we have begun recording traces. If tracing is off,
diff --git a/base/tracing/stdlib/chrome/input.sql b/base/tracing/stdlib/chrome/input.sql
index f4e2537..0af148d 100644
--- a/base/tracing/stdlib/chrome/input.sql
+++ b/base/tracing/stdlib/chrome/input.sql
@@ -109,24 +109,60 @@
 WHERE step.step = 'STEP_RESAMPLE_SCROLL_EVENTS'
   AND args.flat_key = 'chrome_latency_info.coalesced_trace_ids';
 
--- Slices with information about non-blocking touch move inputs
--- that were converted into gesture scroll updates.
+
+-- Each scroll update event (except flings) in Chrome starts its life as a touch
+-- move event, which is then eventually converted to a scroll update itself.
+-- Each of these events is represented by its own LatencyInfo. This table
+-- contains a mapping between touch move events and scroll update events they
+-- were converted into.
 CREATE PERFETTO TABLE chrome_touch_move_to_scroll_update(
   -- Latency id of the touch move input (LatencyInfo).
   touch_move_latency_id LONG,
   -- Latency id of the corresponding scroll update input (LatencyInfo).
   scroll_update_latency_id LONG
 ) AS
+WITH
+scroll_update_steps AS (
+  SELECT *
+  FROM chrome_input_pipeline_steps
+  WHERE step = 'STEP_SEND_INPUT_EVENT_UI'
+  AND input_type = 'GESTURE_SCROLL_UPDATE_EVENT'
+),
+-- By default, we map a scroll update event to an ancestor touch move event with
+-- STEP_TOUCH_EVENT_HANDLED.
+default_mapping AS (
+  SELECT
+    touch_move_step.latency_id AS touch_move_latency_id,
+    scroll_update_steps.latency_id AS scroll_update_latency_id
+  FROM scroll_update_steps
+  JOIN ancestor_slice(scroll_update_steps.slice_id) AS ancestor
+  JOIN chrome_input_pipeline_steps AS touch_move_step
+    ON ancestor.id = touch_move_step.slice_id
+  WHERE touch_move_step.step = 'STEP_TOUCH_EVENT_HANDLED'
+),
+-- In the rare case where there are no touch handlers in the renderer, there's
+-- no ancestor touch move event with STEP_TOUCH_EVENT_HANDLED. In that case, we
+-- try to fall back to an ancestor touch move event with
+-- STEP_SEND_INPUT_EVENT_UI instead.
+fallback_mapping AS (
+  SELECT
+    touch_move_step.latency_id AS touch_move_latency_id,
+    scroll_update_steps.latency_id AS scroll_update_latency_id
+  FROM scroll_update_steps
+  JOIN ancestor_slice(scroll_update_steps.slice_id) AS ancestor
+  JOIN chrome_input_pipeline_steps AS touch_move_step
+    ON ancestor.id = touch_move_step.slice_id
+  WHERE touch_move_step.step = 'STEP_SEND_INPUT_EVENT_UI'
+  AND touch_move_step.input_type = 'TOUCH_MOVE_EVENT'
+)
 SELECT
-  scroll_update_step.latency_id AS scroll_update_latency_id,
-  touch_move_step.latency_id AS touch_move_latency_id
-FROM chrome_input_pipeline_steps scroll_update_step
-JOIN ancestor_slice(scroll_update_step.slice_id) AS ancestor
-JOIN chrome_input_pipeline_steps touch_move_step
-  ON ancestor.id = touch_move_step.slice_id
-WHERE scroll_update_step.step = 'STEP_SEND_INPUT_EVENT_UI'
-AND scroll_update_step.input_type = 'GESTURE_SCROLL_UPDATE_EVENT'
-AND touch_move_step.step = 'STEP_TOUCH_EVENT_HANDLED';
+  COALESCE(
+    default_mapping.touch_move_latency_id,
+    fallback_mapping.touch_move_latency_id
+  ) AS touch_move_latency_id,
+  scroll_update_latency_id
+FROM default_mapping
+FULL OUTER JOIN fallback_mapping USING (scroll_update_latency_id);
 
 -- Matches Android input id to the corresponding touch move event.
 CREATE PERFETTO TABLE chrome_dispatch_android_input_event_to_touch_move(
diff --git a/base/tracing/test/data_sha256/scroll_with_input_not_forwarded_to_renderer.pftrace.sha256 b/base/tracing/test/data_sha256/scroll_with_input_not_forwarded_to_renderer.pftrace.sha256
new file mode 100644
index 0000000..aaf42de
--- /dev/null
+++ b/base/tracing/test/data_sha256/scroll_with_input_not_forwarded_to_renderer.pftrace.sha256
@@ -0,0 +1 @@
+ceb2ff3cb64c99ddb28a29867bc82f1491c4b413bfacd8638551b80936240faf
\ No newline at end of file
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py b/base/tracing/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py
index 5e56d00..8b49766 100755
--- a/base/tracing/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py
+++ b/base/tracing/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py
@@ -529,6 +529,33 @@
         -2143831735395280142,-2143831735395280132
         """))
 
+  def test_chrome_touch_move_to_scroll_update_not_forwarded_to_renderer(self):
+        return DiffTestBlueprint(
+        trace=DataPath('scroll_with_input_not_forwarded_to_renderer.pftrace'),
+        query="""
+        INCLUDE PERFETTO MODULE chrome.input;
+
+        SELECT
+          touch_move_latency_id,
+          scroll_update_latency_id
+        FROM chrome_touch_move_to_scroll_update
+        ORDER BY touch_move_latency_id
+        LIMIT 10
+        """,
+        out=Csv("""
+        "touch_move_latency_id","scroll_update_latency_id"
+        8456911910253096960,8456911910253096967
+        8456911910253096963,8456911910253096962
+        8456911910253096965,8456911910253096964
+        8456911910253096970,8456911910253096969
+        8456911910253096978,8456911910253096977
+        8456911910253096980,8456911910253096987
+        8456911910253096983,8456911910253096982
+        8456911910253096985,8456911910253096984
+        8456911910253096990,8456911910253096989
+        8456911910253096993,8456911910253096992
+        """))
+
   def test_chrome_scroll_update_info(self):
         return DiffTestBlueprint(
         trace=DataPath('scroll_m131.pftrace'),
diff --git a/build/android/gyp/create_app_bundle.py b/build/android/gyp/create_app_bundle.py
index 529ab086..2798988 100755
--- a/build/android/gyp/create_app_bundle.py
+++ b/build/android/gyp/create_app_bundle.py
@@ -79,11 +79,6 @@
     'com.google.apps.tiktok.concurrent.AndroidFuturesService',
     'com.google.apps.tiktok.concurrent.InternalForegroundService',
 }
-_ALLOWLISTED_NON_BASE_PROVIDERS = {
-    # These need to be burned down.
-    ('com.google.android.libraries.sharing.sharekit.provider.'
-     'ShareKitContentProvider')
-}
 
 
 def _ParseArgs(args):
@@ -515,11 +510,10 @@
       continue
     provider_names = _GetComponentNames(cur_manifest, 'provider')
     for p in provider_names:
-      if p not in _ALLOWLISTED_NON_BASE_PROVIDERS:
-        errors.append(f'Provider {p} should be declared in the base manifest,'
-                      f' but is in "{module_name}" module. For details, see '
-                      'https://chromium.googlesource.com/chromium/src/+/main/'
-                      'docs/android_isolated_splits.md#contentproviders')
+      errors.append(f'Provider {p} should be declared in the base manifest,'
+                    f' but is in "{module_name}" module. For details, see '
+                    'https://chromium.googlesource.com/chromium/src/+/main/'
+                    'docs/android_isolated_splits.md#contentproviders')
 
   # Ensure all services are present in base module because service classes are
   # not found if they are not present in the base module. b/169196314
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index 6f8cb29..60718438 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -271,13 +271,6 @@
     # be present on bots that run exes or load DLLs. This also includes
     # debugging DLLs in all builds.
     data_deps = [ "//build/win:runtime_libs" ]
-
-    # In order to ensure the ACLing is applied to every binary loaded in an
-    # app container sandbox, run the ACL step before any binary is built. We
-    # do this because the tool is subject to race conditions if a binary is
-    # placed in the out folder while it is running.
-    public_deps +=
-        [ "//build/config/win:maybe_set_appcontainer_acls($host_toolchain)" ]
   }
 }
 
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn
index a75b2b0..9b062d60 100644
--- a/build/config/win/BUILD.gn
+++ b/build/config/win/BUILD.gn
@@ -479,29 +479,6 @@
   ]
 }
 
-# ACLs are placed on the filesystem in order to allow chrome to launch
-# sandboxed processes in an app container when run from the out directory.
-group("maybe_set_appcontainer_acls") {
-  # Exclude setting ACLs when build is not happening on chromium, or with a different toolchain.
-  if (build_with_chromium && current_cpu == target_cpu) {
-    deps = [ ":set_appcontainer_acls" ]
-  }
-}
-
-if (build_with_chromium && current_cpu == target_cpu) {
-  action("set_appcontainer_acls") {
-    script = "//build/win/set_appcontainer_acls.py"
-    stamp_file = "$target_out_dir/acls.stamp"
-    inputs = [ script ]
-    outputs = [ stamp_file ]
-
-    args = [
-      "--stamp=" + rebase_path(stamp_file, root_out_dir),
-      "--dir=" + rebase_path(root_out_dir, root_out_dir),
-    ]
-  }
-}
-
 # CRT --------------------------------------------------------------------------
 
 # Configures how the runtime library (CRT) is going to be used.
diff --git a/buildtools/deps_revisions.gni b/buildtools/deps_revisions.gni
index cafc3c9..de26bebd 100644
--- a/buildtools/deps_revisions.gni
+++ b/buildtools/deps_revisions.gni
@@ -5,5 +5,5 @@
 declare_args() {
   # Used to cause full rebuilds on libc++ rolls. This should be kept in sync
   # with the libcxx_revision var in //DEPS.
-  libcxx_revision = "619ccf05152d4612fac76ba5899094704f3661dd"
+  libcxx_revision = "60a3e1838767d557822e90f2671135a79a62c5d0"
 }
diff --git a/cc/input/scrollbar.h b/cc/input/scrollbar.h
index 884d2531..f83895f7 100644
--- a/cc/input/scrollbar.h
+++ b/cc/input/scrollbar.h
@@ -114,8 +114,8 @@
   // (`HasTickmarks()`), this can still return true, but the nine-patch
   // implementation in cc will not be used for painting.
   virtual bool UsesNinePatchTrackAndButtonsResource() const = 0;
-  virtual gfx::Size NinePatchTrackAndButtonsCanvasSize(float scale) const = 0;
-  virtual gfx::Rect NinePatchTrackAndButtonsAperture(float scale) const = 0;
+  virtual gfx::Size NinePatchTrackAndButtonsCanvasSize() const = 0;
+  virtual gfx::Rect NinePatchTrackAndButtonsAperture() const = 0;
 
   // This is used by blink only, to adjust the painted thumb rect in
   // main-thread minimal mode.
diff --git a/cc/layers/painted_scrollbar_layer.cc b/cc/layers/painted_scrollbar_layer.cc
index 7c9b7375..540be238 100644
--- a/cc/layers/painted_scrollbar_layer.cc
+++ b/cc/layers/painted_scrollbar_layer.cc
@@ -203,8 +203,7 @@
   bool updated = false;
 
   updated |= ScrollbarLayerBase::Update();
-  const bool internal_content_scaled = UpdateInternalContentScale();
-  updated |= internal_content_scaled;
+  updated |= UpdateInternalContentScale();
   updated |= UpdateGeometry();
   updated |= SetHasFindInPageTickmarks(scrollbar_.Read(*this)->HasTickmarks());
 
@@ -224,30 +223,26 @@
     updated = true;
   }
 
-  updated |= UpdateTrackAndButtonsIfNeeded(internal_content_scaled);
+  updated |= UpdateTrackAndButtonsIfNeeded();
   updated |= UpdateThumbIfNeeded();
 
   return updated;
 }
 
-bool PaintedScrollbarLayer::UpdateTrackAndButtonsIfNeeded(
-    bool internal_content_scaled) {
+bool PaintedScrollbarLayer::UpdateTrackAndButtonsIfNeeded() {
   bool updated = false;
   gfx::Size size = bounds();
   gfx::Size scaled_size = internal_content_bounds_.Read(*this);
   if (!track_and_buttons_resource_.Read(*this) ||
-      scrollbar_.Read(*this)->TrackAndButtonsNeedRepaint() ||
-      (uses_nine_patch_track_and_buttons_ && internal_content_scaled)) {
+      scrollbar_.Read(*this)->TrackAndButtonsNeedRepaint()) {
     if (uses_nine_patch_track_and_buttons_ &&
         // Can't use nine-patch track and buttons if tickmarks are present.
         !scrollbar_.Read(*this)->HasTickmarks()) {
-      size = scrollbar_.Read(*this)->NinePatchTrackAndButtonsCanvasSize(
-          /*scale=*/1.f);
-      const float scale = internal_contents_scale_.Read(*this);
+      size = scrollbar_.Read(*this)->NinePatchTrackAndButtonsCanvasSize();
       scaled_size =
-          scrollbar_.Read(*this)->NinePatchTrackAndButtonsCanvasSize(scale);
+          gfx::ScaleToCeiledSize(size, internal_contents_scale_.Read(*this));
       track_and_buttons_aperture_.Write(*this) =
-          scrollbar_.Read(*this)->NinePatchTrackAndButtonsAperture(scale);
+          scrollbar_.Read(*this)->NinePatchTrackAndButtonsAperture();
     }
 
     track_and_buttons_resource_.Write(*this) = ScopedUIResource::Create(
diff --git a/cc/layers/painted_scrollbar_layer.h b/cc/layers/painted_scrollbar_layer.h
index afc71cd..3376b66c 100644
--- a/cc/layers/painted_scrollbar_layer.h
+++ b/cc/layers/painted_scrollbar_layer.h
@@ -71,7 +71,7 @@
  private:
   gfx::Size LayerSizeToContentSize(const gfx::Size& layer_size) const;
   bool UpdateThumbIfNeeded();
-  bool UpdateTrackAndButtonsIfNeeded(bool internal_content_scaled);
+  bool UpdateTrackAndButtonsIfNeeded();
 
   template <typename T>
   bool UpdateProperty(T value, T* prop) {
diff --git a/cc/layers/painted_scrollbar_layer_impl.cc b/cc/layers/painted_scrollbar_layer_impl.cc
index 27a0a58..f5b1405 100644
--- a/cc/layers/painted_scrollbar_layer_impl.cc
+++ b/cc/layers/painted_scrollbar_layer_impl.cc
@@ -220,15 +220,14 @@
     track_and_buttons_shared_quad_state->opacity *= scaled_opacity;
   }
 
-  gfx::Rect scaled_track_and_buttons_quad_rect(internal_content_bounds_);
-
   if (uses_nine_patch_track_and_buttons_ && !has_find_in_page_tickmarks()) {
     AppendNinePatchScaledTrackAndButtons(render_pass,
                                          track_and_buttons_shared_quad_state,
-                                         scaled_track_and_buttons_quad_rect);
+                                         track_and_buttons_quad_rect);
     return;
   }
 
+  gfx::Rect scaled_track_and_buttons_quad_rect(internal_content_bounds_);
   gfx::Rect scaled_visible_track_and_buttons_quad_rect =
       gfx::ScaleToEnclosingRect(visible_track_and_buttons_quad_rect,
                                 internal_contents_scale_);
@@ -249,14 +248,15 @@
 void PaintedScrollbarLayerImpl::AppendNinePatchScaledTrackAndButtons(
     viz::CompositorRenderPass* render_pass,
     viz::SharedQuadState* shared_quad_state,
-    const gfx::Rect& track_and_buttons_quad_rect) {
+    gfx::Rect& track_and_buttons_quad_rect) {
   CHECK(uses_nine_patch_track_and_buttons_);
-  const gfx::Rect border(
+  gfx::Rect border(
       track_and_buttons_aperture_.x(), track_and_buttons_aperture_.y(),
       track_and_buttons_aperture_.x() * 2, track_and_buttons_aperture_.y() * 2);
-  const bool layout_changed = track_and_buttons_patch_generator_.SetLayout(
+  gfx::Rect layer_occlusion;
+  bool layout_changed = track_and_buttons_patch_generator_.SetLayout(
       track_and_buttons_image_bounds_, track_and_buttons_quad_rect.size(),
-      track_and_buttons_aperture_, border, /*output_occlusion=*/gfx::Rect(),
+      track_and_buttons_aperture_, border, layer_occlusion,
       /*fill_center=*/true, /*nearest_neighbor=*/false);
   if (layout_changed) {
     track_and_buttons_patch_generator_.CheckGeometryLimitations();
diff --git a/cc/layers/painted_scrollbar_layer_impl.h b/cc/layers/painted_scrollbar_layer_impl.h
index a8a8bf57..9ed239f 100644
--- a/cc/layers/painted_scrollbar_layer_impl.h
+++ b/cc/layers/painted_scrollbar_layer_impl.h
@@ -107,7 +107,7 @@
   void AppendNinePatchScaledTrackAndButtons(
       viz::CompositorRenderPass* render_pass,
       viz::SharedQuadState* shared_quad_state,
-      const gfx::Rect& track_and_buttons_quad_rect);
+      gfx::Rect& track_and_buttons_quad_rect);
   // Expand the scrollbar thumb's hit testable rect to be able to capture the
   // thumb across the entire width of the track rect.
   gfx::Rect ExpandSolidColorThumb(gfx::Rect thumb_rect) const;
diff --git a/cc/paint/paint_op_reader.cc b/cc/paint/paint_op_reader.cc
index 81d9761..a0e80f0a 100644
--- a/cc/paint/paint_op_reader.cc
+++ b/cc/paint/paint_op_reader.cc
@@ -24,7 +24,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/notreached.h"
-#include "base/numerics/safe_conversions.h"
+#include "base/numerics/safe_math.h"
 #include "base/rand_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/types/optional_util.h"
@@ -709,7 +709,12 @@
   ReadSize(&colors_size);
 
   // If there are too many colors, abort.
-  size_t colors_bytes = colors_size * sizeof(decltype(ref.colors_)::value_type);
+  size_t colors_bytes;
+  if (!base::CheckMul(colors_size, sizeof(decltype(ref.colors_)::value_type))
+           .AssignIfValid(&colors_bytes)) {
+    SetInvalid(DeserializationError::
+                   kInsufficientRemainingBytes_Read_PaintShader_ColorSize);
+  }
   if (colors_bytes > remaining_bytes_) {
     SetInvalid(DeserializationError::
                    kInsufficientRemainingBytes_Read_PaintShader_ColorBytes);
diff --git a/cc/paint/paint_op_reader.h b/cc/paint/paint_op_reader.h
index 4002058..b5de6357 100644
--- a/cc/paint/paint_op_reader.h
+++ b/cc/paint/paint_op_reader.h
@@ -192,7 +192,7 @@
     kInsufficientRemainingBytes_ExtractReadableMemory = 4,
     kInsufficientRemainingBytes_Read_PaintRecord = 5,
     kInsufficientRemainingBytes_Read_PaintShader_ColorBytes = 6,
-    kInsufficientRemainingBytes_Read_PaintShader_ColorSize = 7,  // Obsolete
+    kInsufficientRemainingBytes_Read_PaintShader_ColorSize = 7,
     kInsufficientRemainingBytes_Read_PaintShader_Positions = 8,
     kInsufficientRemainingBytes_Read_SkData = 9,
     kInsufficientRemainingBytes_Read_SkPath = 10,
diff --git a/cc/test/fake_scrollbar.cc b/cc/test/fake_scrollbar.cc
index 283aebe3..960f08a 100644
--- a/cc/test/fake_scrollbar.cc
+++ b/cc/test/fake_scrollbar.cc
@@ -148,20 +148,14 @@
   return uses_nine_patch_track_and_buttons_resource_;
 }
 
-gfx::Size FakeScrollbar::NinePatchTrackAndButtonsCanvasSize(float scale) const {
+gfx::Size FakeScrollbar::NinePatchTrackAndButtonsCanvasSize() const {
   return uses_nine_patch_track_and_buttons_resource_ ? gfx::Size(5, 5)
                                                      : gfx::Size();
 }
 
-gfx::Rect FakeScrollbar::NinePatchTrackAndButtonsAperture(float scale) const {
-  if (uses_nine_patch_track_and_buttons_resource_) {
-    const gfx::Size canvas_size = NinePatchTrackAndButtonsCanvasSize(scale);
-    if (Orientation() == ScrollbarOrientation::kHorizontal) {
-      return gfx::Rect(canvas_size.width() / 2, 0, 1, canvas_size.height());
-    }
-    return gfx::Rect(0, canvas_size.height() / 2, canvas_size.width(), 1);
-  }
-  return gfx::Rect();
+gfx::Rect FakeScrollbar::NinePatchTrackAndButtonsAperture() const {
+  return uses_nine_patch_track_and_buttons_resource_ ? gfx::Rect(0, 0, 5, 5)
+                                                     : gfx::Rect();
 }
 
 bool FakeScrollbar::IsOpaque() const {
diff --git a/cc/test/fake_scrollbar.h b/cc/test/fake_scrollbar.h
index 93142cc7..c2e932c 100644
--- a/cc/test/fake_scrollbar.h
+++ b/cc/test/fake_scrollbar.h
@@ -50,8 +50,8 @@
   bool UsesSolidColorThumb() const override;
   gfx::Insets SolidColorThumbInsets() const override;
   bool UsesNinePatchTrackAndButtonsResource() const override;
-  gfx::Size NinePatchTrackAndButtonsCanvasSize(float scale) const override;
-  gfx::Rect NinePatchTrackAndButtonsAperture(float scale) const override;
+  gfx::Size NinePatchTrackAndButtonsCanvasSize() const override;
+  gfx::Rect NinePatchTrackAndButtonsAperture() const override;
   gfx::Rect ShrinkMainThreadedMinimalModeThumbRect(
       gfx::Rect& rect) const override;
   bool IsOpaque() const override;
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 5789f6c..38a6e4d5 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -4861,7 +4861,6 @@
     scrollbar->set_has_thumb(false);
     scrollbar_layer_ =
         base::MakeRefCounted<FakePaintedScrollbarLayer>(root_->element_id());
-    scrollbar_layer_->SetBounds(gfx::Size(23, 100));
 
     root_->AddChild(scrollbar_layer_);
 
diff --git a/chrome/VERSION b/chrome/VERSION
index 7b50e1bc..5373028 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=133
 MINOR=0
-BUILD=6887
+BUILD=6888
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index eb30368..72986d1 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -456,6 +456,7 @@
       "//chrome/browser/screenshot_monitor:java",
       "//chrome/browser/search_engines/android:java",
       "//chrome/browser/search_resumption:java",
+      "//chrome/browser/segmentation_platform:client_util_java",
       "//chrome/browser/segmentation_platform:factory_java",
       "//chrome/browser/selection/android:java",
       "//chrome/browser/settings:factory_java",
@@ -3981,6 +3982,7 @@
     "//chrome/browser/profiles/android:jni_headers",
     "//chrome/browser/quick_delete:jni_headers",
     "//chrome/browser/search_engines/android:jni_headers",
+    "//chrome/browser/segmentation_platform:client_util_jni_headers",
     "//chrome/browser/segmentation_platform:jni_headers",
     "//chrome/browser/tab:jni_headers",
     "//chrome/browser/tab_group_sync:factory_jni_headers",
diff --git a/chrome/android/features/tab_ui/java/res/values/dimens.xml b/chrome/android/features/tab_ui/java/res/values/dimens.xml
index 03df09d..c46d893 100644
--- a/chrome/android/features/tab_ui/java/res/values/dimens.xml
+++ b/chrome/android/features/tab_ui/java/res/values/dimens.xml
@@ -96,6 +96,7 @@
     <dimen name="tab_card_label_icon_inset">3dp</dimen>
     <dimen name="tab_card_label_icon_radius">8dp</dimen>
     <dimen name="tab_card_label_height">24dp</dimen>
+    <dimen name="tab_card_label_list_margin_end">9dp</dimen>
 
     <!-- Dimens for TabGroupSync features -->
     <dimen name="tab_group_start_icon_size">34dp</dimen>
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
index 05ba6a9..6eb6302 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
@@ -13,12 +13,14 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.CallbackController;
+import org.chromium.base.Token;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.LazyOneshotSupplier;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.supplier.OneshotSupplier;
+import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.data_sharing.DataSharingServiceFactory;
 import org.chromium.chrome.browser.data_sharing.ui.shared_image_tiles.SharedImageTilesCoordinator;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -57,6 +59,7 @@
 import org.chromium.url.GURL;
 
 import java.util.List;
+import java.util.Objects;
 
 /** A mediator for the TabGroupUi. Responsible for managing the internal state of the component. */
 public class TabGroupUiMediator implements BackPressHandler, ThemeColorObserver, TintObserver {
@@ -108,8 +111,8 @@
     private TabGroupModelFilterObserver mTabGroupModelFilterObserver;
     private TabModelSelectorTabObserver mTabModelSelectorTabObserver;
     private Callback<Boolean> mOmniboxFocusObserver;
-    private boolean mIsTabGroupUiVisible;
-    private boolean mIsShowingOverViewMode;
+    private @Nullable Token mCurrentTabGroupId;
+    private boolean mIsShowingHub;
 
     TabGroupUiMediator(
             Context context,
@@ -169,7 +172,7 @@
         var layoutStateProvider = layoutStateProviderSupplier.get();
         if (layoutStateProvider != null
                 && layoutStateProvider.isLayoutVisible(LayoutType.TAB_SWITCHER)) {
-            mIsShowingOverViewMode = true;
+            mIsShowingHub = true;
         }
 
         // register for tab model
@@ -177,27 +180,14 @@
                 new TabModelObserver() {
                     @Override
                     public void didSelectTab(Tab tab, @TabSelectionType int type, int lastId) {
-                        if (getTabsToShowForId(lastId).contains(tab)) {
-                            return;
-                        }
-
-                        resetTabStripWithRelatedTabsForId(tab.getId());
+                        resetTabStrip();
                     }
 
                     // TODO(crbug/41496693): Delete this logic once tab groups with one tab are
                     // launched.
                     @Override
                     public void willCloseTab(Tab tab, boolean didCloseAlone) {
-                        if (!mIsTabGroupUiVisible) return;
-
-                        // Check if the group the tab was part of is still a tab group.
-                        TabGroupModelFilter filter = getCurrentTabGroupModelFilter();
-                        Tab groupTab = filter.getGroupLastShownTab(tab.getRootId());
-                        if (groupTab == null) return;
-
-                        if (!getCurrentTabGroupModelFilter().isTabInTabGroup(groupTab)) {
-                            resetTabStripWithRelatedTabsForId(Tab.INVALID_TAB_ID);
-                        }
+                        resetTabStrip();
                     }
 
                     @Override
@@ -206,46 +196,26 @@
                             int type,
                             @TabCreationState int creationState,
                             boolean markedForSelection) {
-                        if (type == TabLaunchType.FROM_CHROME_UI
-                                || type == TabLaunchType.FROM_RESTORE
-                                || type == TabLaunchType.FROM_STARTUP
-                                || type == TabLaunchType.FROM_LONGPRESS_BACKGROUND) {
-                            return;
+                        resetTabStrip();
+                        if (mCurrentTabGroupId != null
+                                && Objects.equals(tab.getTabGroupId(), mCurrentTabGroupId)
+                                && type == TabLaunchType.FROM_TAB_GROUP_UI) {
+                            postUpdateInitialScrollIndex(
+                                    () -> {
+                                        return Math.max(
+                                                0, getTabsToShowForId(tab.getId()).size() - 1);
+                                    });
                         }
-
-                        if (type == TabLaunchType.FROM_TAB_GROUP_UI && mIsTabGroupUiVisible) {
-                            mModel.set(
-                                    TabGroupUiProperties.INITIAL_SCROLL_INDEX,
-                                    getTabsToShowForId(tab.getId()).size() - 1);
-                        }
-
-                        if (mIsTabGroupUiVisible) return;
-
-                        resetTabStripWithRelatedTabsForId(tab.getId());
                     }
 
                     @Override
                     public void restoreCompleted() {
-                        Tab currentTab = mTabModelSelector.getCurrentTab();
-                        // Do not try to show tab strip when there is no current tab or we are not
-                        // in tab page when restore completed.
-                        if (currentTab == null
-                                || (mLayoutStateProvider != null
-                                        && mLayoutStateProvider.isLayoutVisible(
-                                                LayoutType.TAB_SWITCHER))) {
-                            return;
-                        }
-                        resetTabStripWithRelatedTabsForId(currentTab.getId());
+                        resetTabStrip();
                     }
 
                     @Override
                     public void tabClosureUndone(Tab tab) {
-                        if (!mIsTabGroupUiVisible) {
-                            // Reset with the current tab as the undone tab may be in the
-                            // background.
-                            resetTabStripWithRelatedTabsForId(
-                                    mTabModelSelector.getCurrentTab().getId());
-                        }
+                        resetTabStrip();
                     }
                 };
         mLayoutStateObserver =
@@ -253,18 +223,16 @@
                     @Override
                     public void onStartedShowing(@LayoutType int layoutType) {
                         if (layoutType == LayoutType.TAB_SWITCHER) {
-                            mIsShowingOverViewMode = true;
-                            resetTabStripWithRelatedTabsForId(Tab.INVALID_TAB_ID);
+                            mIsShowingHub = true;
+                            resetTabStrip();
                         }
                     }
 
                     @Override
                     public void onFinishedHiding(@LayoutType int layoutType) {
                         if (layoutType == LayoutType.TAB_SWITCHER) {
-                            mIsShowingOverViewMode = false;
-                            Tab tab = mTabModelSelector.getCurrentTab();
-                            if (tab == null) return;
-                            resetTabStripWithRelatedTabsForId(tab.getId());
+                            mIsShowingHub = false;
+                            resetTabStrip();
                         }
                     }
                 };
@@ -274,14 +242,13 @@
                     @Override
                     public void onPageLoadStarted(Tab tab, GURL url) {
                         // TODO(crbug.com/40695094) This is a band-aid fix for M84. The root cause
-                        // is
-                        // probably a leaked observer. Remove this when the TabObservers are removed
-                        // during tab reparenting.
+                        // is probably a leaked observer. Remove this when the TabObservers are
+                        // removed during tab reparenting.
                         if (mTabModelSelector.getTabById(tab.getId()) == null) return;
 
                         int numTabs = 0;
                         TabGroupModelFilter filter = getCurrentTabGroupModelFilter();
-                        if (mIsTabGroupUiVisible && filter.isTabInTabGroup(tab)) {
+                        if (mCurrentTabGroupId != null && filter.isTabInTabGroup(tab)) {
                             numTabs = filter.getRelatedTabCountForRootId(tab.getRootId());
                         }
 
@@ -302,16 +269,14 @@
 
         mCurrentTabModelObserver =
                 (tabModel) -> {
-                    resetTabStripWithRelatedTabsForId(mTabModelSelector.getCurrentTabId());
+                    resetTabStrip();
                 };
 
         mTabGroupModelFilterObserver =
                 new TabGroupModelFilterObserver() {
                     @Override
                     public void didMoveTabOutOfGroup(Tab movedTab, int prevFilterIndex) {
-                        if (mIsTabGroupUiVisible && movedTab == mTabModelSelector.getCurrentTab()) {
-                            resetTabStripWithRelatedTabsForId(movedTab.getId());
-                        }
+                        resetTabStrip();
                     }
                 };
 
@@ -325,13 +290,7 @@
 
         mOmniboxFocusObserver =
                 isFocus -> {
-                    // Hide tab strip when omnibox gains focus and try to re-show it when omnibox
-                    // loses focus.
-                    int tabId =
-                            (isFocus == null || !isFocus)
-                                    ? mTabModelSelector.getCurrentTabId()
-                                    : Tab.INVALID_TAB_ID;
-                    resetTabStripWithRelatedTabsForId(tabId);
+                    resetTabStrip();
                 };
         mOmniboxFocusStateSupplier.addObserver(mOmniboxFocusObserver);
 
@@ -348,10 +307,7 @@
         setupToolbarButtons();
         mModel.set(TabGroupUiProperties.SHOW_GROUP_DIALOG_BUTTON_VISIBLE, true);
         mModel.set(TabGroupUiProperties.IS_MAIN_CONTENT_VISIBLE, true);
-        Tab tab = mTabModelSelector.getCurrentTab();
-        if (tab != null) {
-            resetTabStripWithRelatedTabsForId(tab.getId());
-        }
+        resetTabStrip();
 
         mHandleBackPressChangedSupplier = handleBackPressChangedSupplier;
         if (mTabGridDialogControllerSupplier != null) {
@@ -425,43 +381,62 @@
                 TabGroupUiProperties.NEW_TAB_BUTTON_ON_CLICK_LISTENER, newTabButtonOnClickListener);
     }
 
-    /**
-     * Update the tab strip based on given tab ID.
-     *
-     * @param id If the ID is set to Tab.INVALID_TAB_ID, this method will hide the tab strip. If
-     *     not, associated tabs from #getTabsToShowForID will be showing in the tab strip.
-     */
-    private void resetTabStripWithRelatedTabsForId(int id) {
+    private void hideTabStrip() {
+        if (mCurrentTabGroupId == null) return;
+
+        updateTabGroupIdForShareByTab(null);
+        mResetHandler.resetStripWithListOfTabs(null);
+        mCurrentTabGroupId = null;
+        mVisibilityController.setBottomControlsVisible(false);
+    }
+
+    private void showTabStrip(Tab tab) {
+        if (Objects.equals(mCurrentTabGroupId, tab.getTabGroupId())) return;
+
+        updateTabGroupIdForShareByTab(tab);
+        assert tab.getTabGroupId() != null;
+        List<Tab> listOfTabs = getTabsToShowForId(tab.getId());
+        mResetHandler.resetStripWithListOfTabs(listOfTabs);
+        mCurrentTabGroupId = tab.getTabGroupId();
+
+        postUpdateInitialScrollIndex(
+                () -> {
+                    @Nullable Tab currentTab = mTabModelSelector.getCurrentTab();
+                    if (currentTab == null) return 0;
+
+                    return getTabsToShowForId(currentTab.getId()).indexOf(currentTab);
+                });
+        mVisibilityController.setBottomControlsVisible(true);
+    }
+
+    private void postUpdateInitialScrollIndex(Supplier<Integer> indexSupplier) {
+        // Post to make sure that the recyclerView already knows how many visible items it has.
+        // This is to make sure that we can scroll to a state where the selected tab is in the
+        // middle of the strip.
+        Handler handler = new Handler();
+        handler.post(
+                () -> mModel.set(TabGroupUiProperties.INITIAL_SCROLL_INDEX, indexSupplier.get()));
+    }
+
+    private boolean isOmniboxFocused() {
+        @Nullable Boolean focused = mOmniboxFocusStateSupplier.get();
+        return Boolean.TRUE.equals(focused);
+    }
+
+    private void resetTabStrip() {
         if (!mTabModelSelector.isTabStateInitialized()) return;
 
-        // TODO(crbug.com/40133857): We should be able to guard this call behind some checks so that
-        // we can assert here that 1) mIsShowingOverViewMode is false 2) mIsTabGroupUiVisible with
-        // valid id is false.
-        // When overview mode is showing keep the tab strip hidden.
-        if (mIsShowingOverViewMode) {
-            id = Tab.INVALID_TAB_ID;
+        if (mIsShowingHub || isOmniboxFocused()) {
+            hideTabStrip();
+            return;
         }
-        Tab tab = mTabModelSelector.getTabById(id);
-        updateTabGroupIdForShareByTab(tab);
-        if (tab == null || !getCurrentTabGroupModelFilter().isTabInTabGroup(tab)) {
-            mResetHandler.resetStripWithListOfTabs(null);
-            mIsTabGroupUiVisible = false;
-        } else {
-            List<Tab> listOfTabs = getTabsToShowForId(id);
-            mResetHandler.resetStripWithListOfTabs(listOfTabs);
-            mIsTabGroupUiVisible = true;
 
-            // Post to make sure that the recyclerView already knows how many visible items it has.
-            // This is to make sure that we can scroll to a state where the selected tab is in the
-            // middle of the strip.
-            Handler handler = new Handler();
-            handler.post(
-                    () ->
-                            mModel.set(
-                                    TabGroupUiProperties.INITIAL_SCROLL_INDEX,
-                                    listOfTabs.indexOf(mTabModelSelector.getCurrentTab())));
+        Tab tab = mTabModelSelector.getCurrentTab();
+        if (tab == null || !getCurrentTabGroupModelFilter().isTabInTabGroup(tab)) {
+            hideTabStrip();
+        } else {
+            showTabStrip(tab);
         }
-        mVisibilityController.setBottomControlsVisible(mIsTabGroupUiVisible);
     }
 
     private void updateTabGroupIdForShareByTab(@Nullable Tab tab) {
@@ -568,10 +543,6 @@
         }
     }
 
-    boolean getIsShowingOverViewModeForTesting() {
-        return mIsShowingOverViewMode;
-    }
-
     private @Nullable DialogController getTabGridDialogControllerIfExists() {
         if (mTabGridDialogControllerSupplier == null) return null;
         if (!mTabGridDialogControllerSupplier.hasValue()) return null;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
index b6524ba..6821fde 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -589,6 +589,8 @@
                         // Changing URL will result in a thumbnail invalidation if the on-disk
                         // thumbnail doesn't match.
                         updateThumbnailFetcher(model, tab.getId());
+                        // Changing URL should also invalidate the favicon.
+                        updateFaviconForTab(model, tab, null, null);
                     }
                 }
             };
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewBinder.java
index f6b775f5..68aff42 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewBinder.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewBinder.java
@@ -11,6 +11,7 @@
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.InsetDrawable;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
@@ -78,8 +79,12 @@
             ImageView faviconView = tabListView.findViewById(R.id.start_icon);
             faviconView.setImageDrawable(null);
 
-            FrameLayout container = tabListView.findViewById(R.id.after_title_container);
-            TabCardViewBinderUtils.detachTabGroupColorView(container);
+            FrameLayout colorContainer = tabListView.findViewById(R.id.after_title_container);
+            TabCardViewBinderUtils.detachTabGroupColorView(colorContainer);
+
+            FrameLayout labelContainer =
+                    tabListView.findViewById(R.id.before_description_container);
+            labelContainer.removeAllViews();
         }
     }
 
@@ -158,6 +163,9 @@
         } else if (TabProperties.TAB_LONG_CLICK_LISTENER == propertyKey) {
             TabGridViewBinder.setNullableLongClickListener(
                     model.get(TabProperties.TAB_LONG_CLICK_LISTENER), view, model);
+        } else if (TabProperties.TAB_CARD_LABEL_DATA == propertyKey) {
+            // Ignore this data for tab card labels in selectable mode.
+            updateTabCardLabel(view, /* tabCardLabelData= */ null);
         }
     }
 
@@ -185,6 +193,8 @@
             view.findViewById(R.id.end_button)
                     .setContentDescription(
                             model.get(TabProperties.ACTION_BUTTON_DESCRIPTION_STRING));
+        } else if (TabProperties.TAB_CARD_LABEL_DATA == propertyKey) {
+            updateTabCardLabel(view, model.get(TabProperties.TAB_CARD_LABEL_DATA));
         }
     }
 
@@ -296,4 +306,37 @@
                             : R.color.default_icon_color_tint_list);
         }
     }
+
+    private static void updateTabCardLabel(
+            ViewGroup view, @Nullable TabCardLabelData tabCardLabelData) {
+        TabCardLabelView labelView = getOrSetupTabCardLabelView(view);
+        labelView.setData(tabCardLabelData);
+    }
+
+    private static TabCardLabelView getOrSetupTabCardLabelView(ViewGroup view) {
+        FrameLayout labelContainer = view.findViewById(R.id.before_description_container);
+        if (labelContainer.getChildCount() > 0) {
+            return (TabCardLabelView) labelContainer.getChildAt(0);
+        }
+        Context context = labelContainer.getContext();
+        TabCardLabelView labelView =
+                (TabCardLabelView)
+                        LayoutInflater.from(context)
+                                .inflate(R.layout.tab_card_label_layout, labelContainer, false);
+        labelContainer.addView(labelView);
+
+        Resources res = context.getResources();
+        int marginEnd = res.getDimensionPixelSize(R.dimen.tab_card_label_list_margin_end);
+        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) labelView.getLayoutParams();
+        params.setMarginEnd(marginEnd);
+        labelView.setLayoutParams(params);
+
+        // TODO(crbug.com/362306803): This is technically supposed to have elevation. However,
+        // propagating clipToPadding=false and clipChildren=false all the way from
+        // title_and_description_layout up to tab_list_card_item to make it look right is not worth
+        // the complexity/risk of impacting other list UI when this UI is likely to be deprecated in
+        // 2025.
+        labelView.setElevation(0);
+        return labelView;
+    }
 }
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java
index c3fad0a..178532c 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java
@@ -742,6 +742,37 @@
     @MediumTest
     @UiThreadTest
     @EnableFeatures(ChromeFeatureList.DATA_SHARING)
+    public void testTabCardLabel() {
+        TabCardLabelData data =
+                new TabCardLabelData(
+                        TabCardLabelType.ACTIVITY_UPDATE,
+                        context -> "Test label",
+                        /* asyncImageFactory= */ null,
+                        /* contentDescriptionResolver= */ null);
+        mGridModel.set(TabProperties.TAB_CARD_LABEL_DATA, data);
+
+        TabCardLabelView gridLabel = mTabGridView.findViewById(R.id.tab_card_label);
+        assertNotNull(gridLabel);
+        assertEquals(gridLabel.getVisibility(), View.VISIBLE);
+        FrameLayout listContainer = mTabListView.findViewById(R.id.before_description_container);
+        assertEquals(listContainer.getChildCount(), 1);
+        TabCardLabelView listLabel = (TabCardLabelView) listContainer.getChildAt(0);
+        assertNotNull(listLabel);
+        assertEquals(listLabel.getVisibility(), View.VISIBLE);
+
+        mGridModel.set(TabProperties.TAB_CARD_LABEL_DATA, null);
+
+        assertEquals(gridLabel.getVisibility(), View.GONE);
+        assertEquals(listLabel.getVisibility(), View.GONE);
+
+        TabListViewBinder.onViewRecycled(mGridModel, mTabListView);
+        assertNull(listLabel.getParent());
+    }
+
+    @Test
+    @MediumTest
+    @UiThreadTest
+    @EnableFeatures(ChromeFeatureList.DATA_SHARING)
     public void testPriceStringPriceDrop_TabCardLabel() {
         Tab tab = MockTab.createAndInitialize(1, mProfile);
         MockShoppingPersistedTabDataFetcher fetcher = new MockShoppingPersistedTabDataFetcher(tab);
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
index f760d3c..205f46bd 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
@@ -8,7 +8,6 @@
 
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.instanceOf;
-import static org.hamcrest.CoreMatchers.nullValue;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -57,7 +56,6 @@
 import org.chromium.base.Callback;
 import org.chromium.base.Token;
 import org.chromium.base.supplier.LazyOneshotSupplier;
-import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.supplier.OneshotSupplierImpl;
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -143,7 +141,6 @@
     @Mock private TabGroupModelFilterProvider mTabGroupModelFilterProvider;
     @Mock private TabGroupModelFilter mTabGroupModelFilter;
     @Mock private TabGridDialogMediator.DialogController mTabGridDialogController;
-    @Mock private ObservableSupplier<Boolean> mOmniboxFocusStateSupplier;
     @Mock private SharedImageTilesCoordinator mSharedImageTilesCoordinator;
     @Mock private ObservableSupplierImpl<TabModel> mTabModelSupplier;
     @Mock private ThemeColorProvider mThemeColorProvider;
@@ -158,9 +155,10 @@
     private ArgumentCaptor<TabGroupModelFilterObserver> mTabGroupModelFilterObserverArgumentCaptor;
 
     @Captor private ArgumentCaptor<TabObserver> mTabObserverCaptor;
-    @Captor private ArgumentCaptor<Callback<Boolean>> mOmniboxFocusObserverCaptor;
     @Captor private ArgumentCaptor<DataSharingService.Observer> mSharingObserverCaptor;
 
+    private final ObservableSupplierImpl<Boolean> mOmniboxFocusStateSupplier =
+            new ObservableSupplierImpl<>();
     private final ObservableSupplierImpl<Boolean> mHandleBackPressChangedSupplier =
             new ObservableSupplierImpl<>();
     private final ObservableSupplierImpl<Boolean> mTabGridDialogBackPressSupplier =
@@ -263,7 +261,7 @@
         if (mTabGroupModelFilter.isTabInTabGroup(currentTab)) {
             verifyResetStrip(true, tabs);
         } else {
-            verifyResetStrip(false, null);
+            verifyNeverReset();
         }
     }
 
@@ -375,11 +373,6 @@
         doReturn(mTabCreator).when(mTabCreatorManager).getTabCreator(anyBoolean());
         doReturn(null).when(mTabCreator).createNewTab(any(), anyInt(), any());
 
-        // Set up omnibox focus state observer.
-        doReturn(nullValue())
-                .when(mOmniboxFocusStateSupplier)
-                .addObserver(mOmniboxFocusObserverCaptor.capture());
-
         mResetHandlerInOrder = inOrder(mResetHandler);
         mVisibilityControllerInOrder = inOrder(mVisibilityController);
         mModel = new PropertyModel(TabGroupUiProperties.ALL_KEYS);
@@ -456,6 +449,7 @@
         initAndAssertProperties(mTab2);
 
         // Mock selecting tab 1, and the last selected tab is tab 2 which is in different group.
+        when(mTabModelSelector.getCurrentTab()).thenReturn(mTab1);
         mTabModelObserverArgumentCaptor
                 .getValue()
                 .didSelectTab(mTab1, TabSelectionType.FROM_USER, TAB2_ID);
@@ -474,8 +468,12 @@
         doReturn(tabs).when(mTabGroupModelFilter).getRelatedTabList(TAB1_ID);
         doReturn(true).when(mTabGroupModelFilter).isTabInTabGroup(mTab1);
         doReturn(true).when(mTabGroupModelFilter).isTabInTabGroup(newTab);
+        Token tab1GroupId = new Token(1L, 32L);
+        when(mTab1.getTabGroupId()).thenReturn(tab1GroupId);
+        when(newTab.getTabGroupId()).thenReturn(tab1GroupId);
 
         // Mock selecting tab 1, and the last selected tab is tab 2 which is in different group.
+        when(mTabModelSelector.getCurrentTab()).thenReturn(mTab1);
         mTabModelObserverArgumentCaptor
                 .getValue()
                 .didSelectTab(mTab1, TabSelectionType.FROM_USER, TAB2_ID);
@@ -491,6 +489,7 @@
         // Mock that tab 2 is not a single tab.
         List<Tab> tabGroup = mTabGroupModelFilter.getRelatedTabList(TAB2_ID);
         assertThat(tabGroup.size(), equalTo(2));
+        when(mTabModelSelector.getCurrentTab()).thenReturn(mTab2);
 
         // Mock selecting tab 2, and the last selected tab is tab 1 which is a single tab.
         mTabModelObserverArgumentCaptor
@@ -516,7 +515,7 @@
                 .didSelectTab(newTab, TabSelectionType.FROM_USER, TAB1_ID);
 
         // Strip should not be showing since new tab is a single tab.
-        verifyResetStrip(false, null);
+        verifyNeverReset();
     }
 
     @Test
@@ -581,6 +580,7 @@
         doReturn(mTab3).when(mTabGroupModelFilter).getGroupLastShownTab(TAB2_ROOT_ID);
         doReturn(false).when(mTabGroupModelFilter).isTabInTabGroup(mTab2);
         doReturn(true).when(mTabGroupModelFilter).isTabInTabGroup(mTab3);
+        when(mTabModelSelector.getCurrentTab()).thenReturn(mTab3);
 
         // Mock closing tab 2, and tab 3 then gets selected. They are in the same group assume that
         // that Tab 3 is the last tab in the group, but tab groups of size 1 are supported.
@@ -629,6 +629,7 @@
 
         // Mock closing tab 1, and tab 2 then gets selected. They are in different group.
         mTabModelObserverArgumentCaptor.getValue().willCloseTab(mTab1, true);
+        when(mTabModelSelector.getCurrentTab()).thenReturn(mTab2);
         mTabModelObserverArgumentCaptor
                 .getValue()
                 .didSelectTab(mTab2, TabSelectionType.FROM_CLOSE, TAB1_ID);
@@ -694,8 +695,12 @@
         Tab newTab = prepareTab(TAB4_ID, TAB4_ID);
         List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, newTab));
         doReturn(tabs).when(mTabGroupModelFilter).getRelatedTabList(TAB4_ID);
+        doReturn(tabs).when(mTabGroupModelFilter).getRelatedTabList(TAB1_ID);
         doReturn(true).when(mTabGroupModelFilter).isTabInTabGroup(mTab1);
         doReturn(true).when(mTabGroupModelFilter).isTabInTabGroup(newTab);
+        Token tab1GroupId = new Token(3478L, 348L);
+        when(mTab1.getTabGroupId()).thenReturn(tab1GroupId);
+        when(newTab.getTabGroupId()).thenReturn(tab1GroupId);
 
         mTabModelObserverArgumentCaptor
                 .getValue()
@@ -750,6 +755,7 @@
 
         Tab newTab = prepareTab(TAB4_ID, TAB4_ID);
         mTabGroup2.add(newTab);
+        when(newTab.getTabGroupId()).thenReturn(TAB2_GROUP_ID);
         doReturn(mTabGroup2).when(mTabGroupModelFilter).getRelatedTabList(TAB4_ID);
 
         mTabModelObserverArgumentCaptor
@@ -788,13 +794,15 @@
         // Simulate restore finished.
         mTabModelObserverArgumentCaptor.getValue().restoreCompleted();
 
-        mVisibilityControllerInOrder.verify(mVisibilityController).setBottomControlsVisible(false);
+        mVisibilityControllerInOrder
+                .verify(mVisibilityController, never())
+                .setBottomControlsVisible(anyBoolean());
     }
 
     @Test
     public void restoreCompleted_UiVisible() {
+        initAndAssertProperties(mTab1);
         // Assume mTab2 is selected, and it has related tabs mTab2 and mTab3.
-        initAndAssertProperties(mTab2);
         doReturn(POSITION2).when(mTabModel).index();
         doReturn(mTab2).when(mTabModelSelector).getCurrentTab();
         // Simulate restore finished.
@@ -823,8 +831,6 @@
     public void tabClosureUndone_UiVisible_NotShowingOverviewMode() {
         // Assume mTab2 is selected, and it has related tabs mTab2 and mTab3.
         initAndAssertProperties(mTab2);
-        // OverviewMode is hiding by default.
-        assertThat(mTabGroupUiMediator.getIsShowingOverViewModeForTesting(), equalTo(false));
 
         // Simulate that another member of this group, newTab, is being undone from closure.
         Tab newTab = prepareTab(TAB4_ID, TAB4_ID);
@@ -844,8 +850,6 @@
     public void tabClosureUndone_UiNotVisible_NotShowingOverviewMode_TabNotInGroup() {
         // Assume mTab1 is selected. Since mTab1 is now a single tab, the strip is invisible.
         initAndAssertProperties(mTab1);
-        // OverviewMode is hiding by default.
-        assertThat(mTabGroupUiMediator.getIsShowingOverViewModeForTesting(), equalTo(false));
 
         // Simulate mTab2 and mTab3 being undone from closure with mTab1 still selected.
         doReturn(new ArrayList<>(Arrays.asList(mTab2, mTab3)))
@@ -863,15 +867,13 @@
         mTabModelObserverArgumentCaptor.getValue().tabClosureUndone(mTab3);
 
         // Strip should remain invisible.
-        assertThat(mTabGroupUiMediator.getIsShowingOverViewModeForTesting(), equalTo(false));
+        verify(mVisibilityController, never()).setBottomControlsVisible(true);
     }
 
     @Test
     public void tabClosureUndone_UiNotVisible_NotShowingOverviewMode_TabInGroup() {
         // Assume mTab1 is selected. Since mTab1 is now a single tab, the strip is invisible.
         initAndAssertProperties(mTab1);
-        // OverviewMode is hiding by default.
-        assertThat(mTabGroupUiMediator.getIsShowingOverViewModeForTesting(), equalTo(false));
 
         // Simulate that newTab which was a tab in the same group as mTab1 is being undone from
         // closure.
@@ -879,6 +881,9 @@
         List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, newTab));
         doReturn(tabs).when(mTabGroupModelFilter).getRelatedTabList(TAB1_ID);
         doReturn(tabs).when(mTabGroupModelFilter).getRelatedTabList(TAB4_ID);
+        Token tab1GroupId = new Token(1L, 3789L);
+        when(mTab1.getTabGroupId()).thenReturn(tab1GroupId);
+        when(newTab.getTabGroupId()).thenReturn(tab1GroupId);
         doReturn(true).when(mTabGroupModelFilter).isTabInTabGroup(mTab1);
         doReturn(true).when(mTabGroupModelFilter).isTabInTabGroup(newTab);
         doReturn(mTab1).when(mTabModelSelector).getCurrentTab();
@@ -893,59 +898,52 @@
 
     @Test
     public void tabClosureUndone_UiNotVisible_ShowingTabSwitcherMode() {
-        // Assume mTab1 is selected.
+        // Assume mTab1 is selected the strip is hidden.
         initAndAssertProperties(mTab1);
-        // OverviewMode is hiding by default.
-        assertThat(mTabGroupUiMediator.getIsShowingOverViewModeForTesting(), equalTo(false));
 
-        // Simulate the overview mode is showing, which hides the strip.
+        // Simulate the overview mode is showing, which suppresses showing the strip.
         mLayoutStateObserverCaptor.getValue().onStartedShowing(LayoutType.TAB_SWITCHER);
-        assertThat(mTabGroupUiMediator.getIsShowingOverViewModeForTesting(), equalTo(true));
-        mVisibilityControllerInOrder.verify(mVisibilityController).setBottomControlsVisible(false);
+        verifyNeverReset();
 
         // Simulate that we undo a group closure of {mTab2, mTab3}.
+        when(mTabModelSelector.getCurrentTab()).thenReturn(mTab3);
         mTabModelObserverArgumentCaptor.getValue().tabClosureUndone(mTab3);
         mTabModelObserverArgumentCaptor.getValue().tabClosureUndone(mTab2);
 
         // Since overview mode is showing, we should not show strip.
-        mVisibilityControllerInOrder
-                .verify(mVisibilityController, times(2))
-                .setBottomControlsVisible(eq(false));
-    }
-
-    @Test
-    public void overViewStartedShowing() {
-        initAndAssertProperties(mTab1);
-
-        mLayoutStateObserverCaptor.getValue().onStartedShowing(LayoutType.TAB_SWITCHER);
-
-        verifyResetStrip(false, null);
-    }
-
-    @Test
-    public void overViewFinishedHiding_NoCurrentTab() {
-        initAndAssertProperties(null);
-
-        mLayoutStateObserverCaptor.getValue().onFinishedHiding(LayoutType.TAB_SWITCHER);
-
         verifyNeverReset();
     }
 
     @Test
-    public void overViewFinishedHiding_CurrentTabSingle() {
+    public void layoutStateChange_SingleTab() {
         initAndAssertProperties(mTab1);
 
-        mLayoutStateObserverCaptor.getValue().onFinishedHiding(LayoutType.TAB_SWITCHER);
+        mLayoutStateObserverCaptor.getValue().onStartedShowing(LayoutType.TAB_SWITCHER);
+        verifyNeverReset();
 
-        verifyResetStrip(false, null);
+        mLayoutStateObserverCaptor.getValue().onFinishedHiding(LayoutType.TAB_SWITCHER);
+        verifyNeverReset();
     }
 
     @Test
-    public void overViewFinishedHiding_CurrentTabInGroup() {
-        initAndAssertProperties(mTab2);
+    public void layoutStateChange_NoCurrentTab() {
+        initAndAssertProperties(null);
+
+        mLayoutStateObserverCaptor.getValue().onStartedShowing(LayoutType.TAB_SWITCHER);
+        verifyNeverReset();
 
         mLayoutStateObserverCaptor.getValue().onFinishedHiding(LayoutType.TAB_SWITCHER);
+        verifyNeverReset();
+    }
 
+    @Test
+    public void layoutStateChange_TabGroup() {
+        initAndAssertProperties(mTab2);
+
+        mLayoutStateObserverCaptor.getValue().onStartedShowing(LayoutType.TAB_SWITCHER);
+        verifyResetStrip(false, null);
+
+        mLayoutStateObserverCaptor.getValue().onFinishedHiding(LayoutType.TAB_SWITCHER);
         verifyResetStrip(true, mTabGroup2);
     }
 
@@ -982,6 +980,7 @@
         List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab3));
         doReturn(tabs).when(mTabGroupModelFilter).getRelatedTabList(TAB3_ID);
         doReturn(true).when(mTabGroupModelFilter).isTabInTabGroup(mTab3);
+        doReturn(new Token(1L, TAB3_ROOT_ID)).when(mTab3).getTabGroupId();
         mTabGroupModelFilterObserverArgumentCaptor.getValue().didMoveTabOutOfGroup(mTab3, 1);
 
         verifyResetStrip(true, tabs);
@@ -1038,11 +1037,10 @@
     @Test
     public void switchTabModel_UiVisible_TabGroup() {
         initAndAssertProperties(mTab1);
-        assertThat(mTabGroupUiMediator.getIsShowingOverViewModeForTesting(), equalTo(false));
         prepareIncognitoTabModel();
 
         // Mock that tab2 is selected after tab model switch, and tab2 is in a group.
-        doReturn(TAB2_ID).when(mTabModelSelector).getCurrentTabId();
+        when(mTabModelSelector.getCurrentTab()).thenReturn(mTab2);
         mTabModelSupplierObserverCaptor.getValue().onResult(mTabModel);
 
         verifyResetStrip(true, mTabGroup2);
@@ -1050,12 +1048,11 @@
 
     @Test
     public void switchTabModel_UiNotVisible_TabGroup() {
-        initAndAssertProperties(mTab1);
-        assertThat(mTabGroupUiMediator.getIsShowingOverViewModeForTesting(), equalTo(false));
+        initAndAssertProperties(mTab2);
         prepareIncognitoTabModel();
 
         // Mock that tab1 is selected after tab model switch, and tab1 is a single tab.
-        doReturn(TAB1_ID).when(mTabModelSelector).getCurrentTabId();
+        when(mTabModelSelector.getCurrentTab()).thenReturn(mTab1);
         mTabModelSupplierObserverCaptor.getValue().onResult(mTabModel);
 
         verifyResetStrip(false, null);
@@ -1095,11 +1092,11 @@
     public void testOmniboxFocusChange() {
         initAndAssertProperties(mTab2);
 
-        mOmniboxFocusObserverCaptor.getValue().onResult(true);
+        mOmniboxFocusStateSupplier.set(true);
         verifyResetStrip(false, null);
 
-        doReturn(TAB2_ID).when(mTabModelSelector).getCurrentTabId();
-        mOmniboxFocusObserverCaptor.getValue().onResult(false);
+        when(mTabModelSelector.getCurrentTab()).thenReturn(mTab2);
+        mOmniboxFocusStateSupplier.set(false);
         verifyResetStrip(true, mTabGroup2);
     }
 
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
index 79e45db2..573b12c 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
@@ -2924,13 +2924,16 @@
 
         doReturn(new GURL(NEW_URL)).when(mTab1).getUrl();
 
-        var oldFetcher = mModelList.get(POSITION1).model.get(TabProperties.THUMBNAIL_FETCHER);
+        PropertyModel model1 = mModelList.get(POSITION1).model;
+        var oldThumbnailFetcher = model1.get(TabProperties.THUMBNAIL_FETCHER);
+        // Set to null to see if an update happens.
+        model1.set(TabProperties.FAVICON_FETCHER, null);
         mTabObserverCaptor.getValue().onUrlUpdated(mTab1);
 
-        assertEquals(mNewDomain, mModelList.get(POSITION1).model.get(TabProperties.URL_DOMAIN));
+        assertEquals(mNewDomain, model1.get(TabProperties.URL_DOMAIN));
         assertEquals(mTab2Domain, mModelList.get(POSITION2).model.get(TabProperties.URL_DOMAIN));
-        assertNotEquals(
-                oldFetcher, mModelList.get(POSITION1).model.get(TabProperties.THUMBNAIL_FETCHER));
+        assertNotEquals(oldThumbnailFetcher, model1.get(TabProperties.THUMBNAIL_FETCHER));
+        assertNotNull(model1.get(TabProperties.FAVICON_FETCHER));
     }
 
     @Test
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/BrowsingDataCounterBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/BrowsingDataCounterBridge.java
index fe286d66..725ff25 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/BrowsingDataCounterBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/BrowsingDataCounterBridge.java
@@ -32,16 +32,36 @@
      *
      * @param profile The {@link Profile} owning the browsing data.
      * @param callback A callback to call with the result when the counter finishes.
+     * @param selectedTimePeriod The time period selected in the UI.
      * @param dataType The browsing data type to be counted (from the shared enum
      * @param prefType The type of preference that should be handled (Default, Basic or Advanced
      *     from {@link org.chromium.chrome.browser.browsing_data.ClearBrowsingDataTab}).
      */
     public BrowsingDataCounterBridge(
-            Profile profile, BrowsingDataCounterCallback callback, int dataType, int prefType) {
+            Profile profile,
+            BrowsingDataCounterCallback callback,
+            @TimePeriod int selectedTimePeriod,
+            int dataType,
+            int prefType) {
         mCallback = callback;
         mNativeBrowsingDataCounterBridge =
                 BrowsingDataCounterBridgeJni.get()
-                        .init(BrowsingDataCounterBridge.this, profile, dataType, prefType);
+                        .initWithoutPeriodPref(
+                                BrowsingDataCounterBridge.this,
+                                profile,
+                                selectedTimePeriod,
+                                dataType,
+                                prefType);
+    }
+
+    public void setSelectedTimePeriod(@TimePeriod int selectedTimePeriod) {
+        if (mNativeBrowsingDataCounterBridge != 0) {
+            BrowsingDataCounterBridgeJni.get()
+                    .setSelectedTimePeriod(
+                            mNativeBrowsingDataCounterBridge,
+                            BrowsingDataCounterBridge.this,
+                            selectedTimePeriod);
+        }
     }
 
     /** Destroys the native counterpart of this class. */
@@ -60,12 +80,18 @@
 
     @NativeMethods
     interface Natives {
-        long init(
+        long initWithoutPeriodPref(
                 BrowsingDataCounterBridge caller,
                 @JniType("Profile*") Profile profile,
+                int selectedTimePeriod,
                 int dataType,
                 int prefType);
 
+        void setSelectedTimePeriod(
+                long nativeBrowsingDataCounterBridge,
+                BrowsingDataCounterBridge caller,
+                int selectedTimePeriod);
+
         void destroy(long nativeBrowsingDataCounterBridge, BrowsingDataCounterBridge caller);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragment.java
index 98f2570c7..99aac66 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragment.java
@@ -97,6 +97,7 @@
         private final ClearBrowsingDataCheckBoxPreference mCheckbox;
         private BrowsingDataCounterBridge mCounter;
         private boolean mShouldAnnounceCounterResult;
+        private @TimePeriod int mSelectedTimePeriod;
 
         public Item(
                 Context context,
@@ -104,11 +105,13 @@
                 @DialogOption int option,
                 ClearBrowsingDataCheckBoxPreference checkbox,
                 boolean selected,
-                boolean enabled) {
+                boolean enabled,
+                @TimePeriod int selectedTimePeriod) {
             super();
             mParent = parent;
             mOption = option;
             mCheckbox = checkbox;
+            mSelectedTimePeriod = selectedTimePeriod;
             if (option == DialogOption.CLEAR_TABS && !enabled) {
                 mCheckbox.setSummary(R.string.clear_tabs_disabled_summary);
             } else {
@@ -116,6 +119,7 @@
                         new BrowsingDataCounterBridge(
                                 parent.getProfile(),
                                 this,
+                                selectedTimePeriod,
                                 ClearBrowsingDataFragment.getDataType(mOption),
                                 mParent.getClearBrowsingDataTabType());
             }
@@ -149,17 +153,16 @@
             return mCheckbox.isChecked();
         }
 
+        public boolean isEnabled() {
+            return mCheckbox.isEnabled();
+        }
+
         @Override
         public boolean onPreferenceClick(Preference preference) {
             assert mCheckbox == preference;
 
             mParent.updateButtonState();
             mShouldAnnounceCounterResult = true;
-            BrowsingDataBridge.getForProfile(mParent.getProfile())
-                    .setBrowsingDataDeletionPreference(
-                            ClearBrowsingDataFragment.getDataType(mOption),
-                            mParent.getClearBrowsingDataTabType(),
-                            mCheckbox.isChecked());
             return true;
         }
 
@@ -179,6 +182,14 @@
         public void setShouldAnnounceCounterResult(boolean value) {
             mShouldAnnounceCounterResult = value;
         }
+
+        public void setSelectedTimePeriod(@TimePeriod int selectedTimePeriod) {
+            if (mSelectedTimePeriod == selectedTimePeriod) {
+                return;
+            }
+            mSelectedTimePeriod = selectedTimePeriod;
+            mCounter.setSelectedTimePeriod(mSelectedTimePeriod);
+        }
     }
 
     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
@@ -424,6 +435,9 @@
             BrowsingDataBridge.getForProfile(getProfile())
                     .clearBrowsingData(this, dataTypesArray, mLastSelectedTimePeriod);
         }
+
+        // Update prefs with the values displayed in the UI.
+        updateProfilePrefs();
     }
 
     private void dismissProgressDialog() {
@@ -433,6 +447,26 @@
         mProgressDialog = null;
     }
 
+    /** Updates the preferences with the option values of the latest deletion. */
+    private void updateProfilePrefs() {
+        for (Item item : mItems) {
+            // Don't save the selection of items that are disabled, e.g. by policy, into their
+            // preference.
+            if (!item.isEnabled()) {
+                continue;
+            }
+            BrowsingDataBridge.getForProfile(getProfile())
+                    .setBrowsingDataDeletionPreference(
+                            ClearBrowsingDataFragment.getDataType(item.getOption()),
+                            getClearBrowsingDataTabType(),
+                            item.isSelected());
+        }
+
+        BrowsingDataBridge.getForProfile(getProfile())
+                .setBrowsingDataDeletionTimePeriod(
+                        getClearBrowsingDataTabType(), mLastSelectedTimePeriod);
+    }
+
     /** Returns the list of supported {@link DialogOption}. */
     protected abstract List<Integer> getDialogOptions(Bundle fragmentArgs);
 
@@ -531,16 +565,14 @@
     @Override
     public boolean onPreferenceChange(Preference preference, Object value) {
         if (preference.getKey().equals(PREF_TIME_RANGE)) {
+            mLastSelectedTimePeriod = ((TimePeriodSpinnerOption) value).getTimePeriod();
+
             // Inform the items that a recalculation is going to happen as a result of the time
             // period change.
             for (Item item : mItems) {
                 item.setShouldAnnounceCounterResult(false);
+                item.setSelectedTimePeriod(mLastSelectedTimePeriod);
             }
-
-            BrowsingDataBridge.getForProfile(getProfile())
-                    .setBrowsingDataDeletionTimePeriod(
-                            getClearBrowsingDataTabType(),
-                            ((TimePeriodSpinnerOption) value).getTimePeriod());
             return true;
         }
         return false;
@@ -595,6 +627,34 @@
         mItems = new Item[options.size()];
 
         BrowsingDataBridge browsingDataBridge = BrowsingDataBridge.getForProfile(getProfile());
+
+        // Not all checkboxes defined in the layout are necessarily handled by this class
+        // or a particular subclass. Hide those that are not.
+        Set<Integer> unboundOptions = getAllOptions();
+        unboundOptions.removeAll(options);
+        for (@DialogOption Integer option : unboundOptions) {
+            getPreferenceScreen().removePreference(findPreference(getPreferenceKey(option)));
+        }
+
+        // The time range selection spinner.
+        SpinnerPreference spinner = (SpinnerPreference) findPreference(PREF_TIME_RANGE);
+        TimePeriodSpinnerOption[] spinnerOptions = getTimePeriodSpinnerOptions(getActivity());
+        @TimePeriod
+        int selectedTimePeriod =
+                browsingDataBridge.getBrowsingDataDeletionTimePeriod(getClearBrowsingDataTabType());
+        int spinnerOptionIndex = getSpinnerIndex(selectedTimePeriod, spinnerOptions);
+        // If there is no previously-selected value, use last hour as the default.
+        if (spinnerOptionIndex == -1) {
+            spinnerOptionIndex = getSpinnerIndex(TimePeriod.LAST_HOUR, spinnerOptions);
+        }
+        assert spinnerOptionIndex != -1;
+        spinner.setOptions(spinnerOptions, spinnerOptionIndex);
+        spinner.setOnPreferenceChangeListener(this);
+
+        Object spinnerSelection =
+                ((SpinnerPreference) findPreference(PREF_TIME_RANGE)).getSelectedOption();
+        mLastSelectedTimePeriod = ((TimePeriodSpinnerOption) spinnerSelection).getTimePeriod();
+
         for (int i = 0; i < options.size(); i++) {
             @DialogOption int option = options.get(i);
             boolean enabled = true;
@@ -629,32 +689,10 @@
                             (ClearBrowsingDataCheckBoxPreference)
                                     findPreference(getPreferenceKey(option)),
                             enabled && isOptionSelectedByDefault(option),
-                            enabled);
+                            enabled,
+                            mLastSelectedTimePeriod);
         }
 
-        // Not all checkboxes defined in the layout are necessarily handled by this class
-        // or a particular subclass. Hide those that are not.
-        Set<Integer> unboundOptions = getAllOptions();
-        unboundOptions.removeAll(options);
-        for (@DialogOption Integer option : unboundOptions) {
-            getPreferenceScreen().removePreference(findPreference(getPreferenceKey(option)));
-        }
-
-        // The time range selection spinner.
-        SpinnerPreference spinner = (SpinnerPreference) findPreference(PREF_TIME_RANGE);
-        TimePeriodSpinnerOption[] spinnerOptions = getTimePeriodSpinnerOptions(getActivity());
-        @TimePeriod
-        int selectedTimePeriod =
-                browsingDataBridge.getBrowsingDataDeletionTimePeriod(getClearBrowsingDataTabType());
-        int spinnerOptionIndex = getSpinnerIndex(selectedTimePeriod, spinnerOptions);
-        // If there is no previously-selected value, use last hour as the default.
-        if (spinnerOptionIndex == -1) {
-            spinnerOptionIndex = getSpinnerIndex(TimePeriod.LAST_HOUR, spinnerOptions);
-        }
-        assert spinnerOptionIndex != -1;
-        spinner.setOptions(spinnerOptions, spinnerOptionIndex);
-        spinner.setOnPreferenceChangeListener(this);
-
         // Text for sign-out option.
         updateSignOutOfChromeText();
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index 52f3038..5dd3b03 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -418,7 +418,7 @@
         @Override
         public int handleBackPress() {
             mIsInProgress = false;
-            if (mIsGestureMode) {
+            if (mIsGestureMode && mBackGestureInProgress) {
                 BackPressMetrics.recordNavStatusDuringGesture(
                         mStartNavDuringOngoingGesture, mActivity.getWindow());
                 BackPressMetrics.recordPredictiveGestureNav(
@@ -433,6 +433,7 @@
                 res = ToolbarManager.this.handleBackPress();
             }
             mBackGestureInProgress = false;
+            mIsGestureMode = false;
             mHandler = null;
             return res;
         }
@@ -445,15 +446,17 @@
         @Override
         public void handleOnBackCancelled() {
             mIsInProgress = false;
-            if (mIsGestureMode) {
+            if (mIsGestureMode && mBackGestureInProgress) {
                 BackPressMetrics.recordNavStatusDuringGesture(
                         mStartNavDuringOngoingGesture, mActivity.getWindow());
                 BackPressMetrics.recordPredictiveGestureNav(
                         mHandler != null, PredictiveGestureNavPhase.CANCELLED);
             }
+            if (mHandler != null) {
+                mHandler.onBackCancelled(mIsGestureMode);
+            }
             mBackGestureInProgress = false;
-            if (mHandler == null) return;
-            mHandler.onBackCancelled(mIsGestureMode);
+            mIsGestureMode = false;
             mHandler = null;
         }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataTest.java
index e0caecc..e4df694 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataTest.java
@@ -96,6 +96,7 @@
                             new BrowsingDataCounterBridge(
                                     ProfileManager.getLastUsedRegularProfile(),
                                     callback,
+                                    TimePeriod.LAST_HOUR,
                                     BrowsingDataType.SITE_DATA,
                                     ClearBrowsingDataTab.ADVANCED);
                 });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentTest.java
index e1a6f16..9709d6f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
@@ -377,10 +378,13 @@
         return datatypes;
     }
 
-    /** Tests that changing the time interval for deletion affects the delete request. */
+    /**
+     * Tests that changing the time interval for a deletion changes the option prefs of Clear
+     * Browsing Data and affects the delete request if the deletion goes through.
+     */
     @Test
     @MediumTest
-    public void testClearTimeInterval() throws Exception {
+    public void testTimeIntervalChangedAndDelete() throws Exception {
         setDataTypesToClear(DialogOption.CLEAR_CACHE);
 
         final ClearBrowsingDataFragment preferences =
@@ -407,6 +411,40 @@
                         any(),
                         any(),
                         any());
+
+        // Verify the preferences are saved if the deletion goes through.
+        verify(mBrowsingDataBridgeMock)
+                .setBrowsingDataDeletionTimePeriod(
+                        eq(expectedProfile), anyInt(), eq(TimePeriod.LAST_HOUR));
+        verify(mBrowsingDataBridgeMock)
+                .setBrowsingDataDeletionPreference(
+                        eq(expectedProfile), eq(BrowsingDataType.CACHE), anyInt(), eq(true));
+    }
+
+    /**
+     * Tests that changing the time interval for a deletion does not change the option prefs of
+     * Clear Browsing Data if the deletion doesn't go through.
+     */
+    @Test
+    @MediumTest
+    public void testTimeIntervalChangedAndDismiss() throws Exception {
+        setDataTypesToClear(DialogOption.CLEAR_CACHE);
+
+        final ClearBrowsingDataFragment preferences =
+                (ClearBrowsingDataFragment) startPreferences().getMainFragment();
+        final Profile expectedProfile = preferences.getProfile();
+
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> {
+                    changeTimePeriodTo(preferences, TimePeriod.LAST_HOUR);
+                });
+
+        // Verify the preferences are not set if the deletion doesn't go through.
+        verify(mBrowsingDataBridgeMock, never())
+                .setBrowsingDataDeletionTimePeriod(any(), anyInt(), anyInt());
+        verify(mBrowsingDataBridgeMock, never())
+                .setBrowsingDataDeletionPreference(
+                        eq(expectedProfile), anyInt(), anyInt(), anyBoolean());
     }
 
     /** Selects the specified time for browsing data removal. */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/PasswordsPreferenceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/PasswordsPreferenceTest.java
index 6528dc4..1918677 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/PasswordsPreferenceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/PasswordsPreferenceTest.java
@@ -101,7 +101,7 @@
         when(mPasswordManagerUtilBridgeJniMock.getPasswordAccessLossWarningType(any()))
                 .thenReturn(mWarningType);
 
-        SettingsStation page = mEntryPoints.startMainSettingsNonBatched();
+        SettingsStation<MainSettings> page = mEntryPoints.startMainSettingsNonBatched();
         PreferenceFacility passwordsPref = page.scrollToPref(MainSettings.PREF_PASSWORDS);
 
         mRenderTestRule.render(passwordsPref.getPrefView(), "passwords_preference");
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h
index 6203208..c4f4e8d 100644
--- a/chrome/app/chrome_command_ids.h
+++ b/chrome/app/chrome_command_ids.h
@@ -405,6 +405,8 @@
 #define IDC_CONTENT_CONTEXT_SEARCHWEBFOR 50191
 #define IDC_CONTENT_CONTEXT_SEARCHWEBFORNEWTAB 50192
 #define IDC_CONTENT_CONTEXT_LENS_OVERLAY 50193
+// Use passkey from another device from the top level of context menu.
+#define IDC_CONTENT_CONTEXT_USE_PASSKEY_FROM_ANOTHER_DEVICE 50194
 // Open with items.
 #define IDC_CONTENT_CONTEXT_OPEN_WITH1 50200
 #define IDC_CONTENT_CONTEXT_OPEN_WITH2 50201
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 5462051..3eb5c8dd4 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -5448,6 +5448,27 @@
   <message name="IDS_BRUSCHETTA_INSTALLER_CLEANING_UP_MESSAGE" desc="Message while the installer is cleaning up a failed install.">
     Install failed, cleaning up
   </message>
+  <message name="IDS_BRUSCHETTA_RESULT_UNKNOWN" desc="Bruschetta (codename) unknown result.">
+    Unknown result.
+  </message>
+  <message name="IDS_BRUSCHETTA_RESULT_SUCCESS" desc="Bruschetta (codename) result for success.">
+    Success.
+  </message>
+  <message name="IDS_BRUSCHETTA_RESULT_DLC_INSTALL_ERROR" desc="Bruschetta (codename) result for error installing DLC.">
+    Error installing DLC (oftentimes a reboot is needed, check Settings\>\>About ChromeOS for more information).
+  </message>
+  <message name="IDS_BRUSCHETTA_RESULT_START_VM_FAILED" desc="Bruschetta (codename) result for when VM fails to start.">
+    Starting VM failed.
+  </message>
+  <message name="IDS_BRUSCHETTA_RESULT_TIMEOUT" desc="Bruschetta (codename) result for a timeout.">
+    Timeout when booting or reconnecting to VM.
+  </message>
+  <message name="IDS_BRUSCHETTA_RESULT_FORBIDDEN_BY_POLICY" desc="Bruschetta (codename) result for when Bruschetta (codename) is forbidden by policy.">
+    Forbidden by policy.
+  </message>
+  <message name="IDS_BRUSCHETTA_RESULT_CONCIERGE_UNAVAILABLE" desc="Bruschetta (codename) result for when concierge service is unavailable.">
+    Concierge service is unavailable.
+  </message>
   <message name="IDS_BRUSCHETTA_UNINSTALLER_TITLE" desc="Title of the Bruschetta (codename) uninstaller, a dialog for uninstalling Bruschetta, the associated VM and files.">
     Remove <ph name="VM_NAME">$1<ex>Bruschetta</ex></ph>
   </message>
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 0889d3aa..2d49939 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -9701,6 +9701,12 @@
       <message name="IDS_DECLUTTER_EMPTY_BODY" desc="The body text for the declutter empty state UI">
         No inactive tabs right now
       </message>
+      <message name="IDS_DUPLICATE_ITEM_TITLE_SINGLE" desc="The title for an item in the duplicate tabs list with 1 duplicate">
+        <ph name="URL">$1<ex>google.com</ex></ph> • 1 duplicate
+      </message>
+      <message name="IDS_DUPLICATE_ITEM_TITLE_MULTI" desc="The title for an item in the duplicate tabs list with multiple duplicates">
+        <ph name="URL">$1<ex>google.com</ex></ph> • <ph name="DUPLICATE_COUNT">$2<ex>2</ex></ph> duplicates
+      </message>
       <message name="IDS_TOOLTIP_TAB_DECLUTTER" desc="The tooltip for the Tab Declutter button.">
         Review inactive tabs?
       </message>
diff --git a/chrome/app/generated_resources_grd/IDS_DECLUTTER_DUPLICATE_BODY.png.sha1 b/chrome/app/generated_resources_grd/IDS_DECLUTTER_DUPLICATE_BODY.png.sha1
index 53adf0e2d..8a9c971 100644
--- a/chrome/app/generated_resources_grd/IDS_DECLUTTER_DUPLICATE_BODY.png.sha1
+++ b/chrome/app/generated_resources_grd/IDS_DECLUTTER_DUPLICATE_BODY.png.sha1
@@ -1 +1 @@
-acc62ee10c8dea96dc45def09fa94fc51b7ce22b
\ No newline at end of file
+acc62ee10c8dea96dc45def09fa94fc51b7ce22b
diff --git a/chrome/app/generated_resources_grd/IDS_DECLUTTER_DUPLICATE_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_DECLUTTER_DUPLICATE_TITLE.png.sha1
index 53adf0e2d..8a9c971 100644
--- a/chrome/app/generated_resources_grd/IDS_DECLUTTER_DUPLICATE_TITLE.png.sha1
+++ b/chrome/app/generated_resources_grd/IDS_DECLUTTER_DUPLICATE_TITLE.png.sha1
@@ -1 +1 @@
-acc62ee10c8dea96dc45def09fa94fc51b7ce22b
\ No newline at end of file
+acc62ee10c8dea96dc45def09fa94fc51b7ce22b
diff --git a/chrome/app/generated_resources_grd/IDS_DECLUTTER_INACTIVE_BODY.png.sha1 b/chrome/app/generated_resources_grd/IDS_DECLUTTER_INACTIVE_BODY.png.sha1
index fd38894..90ea925 100644
--- a/chrome/app/generated_resources_grd/IDS_DECLUTTER_INACTIVE_BODY.png.sha1
+++ b/chrome/app/generated_resources_grd/IDS_DECLUTTER_INACTIVE_BODY.png.sha1
@@ -1 +1 @@
-6953db9903ea7833e274a1a266e92fa3e93a0cf1
\ No newline at end of file
+6953db9903ea7833e274a1a266e92fa3e93a0cf1
diff --git a/chrome/app/generated_resources_grd/IDS_DUPLICATE_ITEM_TITLE_MULTI.png.sha1 b/chrome/app/generated_resources_grd/IDS_DUPLICATE_ITEM_TITLE_MULTI.png.sha1
new file mode 100644
index 0000000..37a2d3f
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_DUPLICATE_ITEM_TITLE_MULTI.png.sha1
@@ -0,0 +1 @@
+453f2a8b36f3edf1d33b58e10a78babb471bf13b
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_DUPLICATE_ITEM_TITLE_SINGLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_DUPLICATE_ITEM_TITLE_SINGLE.png.sha1
new file mode 100644
index 0000000..b43377972
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_DUPLICATE_ITEM_TITLE_SINGLE.png.sha1
@@ -0,0 +1 @@
+6f904b3e2a8226d9d309a55a39fe04094ea33f2b
\ No newline at end of file
diff --git a/chrome/app/resources/chromium_strings_ka.xtb b/chrome/app/resources/chromium_strings_ka.xtb
index ed46d88..481b76a9 100644
--- a/chrome/app/resources/chromium_strings_ka.xtb
+++ b/chrome/app/resources/chromium_strings_ka.xtb
@@ -95,6 +95,7 @@
 <translation id="2199210295479376551">ანგარიშის ამოშლა Chromium-იდან</translation>
 <translation id="2210682093923538346">სახიფათო საიტი Chromium-მა ამოშალა შეტყობინებები.</translation>
 <translation id="2236949375853147973">ჩემი აქტივობა</translation>
+<translation id="2238130810669087193">შედით Chromium-ში, რომ მიიღოთ მისამართები და სხვა მონაცემები თქვენს ყველა მოწყობილობაზე. შესვლის შემდეგ ეს მისამართი შეინახება თქვენს Google ანგარიშში.</translation>
 <translation id="2240214816234246077">ბოლო დროს არ ყოფილხართ. Chromium-მა ამოშალა <ph name="PERMISSION_1" /> და <ph name="PERMISSION_2" /></translation>
 <translation id="2241627712206172106">თუ თქვენ გაზიარებული გაქვთ კომპიუტერი, თქვენი მეგობრები და ოჯახის წევრები შეძლებენ დამოუკიდებლად დათვალიერებას და Chromium-ის დაყენებას სურვილისამებრ.</translation>
 <translation id="2313870531055795960">შეამოწმებს URL-ების თანხვედრას Chromium-ში შენახულ არაუსაფრთხო საიტების სიასთან. საიტის მიერ პაროლის მოპარვის მცდელობის ან თქვენ მიერ საზიანო ფაილის ჩამოტვირთვის შემთხვევაში Chromium-ის მიერ Safe Browsing-ს გაეგზავნება URL-ები და შესაბამისი გვერდის კონტენტის გარკვეული ნაწილი.</translation>
diff --git a/chrome/app/resources/chromium_strings_lo.xtb b/chrome/app/resources/chromium_strings_lo.xtb
index ef6e9da..a374a36e 100644
--- a/chrome/app/resources/chromium_strings_lo.xtb
+++ b/chrome/app/resources/chromium_strings_lo.xtb
@@ -95,6 +95,7 @@
 <translation id="2199210295479376551">ລຶບບັນຊີອອກຈາກ Chromium</translation>
 <translation id="2210682093923538346">ເວັບໄຊທີ່ເປັນອັນຕະລາຍ. Chromium ໄດ້ລຶບສິດເຂົ້າເຖິງການແຈ້ງເຕືອນອອກແລ້ວ.</translation>
 <translation id="2236949375853147973">ການເຄື່ອນໄຫວຂອງຂ້ອຍ</translation>
+<translation id="2238130810669087193">ເພື່ອຮັບທີ່ຢູ່ ແລະ ຂໍ້ມູນອື່ນໆຂອງທ່ານໃນອຸປະກອນທຸກເຄື່ອງຂອງທ່ານ, ໃຫ້ເຂົ້າສູ່ລະບົບ Chromium. ລະບົບຈະບັນທຶກທີ່ຢູ່ນີ້ໄວ້ໃນບັນຊີ Google ຂອງທ່ານຫຼັງຈາກທີ່ທ່ານເຂົ້າສູ່ລະບົບ.</translation>
 <translation id="2240214816234246077">ທ່ານບໍ່ໄດ້ເຂົ້າເບິ່ງເມື່ອບໍ່ດົນມານີ້. Chromium ໄດ້ລຶບສິດເຂົ້າເຖິງ <ph name="PERMISSION_1" /> ແລະ <ph name="PERMISSION_2" /> ອອກແລ້ວ</translation>
 <translation id="2241627712206172106">ຖ້າທ່ານແຊຣ໌ຄອມພິວເຕີ, ໝູ່​ເພື່ອນ ແລະຄອບຄົວຂອງທ່ານ ສາມາດທ່ອງເນັດໄດ້ແຍກຕ່າງຫາກ ແລະຕັ້ງ Chromium ໄດ້ຕາມ​ແບບທີ່ພວກເຂົາຕ້ອງການ.</translation>
 <translation id="2313870531055795960">ກວດສອບ URL ກັບລາຍຊື່ເວັບໄຊທີ່ບໍ່ປອດໄພທີ່ຈັດເກັບໄວ້ໃນ Chromium. ຖ້າມີເວັບໄຊໃດໜຶ່ງພະຍາຍາມລັກເອົາລະຫັດຜ່ານຂອງທ່ານ ຫຼື ເມື່ອທ່ານດາວໂຫຼດໄຟລ໌ອັນຕະລາຍ, Chromium ອາດສົ່ງ URL, ຮວມທັງເນື້ອຫາບາງສ່ວນຂອງໜ້າໄປໃຫ້ Safe Browsing.</translation>
diff --git a/chrome/app/resources/chromium_strings_zh-HK.xtb b/chrome/app/resources/chromium_strings_zh-HK.xtb
index 96ea4d4..518a7bf 100644
--- a/chrome/app/resources/chromium_strings_zh-HK.xtb
+++ b/chrome/app/resources/chromium_strings_zh-HK.xtb
@@ -94,6 +94,7 @@
 <translation id="2199210295479376551">從 Chromium 移除帳戶</translation>
 <translation id="2210682093923538346">危險網站。Chromium 已移除通知權限。</translation>
 <translation id="2236949375853147973">我的活動</translation>
+<translation id="2238130810669087193">如要在所有裝置上使用你的地址和其他資料,請登入 Chromium。登入後,這個地址就會儲存到 Google 帳戶。</translation>
 <translation id="2240214816234246077">由於最近沒有瀏覽記錄,Chromium 已移除<ph name="PERMISSION_1" />和<ph name="PERMISSION_2" />權限</translation>
 <translation id="2241627712206172106">如果您與親朋好友共用電腦,每個人均可享有獨立的瀏覽空間,依照自己的偏好設定 Chromium。</translation>
 <translation id="2313870531055795960">使用儲存在 Chromium 中的不安全網站清單來檢查網址。如果有網站試圖盜取您的密碼,或當您下載有害檔案時,Chromium 亦可能將網址 (包括部分網頁內容) 傳送至「安全瀏覽」功能。</translation>
diff --git a/chrome/app/resources/chromium_strings_zh-TW.xtb b/chrome/app/resources/chromium_strings_zh-TW.xtb
index e5b0cbe..c139848 100644
--- a/chrome/app/resources/chromium_strings_zh-TW.xtb
+++ b/chrome/app/resources/chromium_strings_zh-TW.xtb
@@ -92,6 +92,7 @@
 <translation id="2199210295479376551">從 Chromium 中移除帳戶</translation>
 <translation id="2210682093923538346">危險網站。Chromium 已移除通知權限。</translation>
 <translation id="2236949375853147973">我的活動</translation>
+<translation id="2238130810669087193">如要在所有裝置上使用你的地址和其他資料,請登入 Chromium。登入後,這個地址就會儲存到 Google 帳戶。</translation>
 <translation id="2240214816234246077">由於近期沒有造訪記錄,Chromium 已移除「<ph name="PERMISSION_1" />」和「<ph name="PERMISSION_2" />」權限</translation>
 <translation id="2241627712206172106">如果你與親朋好友共用電腦,人人皆可享有獨立的瀏覽空間,依照自己的偏好設定 Chromium。</translation>
 <translation id="2313870531055795960">可使用儲存在 Chromium 中的不安全網站清單檢查網址。如果有網站試圖竊取你的密碼,或當你下載有害檔案時,Chromium 可能也會將網址 (包括部分網頁內容) 傳送給安全瀏覽功能。</translation>
diff --git a/chrome/app/resources/generated_resources_ar.xtb b/chrome/app/resources/generated_resources_ar.xtb
index 4deda3f7..5561943 100644
--- a/chrome/app/resources/generated_resources_ar.xtb
+++ b/chrome/app/resources/generated_resources_ar.xtb
@@ -7201,7 +7201,7 @@
 <translation id="6122095009389448667">مواصلة حظر الموقع الإلكتروني هذا من الاطلاع على الحافظة</translation>
 <translation id="6122513630797178831">حفظ رمز التحقّق من البطاقة</translation>
 <translation id="6122600716821516697">هل تريد مشاركة الملف مع هذا الجهاز؟</translation>
-<translation id="6122831415929794347">هل تريد إيقاف "التصفُّح الآمن"؟</translation>
+<translation id="6122831415929794347">هل المطلوب إيقاف "التصفُّح الآمن"؟</translation>
 <translation id="6124650939968185064">تعتمد الإضافات التالية على هذه الإضافة:</translation>
 <translation id="6124698108608891449">يحتاج هذا الموقع الإلكتروني إلى مزيد من الأذونات.</translation>
 <translation id="6125479973208104919">عذرًا، ستحتاج إلى إضافة حسابك إلى جهاز <ph name="DEVICE_TYPE" /> هذا مرة أخرى.</translation>
@@ -9690,7 +9690,7 @@
 <translation id="7923564237306226146">‏اكتملت ترقية نظام التشغيل Linux</translation>
 <translation id="7924075559900107275">إصدار مرشَّح للدعم الطويل الأمد</translation>
 <translation id="7924358170328001543">خطأ في إعادة توجيه المنفذ</translation>
-<translation id="7925108652071887026">ملء البيانات تلقائيًا</translation>
+<translation id="7925108652071887026">بيانات الملء التلقائي</translation>
 <translation id="792514962475806987">مستوى التكبير الذي تم إرساؤه:</translation>
 <translation id="7925285046818567682">في انتظار <ph name="HOST_NAME" />‏ ...</translation>
 <translation id="7926423016278357561">لم يكن هذا أنا.</translation>
diff --git a/chrome/app/resources/generated_resources_as.xtb b/chrome/app/resources/generated_resources_as.xtb
index 7b062923..2a36b2690 100644
--- a/chrome/app/resources/generated_resources_as.xtb
+++ b/chrome/app/resources/generated_resources_as.xtb
@@ -1502,6 +1502,7 @@
 <translation id="202352106777823113">ডাউনল’ডৰ বাবে অতি বেছি সময় লাগিছে আৰু নেটৱর্ক সম্পর্কীয় সমস্যাৰ বাবে ই বাধাপ্ৰাপ্ত হৈছে।</translation>
 <translation id="2024195579772565064">সন্ধানৰ ইঞ্জিন মচক</translation>
 <translation id="202500043506723828">EID</translation>
+<translation id="2025123106058020990">সঠিকতাৰ ক্লিক</translation>
 <translation id="2025632980034333559"><ph name="APP_NAME" /> ক্রেশ্ব হ'ল। এক্সটেনশ্বনটো পুনৰ ল'ড কৰিবলৈ এই বেলুনটোত ক্লিক কৰক।</translation>
 <translation id="2026377162111110983">অঞ্চলৰ কণ্ঠধ্বনি</translation>
 <translation id="2028449514182362831">ম'শ্বন ছেন্সৰ আৱশ্যক হোৱা সুবিধাসমূহে কাম নকৰিব</translation>
@@ -4760,6 +4761,7 @@
 <translation id="4324577459193912240">ফাইলটো অসম্পূৰ্ণ</translation>
 <translation id="4325237902968425115"><ph name="LINUX_APP_NAME" /> আনইনষ্টল কৰি থকা হৈছে...</translation>
 <translation id="4325433082696797523">ষ্ট’ৰেজ আৰু পাৱাৰ</translation>
+<translation id="4325515113816851466">আপুনি ছাইন আউট কৰাৰ পাছত আপোনাৰ অভিভাৱকৰ পচন্দসমূহ প্ৰয়োগ নহ’ব</translation>
 <translation id="4326146840124313313">Chromeৰ আটাইতকৈ বৰ্ধিত সুৰক্ষাৰ সুবিধাটোৱে আপোনাক বিপজ্জনক ৱেবছাইট, ডাউনল’ড আৰু এক্সটেনশ্বনসমূহৰ পৰা সুৰক্ষিত কৰিবলৈ অধিক কাৰ্য কৰে</translation>
 <translation id="4327380114687339519">এক্সটেনশ্বনৰ মেনু</translation>
 <translation id="4330191372652740264">বৰফৰ সৈতে পানী</translation>
@@ -4882,6 +4884,7 @@
 <translation id="4412992751769744546">তৃতীয় পক্ষৰ কুকিৰ অনুমতি দিয়ক</translation>
 <translation id="4413087696295876280">ChromeOS Flex ডিভাইচৰ তথ্য আৰু ডেটা পঢ়া</translation>
 <translation id="44137799675104237">স্বাভাৱিক কণ্ঠস্বৰৰে পাঠ বাৰ্তাটো শুনক</translation>
+<translation id="4414051792721275732">আপুনি ক্লিক কৰিবলৈ কোনো নিৰ্দেশ সম্পাদন কৰিলে অধিক নিয়ন্ত্ৰণ প্ৰদান কৰিবলৈ মাউছৰ গতিবেগ হ্ৰাস পাব। ক্লিকটো সম্পূৰ্ণ কৰিবলৈ নিৰ্দেশটো সম্পাদন কৰক।</translation>
 <translation id="441418754432585599"><ph name="MODIFIER_ONE" /> + <ph name="MODIFIER_TWO" /> + <ph name="KEY" /></translation>
 <translation id="44141919652824029">"<ph name="APP_NAME" />"ক আপোনাৰ সংলগ্ন হৈ থকা ইউএছবি ডিভাইচৰ তালিকাখন এক্সেছ কৰিব দিবনে?</translation>
 <translation id="4414232939543644979">নতুন &amp;ইনক'গনিট' ৱিণ্ড'</translation>
@@ -6210,6 +6213,7 @@
 <translation id="5389224261615877010">ৰামধেনু</translation>
 <translation id="5389626883706033615">ছাইটসমূহে আপোনাৰ বিষয়ে ছেভ কৰা তথ্য ব্যৱহাৰ কৰিবলৈ অনুমতি বিচৰাৰ পৰা অৱৰোধ কৰা হৈছে</translation>
 <translation id="5389794555912875905">অসুৰক্ষিত ছাইটসমূহলৈ যোৱাৰ পূৰ্বে সকীয়নি চাওক (চুপাৰিছ কৰা)</translation>
+<translation id="5389943529251318913">মাউছৰ গতিবেগ হ্ৰাস কৰক</translation>
 <translation id="5390112241331447203">মতামতৰ ৰিপ’ৰ্টত পঠিওৱা system_logs.txt ফাইলটো অন্তৰ্ভুক্ত কৰক।</translation>
 <translation id="5390677308841849479">গাঢ় ৰঙা আৰু কমলা</translation>
 <translation id="5392192690789334093">জাননী পঠিওৱাৰ অনুমতি আছে</translation>
diff --git a/chrome/app/resources/generated_resources_da.xtb b/chrome/app/resources/generated_resources_da.xtb
index d9e886f..a7002ba3 100644
--- a/chrome/app/resources/generated_resources_da.xtb
+++ b/chrome/app/resources/generated_resources_da.xtb
@@ -9450,7 +9450,7 @@
 <translation id="7751260505918304024">Vis alle</translation>
 <translation id="7752832973194460442">Android-appoplysninger</translation>
 <translation id="7753735457098489144">Installationen mislykkedes på grund af manglende lagerplads. Slet filer fra lageret på din enhed for at frigøre plads.</translation>
-<translation id="7754704193130578113">Spørg, hvor hver enkelt fil skal gemmes, inden download begynder</translation>
+<translation id="7754704193130578113">Spørg, hvor hver enkelt fil skal gemmes, inden downloaden begynder</translation>
 <translation id="7757592200364144203">Skift navn på enheden</translation>
 <translation id="7757739382819740102">Kontakter i nærheden kan dele med dig. Godkendelse er påkrævet.</translation>
 <translation id="7757787379047923882">Tekst, der deles fra <ph name="DEVICE_NAME" /></translation>
diff --git a/chrome/app/resources/generated_resources_el.xtb b/chrome/app/resources/generated_resources_el.xtb
index b68dd292..62ebb63 100644
--- a/chrome/app/resources/generated_resources_el.xtb
+++ b/chrome/app/resources/generated_resources_el.xtb
@@ -1504,6 +1504,7 @@
 <translation id="202352106777823113">Η λήψη καθυστερούσε πολύ και διακόπηκε από το δίκτυο.</translation>
 <translation id="2024195579772565064">Διαγραφή μηχανής αναζήτησης</translation>
 <translation id="202500043506723828">EID</translation>
+<translation id="2025123106058020990">Κλικ με ακρίβεια</translation>
 <translation id="2025632980034333559">Το <ph name="APP_NAME" /> παρουσίασε πρόβλημα. Κάντε κλικ σε αυτό το πλαίσιο για να επαναλάβετε τη φόρτωση της επέκτασης.</translation>
 <translation id="2026377162111110983">Φωνή περιοχής</translation>
 <translation id="2028449514182362831">Οι λειτουργίες που πρέπει να χρησιμοποιούν αισθητήρες κίνησης δεν θα είναι διαθέσιμες.</translation>
@@ -4763,6 +4764,7 @@
 <translation id="4324577459193912240">Το αρχείο είναι ελλιπές</translation>
 <translation id="4325237902968425115">Απεγκατάσταση <ph name="LINUX_APP_NAME" />...</translation>
 <translation id="4325433082696797523">Αποθηκευτικός χώρος και ισχύς</translation>
+<translation id="4325515113816851466">Οι επιλογές του γονέα σου δεν θα ισχύουν μετά την αποσύνδεση</translation>
 <translation id="4326146840124313313">Η ισχυρότερη ασφάλεια του Chrome κάνει περισσότερα για την προστασία σας από επικίνδυνους ιστοτόπους, λήψεις και επεκτάσεις</translation>
 <translation id="4327380114687339519">Μενού επεκτάσεων</translation>
 <translation id="4330191372652740264">Παγωμένο νερό</translation>
@@ -4885,6 +4887,7 @@
 <translation id="4412992751769744546">Αποδοχή cookie τρίτου μέρους</translation>
 <translation id="4413087696295876280">Ανάγνωση πληροφοριών και δεδομένων συσκευής ChromeOS Flex</translation>
 <translation id="44137799675104237">Ακρόαση του κειμένου με φυσική φωνή</translation>
+<translation id="4414051792721275732">Όταν εκτελείτε μια κίνηση για να κάνετε κλικ, η ταχύτητα του ποντικιού θα μειωθεί, για να έχετε περισσότερο έλεγχο. Εκτελέστε ξανά την κίνηση, για να ολοκληρώσετε το κλικ.</translation>
 <translation id="441418754432585599"><ph name="MODIFIER_ONE" /> + <ph name="MODIFIER_TWO" /> + <ph name="KEY" /></translation>
 <translation id="44141919652824029">Να επιτρέπεται στην εφαρμογή "<ph name="APP_NAME" />" να λάβει τη λίστα των προσαρτημένων συσκευών USB;</translation>
 <translation id="4414232939543644979">Νέο &amp;παράθυρο ανώνυμης περιήγηση</translation>
@@ -6213,6 +6216,7 @@
 <translation id="5389224261615877010">Ουράνιο τόξο</translation>
 <translation id="5389626883706033615">Οι ιστότοποι αποκλείονται από την υποβολή αιτήματος χρήσης πληροφοριών που έχουν αποθηκεύσει σχετικά με εσάς</translation>
 <translation id="5389794555912875905">Εμφάνιση ειδοποιήσεων πριν από τη μετάβαση σε μη ασφαλείς ιστοτόπους (συνιστάται)</translation>
+<translation id="5389943529251318913">Μείωση ταχύτητας ποντικιού κατά</translation>
 <translation id="5390112241331447203">Συμπερίληψη του αρχείου system_logs.txt που στάλθηκε στις αναφορές σχολίων.</translation>
 <translation id="5390677308841849479">Σκούρο κόκκινο και πορτοκαλί</translation>
 <translation id="5392192690789334093">Επιτρέπεται η αποστολή ειδοποιήσεων</translation>
diff --git a/chrome/app/resources/generated_resources_es-419.xtb b/chrome/app/resources/generated_resources_es-419.xtb
index f43b182..1d09a42f 100644
--- a/chrome/app/resources/generated_resources_es-419.xtb
+++ b/chrome/app/resources/generated_resources_es-419.xtb
@@ -1491,6 +1491,7 @@
 <translation id="202352106777823113">La descarga estaba tardando demasiado y fue detenida por la red.</translation>
 <translation id="2024195579772565064">Borrar el motor de búsqueda</translation>
 <translation id="202500043506723828">EID</translation>
+<translation id="2025123106058020990">Clic de precisión</translation>
 <translation id="2025632980034333559"><ph name="APP_NAME" /> se ha bloqueado. Haz clic en este globo para volver a cargar la extensión.</translation>
 <translation id="2026377162111110983">Voz del área</translation>
 <translation id="2028449514182362831">No se habilitarán las funciones que necesitan sensores de movimiento.</translation>
@@ -4747,6 +4748,7 @@
 <translation id="4324577459193912240">El archivo está incompleto</translation>
 <translation id="4325237902968425115">Desinstalando <ph name="LINUX_APP_NAME" />…</translation>
 <translation id="4325433082696797523">Almacenamiento y energía</translation>
+<translation id="4325515113816851466">Las opciones de tu madre o padre no se aplicarán después de que salgas de la cuenta</translation>
 <translation id="4326146840124313313">La seguridad más sólida de Chrome realiza más acciones para protegerte contra sitios web, descargas y extensiones peligrosos.</translation>
 <translation id="4327380114687339519">Menú Extensiones</translation>
 <translation id="4330191372652740264">Agua helada</translation>
@@ -4869,6 +4871,7 @@
 <translation id="4412992751769744546">Permitir cookies de terceros</translation>
 <translation id="4413087696295876280">Leer la información y los datos del dispositivo ChromeOS Flex</translation>
 <translation id="44137799675104237">Escuchar el texto con voz natural</translation>
+<translation id="4414051792721275732">Cuando realices un gesto para hacer clic, la velocidad del mouse disminuirá para brindarte más control. Vuelve a realizar el gesto para completar el clic.</translation>
 <translation id="441418754432585599"><ph name="MODIFIER_ONE" /> + <ph name="MODIFIER_TWO" /> + <ph name="KEY" /></translation>
 <translation id="44141919652824029">¿Deseas permitir que "<ph name="APP_NAME" />" obtenga la lista de los dispositivos USB conectados?</translation>
 <translation id="4414232939543644979">Nueva ventana de &amp;incógnito</translation>
@@ -6197,6 +6200,7 @@
 <translation id="5389224261615877010">Arcoíris</translation>
 <translation id="5389626883706033615">Los sitios no podrán solicitarte usar la información que guardaron sobre ti</translation>
 <translation id="5389794555912875905">Mostrar advertencias antes de acceder a sitios no seguros (recomendado)</translation>
+<translation id="5389943529251318913">Reducir la velocidad del mouse en</translation>
 <translation id="5390112241331447203">Incluye el archivo system_logs.txt que se envía en los informes de comentarios.</translation>
 <translation id="5390677308841849479">Rojo oscuro y naranja</translation>
 <translation id="5392192690789334093">Pueden enviar notificaciones</translation>
diff --git a/chrome/app/resources/generated_resources_es.xtb b/chrome/app/resources/generated_resources_es.xtb
index e7cb9b59..26aeb55 100644
--- a/chrome/app/resources/generated_resources_es.xtb
+++ b/chrome/app/resources/generated_resources_es.xtb
@@ -972,7 +972,7 @@
 <translation id="1654580009054503925">No tiene permiso para mostrar solicitudes</translation>
 <translation id="1654713139320245449">No se han encontrado destinos de envío. ¿Necesitas ayuda?</translation>
 <translation id="1656528038316521561">Opacidad del fondo</translation>
-<translation id="1657406563541664238">Ayúdanos a mejorar <ph name="PRODUCT_NAME" /> enviando estadísticas de uso e informes sobre fallos.</translation>
+<translation id="1657406563541664238">Ayudar a mejorar <ph name="PRODUCT_NAME" /> enviando estadísticas de uso e informes sobre fallos a Google</translation>
 <translation id="1657937299377480641">Para iniciar sesión de nuevo para acceder a recursos educativos, pídele permiso a tu padre o madre</translation>
 <translation id="1658424621194652532">Esta página está accediendo al micrófono</translation>
 <translation id="1660763353352708040">Problema con el adaptador de corriente</translation>
@@ -3432,7 +3432,7 @@
 <translation id="3412265149091626468">Ir a la selección</translation>
 <translation id="3413122095806433232">Entidades emisoras de certificados: <ph name="LOCATION" /></translation>
 <translation id="3414952576877147120">Tamaño:</translation>
-<translation id="3414966631182382431"><ph name="MANAGER" /> <ph name="BEGIN_LINK" />gestiona el navegador<ph name="END_LINK" /></translation>
+<translation id="3414966631182382431"><ph name="MANAGER" /> <ph name="BEGIN_LINK" />gestiona tu navegador<ph name="END_LINK" /></translation>
 <translation id="3414974735818878791">Clic central</translation>
 <translation id="3415580428903497523">Usa certificados locales importados desde tu sistema operativo</translation>
 <translation id="341589277604221596">Subtítulos automáticos: <ph name="LANGUAGE" /></translation>
@@ -7987,7 +7987,7 @@
 <translation id="6709357832553498500">Conectar con <ph name="EXTENSIONNAME" /></translation>
 <translation id="6710172959248731469">Configuración de los servicios de Google</translation>
 <translation id="6710213216561001401">Anterior</translation>
-<translation id="6710394144992407503">Comprobar si hay errores ortográficos cuando escribas texto en páginas web</translation>
+<translation id="6710394144992407503">Comprueba si hay errores ortográficos cuando escribas texto en páginas web</translation>
 <translation id="6712943853047024245">Ya has guardado una contraseña con este nombre de usuario para <ph name="WEBSITE" /></translation>
 <translation id="6713233729292711163">Añadir perfil de trabajo</translation>
 <translation id="6713441551032149301">Mantén pulsada la tecla del menú de aplicaciones para cambiar entre las teclas de función y las teclas del sistema de la fila superior</translation>
diff --git a/chrome/app/resources/generated_resources_fr.xtb b/chrome/app/resources/generated_resources_fr.xtb
index 108fe79f..22a3723 100644
--- a/chrome/app/resources/generated_resources_fr.xtb
+++ b/chrome/app/resources/generated_resources_fr.xtb
@@ -1263,7 +1263,7 @@
 <translation id="1865769994591826607">Uniquement les connexions au même site</translation>
 <translation id="186594096341696655">Diminuer le taux</translation>
 <translation id="186612162884103683">"<ph name="EXTENSION" />" dispose d'un droit d'accès en lecture et en écriture sur les images, les vidéos et les fichiers audio figurant dans les dossiers sélectionnés.</translation>
-<translation id="1867780286110144690"><ph name="PRODUCT_NAME" /> est prêt à terminer l'installation.</translation>
+<translation id="1867780286110144690"><ph name="PRODUCT_NAME" /> est prêt à terminer l'installation</translation>
 <translation id="1868553836791672080">La fonctionnalité Check-up Mots de passe n'est pas disponible dans Chromium</translation>
 <translation id="1868617395637139709">Utilisez la position pour les applis et services Android.</translation>
 <translation id="1869433484041798909">Bouton de favori</translation>
@@ -2097,7 +2097,7 @@
 <translation id="2442916515643169563">Ombre du texte</translation>
 <translation id="2443487764245141020">Les sites peuvent aussi avoir besoin d'identifier votre appareil à l'aide d'un ID</translation>
 <translation id="244475495405467108">Fermer les onglets à gauche</translation>
-<translation id="2444874983932528148">Reprenez facilement là où vous vous étiez arrêté</translation>
+<translation id="2444874983932528148">Reprenez facilement là où vous en étiez</translation>
 <translation id="2445081178310039857">Le répertoire racine de l'extension doit être indiqué.</translation>
 <translation id="2445484935443597917">Créer un profil</translation>
 <translation id="2445726032315793326">Loupe partielle</translation>
@@ -4312,7 +4312,7 @@
     <ph name="BEGIN_PARAGRAPH4" /><ph name="LINK_BEGIN" />En savoir plus sur la précision de la localisation<ph name="LINK_END" /><ph name="END_PARAGRAPH4" /></translation>
 <translation id="399179161741278232">Importés</translation>
 <translation id="3992008114154328194">Téléchargement en cours de <ph name="FILE_NAME" />, <ph name="STATUS" /></translation>
-<translation id="3993259701827857030">Sauvegarder les données</translation>
+<translation id="3993259701827857030">Sauvegarde des données</translation>
 <translation id="3993887353483242788">Synchronisez votre <ph name="DEVICE_TYPE" /> pour que vos préférences soient appliquées sur n'importe quel appareil lorsque vous vous connectez avec votre compte Google. Les préférences regroupent les applis, les paramètres, les mots de passe Wi-Fi, les langues, le fond d'écran, les raccourcis clavier, etc.</translation>
 <translation id="3994318741694670028">Malheureusement, votre ordinateur est configuré avec un ID matériel incorrect. Cela empêche l'installation des derniers correctifs de sécurité sur ChromeOS Flex et rend votre ordinateur <ph name="BEGIN_BOLD" />potentiellement vulnérable aux attaques malveillantes<ph name="END_BOLD" />.</translation>
 <translation id="3994374631886003300">Déverrouillez votre téléphone et rapprochez-le de votre <ph name="DEVICE_TYPE" /> pour le déverrouiller.</translation>
@@ -5652,7 +5652,7 @@
 <translation id="4979510648199782334">Configuration de Microsoft 365 terminée</translation>
 <translation id="4980805016576257426">Cette extension contient des logiciels malveillants.</translation>
 <translation id="4983159853748980742">Votre mot de passe n'a pas été partagé. Vérifiez votre connexion Internet et assurez-vous que vous êtes connecté à Chrome, puis réessayez.</translation>
-<translation id="4986706507552097681">Vous avez toujours la possibilité de sélectionner les éléments à synchroniser dans les paramètres. Google peut personnaliser la recherche et d'autres services en fonction de votre historique.</translation>
+<translation id="4986706507552097681">Vous pourrez toujours choisir ce que vous voulez synchroniser dans les paramètres. Google peut personnaliser la recherche et d'autres services en fonction de votre historique.</translation>
 <translation id="4986728572522335985">Cette opération supprimera toutes les données stockées sur la clé de sécurité, y compris son code</translation>
 <translation id="4987944280765486504">Votre Chromebook redémarrera une fois le téléchargement terminé, et vous pourrez poursuivre la configuration.</translation>
 <translation id="4988526792673242964">Pages</translation>
@@ -7378,7 +7378,7 @@
 <translation id="6247620186971210352">Aucune application n'a été trouvée</translation>
 <translation id="6247708409970142803"><ph name="PERCENTAGE" /> %</translation>
 <translation id="6247802389331535091">Système : <ph name="ARC_PROCESS_NAME" /></translation>
-<translation id="6248988683584659830">Rechercher</translation>
+<translation id="6248988683584659830">Rechercher dans les paramètres</translation>
 <translation id="6249200942125593849">Gérer les paramètres d'accessibilité</translation>
 <translation id="6250186368828697007">Les détails sont masqués lors du partage d'écran</translation>
 <translation id="6251870443722440887">Handles GDI</translation>
diff --git a/chrome/app/resources/generated_resources_it.xtb b/chrome/app/resources/generated_resources_it.xtb
index cf2ec42..7a21cd7 100644
--- a/chrome/app/resources/generated_resources_it.xtb
+++ b/chrome/app/resources/generated_resources_it.xtb
@@ -7989,7 +7989,7 @@
 <translation id="6709357832553498500">Connettiti utilizzando <ph name="EXTENSIONNAME" /></translation>
 <translation id="6710172959248731469">Impostazioni dei servizi Google</translation>
 <translation id="6710213216561001401">Precedente</translation>
-<translation id="6710394144992407503">Verifica la presenza di errori ortografici durante la digitazione di testo nelle pagine web</translation>
+<translation id="6710394144992407503">Verifica la presenza di errori ortografici durante la digitazione di testo nelle pagine web.</translation>
 <translation id="6712943853047024245">Hai già salvato una password con questo nome utente per <ph name="WEBSITE" /></translation>
 <translation id="6713233729292711163">Aggiungi profilo di lavoro</translation>
 <translation id="6713441551032149301">Tieni premuto il tasto Avvio app per spostarti tra i tasti funzione e i tasti della fila superiore del sistema</translation>
diff --git a/chrome/app/resources/generated_resources_ja.xtb b/chrome/app/resources/generated_resources_ja.xtb
index 886d671..16609398 100644
--- a/chrome/app/resources/generated_resources_ja.xtb
+++ b/chrome/app/resources/generated_resources_ja.xtb
@@ -8261,7 +8261,7 @@
 <translation id="6903022061658753260">このアカウントで同期をオンにしたすべての Chrome ブラウザでデータが同期されます。Chrome OS の同期オプションについては、<ph name="LINK_BEGIN" />Chrome OS の設定<ph name="LINK_END" />をご覧ください。</translation>
 <translation id="6903437476849497868">オプトアウト</translation>
 <translation id="6903590427234129279">すべて開く(<ph name="URL_COUNT" /> 件の URL)</translation>
-<translation id="6903907808598579934">同期を ON にする</translation>
+<translation id="6903907808598579934">同期をオンにする</translation>
 <translation id="6903916726032521638"><ph name="QUERY_CLUSTER_NAME" /> を検索</translation>
 <translation id="6909422577741440844">このデバイスから受信しますか?</translation>
 <translation id="6910190732484284349">ユーザー名 <ph name="USER_EMAIL" /> のパスキーを削除</translation>
diff --git a/chrome/app/resources/generated_resources_ka.xtb b/chrome/app/resources/generated_resources_ka.xtb
index a0a7b7a..5f58093 100644
--- a/chrome/app/resources/generated_resources_ka.xtb
+++ b/chrome/app/resources/generated_resources_ka.xtb
@@ -1494,6 +1494,7 @@
 <translation id="202352106777823113">ჩამოტვირთვას დიდი დრო დასჭირდა და იგი შეწყვეტილ იქნა ქსელის მიერ.</translation>
 <translation id="2024195579772565064">საძიებო სისტემის წაშლა</translation>
 <translation id="202500043506723828">EID</translation>
+<translation id="2025123106058020990">ზუსტი დაწკაპუნება</translation>
 <translation id="2025632980034333559"><ph name="APP_NAME" /> უკვე გაითიშა. დააწკაპუნეთ ამ ბურთზე გაფართოების ხელახლა ჩასატვირთად.</translation>
 <translation id="2026377162111110983">გარემოს ხმა</translation>
 <translation id="2028449514182362831">ფუნქციები, რომლებიც მოძრაობის სენსორებს საჭიროებს, არ იმუშავებს</translation>
@@ -4750,6 +4751,7 @@
 <translation id="4324577459193912240">ფაილი არასრულია</translation>
 <translation id="4325237902968425115">მიმდინარეობს <ph name="LINUX_APP_NAME" />-ის დეინსტალაცია…</translation>
 <translation id="4325433082696797523">მეხსიერება და ელკვება</translation>
+<translation id="4325515113816851466">თქვენი მშობლის არჩევანი არ იმოქმედებს სისტემიდან გასვლის შემდეგ</translation>
 <translation id="4326146840124313313">Chrome-ის ყველაზე ძლიერი დაცვა უკეთ გიცავთ სახიფათო ვებსაიტებისგან, ჩამოტვირთვებისა და გაფართოებებისგან.</translation>
 <translation id="4327380114687339519">გაფართოებების მენიუ</translation>
 <translation id="4330191372652740264">გაყინული წყალი</translation>
@@ -4872,6 +4874,7 @@
 <translation id="4412992751769744546">მეს. მხარის ქ. ფაილების დაშვება</translation>
 <translation id="4413087696295876280">ChromeOS Flex მოწყობილობის ინფორმაციისა და მონაცემების წაკითხვა</translation>
 <translation id="44137799675104237">მოუსმინეთ ბუნებრივი ხმით წარმოთქმულ ტექსტს</translation>
+<translation id="4414051792721275732">დასაწკაპუნებლად ჟესტის შესრულებისას მაუსის სიჩქარე შემცირდება, რათა უკეთ მართოთ ის. დაწკაპუნების დასასრულებლად შეასრულეთ ჟესტი ხელახლა.</translation>
 <translation id="441418754432585599"><ph name="MODIFIER_ONE" /> + <ph name="MODIFIER_TWO" /> + <ph name="KEY" /></translation>
 <translation id="44141919652824029">გსურთ, „<ph name="APP_NAME" />“-მა შეძლოს დაკავშირებული USB მოწყობილობების სიაზე წვდომა?</translation>
 <translation id="4414232939543644979">ახალი &amp;ინკოგნიტო ფანჯარა</translation>
@@ -5108,6 +5111,7 @@
 <translation id="4586275095964870617"><ph name="URL" /> ვერ გაიხსნა ალტერნატიულ ბრაუზერში. გთხოვთ, დაუკავშირდეთ თქვენი სიტემის ადმინისტრატორს.</translation>
 <translation id="4587589328781138893">საიტები</translation>
 <translation id="4588749726511456218">გადაადგილების აჩქარება. <ph name="LINK_BEGIN" />შეიტყვეთ მეტი<ph name="LINK_END" /></translation>
+<translation id="4589197033939192905"><ph name="PASSWORD_DOMAIN" /> და <ph name="DOMAIN" />, როგორც ჩანს, დაკავშირებულია ერთმანეთთან. დარწმუნდით, რომ <ph name="DOMAIN" /> სანდოა, სანამ თქვენს პაროლს გამოიყენებთ.</translation>
 <translation id="4589713469967853491">ჟურნალები წარმატებით ჩაიწერა „ჩამოტვირთვების“ კატალოგში.</translation>
 <translation id="4590785647529325123">თქვენი მოწყობილობიდან ინკოგნიტო რეჟიმში დათვალიერების ისტორია რომ წაშალოთ, დახურეთ ყველა ინკოგნიტო ჩანართი</translation>
 <translation id="459204634473266369"><ph name="PRIMARY_EMAIL" />-ში შენახული მოწყობილობები არ არის</translation>
@@ -5614,6 +5618,7 @@
 <translation id="4946998421534856407">launcher + ზემოთ მიმართული ისარი</translation>
 <translation id="4947376546135294974">მონაცემები თქვენ მიერ მონახულებული საიტიდან</translation>
 <translation id="4950100687509657457">პროფილის შექმნა</translation>
+<translation id="4950360215042327246">[ჩანაცვლების ველის ფრაზა]</translation>
 <translation id="495164417696120157">{COUNT,plural, =1{ფაილი}other{# ფაილი}}</translation>
 <translation id="495170559598752135">ქმედებები</translation>
 <translation id="4951966678293618079">არასოდეს შეინახოს პაროლები ამ საიტისთვის</translation>
@@ -5752,6 +5757,7 @@
 <translation id="5061531353537614467">ტუნდრა</translation>
 <translation id="5062930723426326933">შესვლა ვერ განხორციელდა. დაუკავშირდით ინტერნეტს და ხელახლა სცადეთ.</translation>
 <translation id="5063480226653192405">გამოყენება</translation>
+<translation id="5064921774605267982"><ph name="PROFILE_NAME" />-ის პროფილის გახსნა. ამ პროფილს მართავს თქვენი ორგანიზაცია.</translation>
 <translation id="5065775832226780415">Smart Lock</translation>
 <translation id="5066100345385738837">მართეთ დაცული DNS ChromeOS-ის პარამეტრებიდან</translation>
 <translation id="5066534201484101197">საზღვრის მიღმა გადაადგილდით გვერდებს შორის ნავიგაციისთვის</translation>
@@ -6200,6 +6206,7 @@
 <translation id="5389224261615877010">ცისარტყელისფერი</translation>
 <translation id="5389626883706033615">საიტებისთვის დაბლოკილია მათ მიერ თქვენ შესახებ შენახული ინფორმაციის გამოყენების თხოვნის შესაძლებლობა</translation>
 <translation id="5389794555912875905">გაფრთხილებების ნახვა დაუცველ საიტებზე გადასვლამდე (რეკომენდებული)</translation>
+<translation id="5389943529251318913">მაუსის სიჩქარის შემცირება:</translation>
 <translation id="5390112241331447203">გამოხმაურების ანგარიშებში გაგზავნილი system_logs.txt ფაილის დართვა.</translation>
 <translation id="5390677308841849479">მუქი წითელი და ნარინჯისფერი</translation>
 <translation id="5392192690789334093">შეტყობინებების გამოგზავნა დაშვებულია</translation>
@@ -7408,6 +7415,7 @@
 <translation id="6266984048393265562">პროფილის მორგება</translation>
 <translation id="6267166720438879315">თქვენი ვინაობის ავთენტიფიკაციისათვის, აირჩიეთ სერთიფიკატი <ph name="HOST_NAME" /></translation>
 <translation id="6268252012308737255">გახსნა <ph name="APP" />-ით</translation>
+<translation id="6269050081341530851">დუბლიკატების დახურვისას შეინახება უძველესი ასლი</translation>
 <translation id="6270309713620950855">შეხსენების დადუმება</translation>
 <translation id="6270391203985052864">საიტებს შეუძლიათ შეტყობინებების გამოგზავნის თხოვნა</translation>
 <translation id="6270486800167535228">გაფართოება ჩამაგრებულია. აირჩიეთ მეტი ვარიანტის სანახავად</translation>
@@ -7949,6 +7957,7 @@
 <translation id="6679947539429331601">12 საათით დამალვა</translation>
 <translation id="6680442031740878064">ხელმისაწვდომია: <ph name="AVAILABLE_SPACE" /></translation>
 <translation id="6680650203439190394">სიხშირე</translation>
+<translation id="6682261381769522894"><ph name="WINDOW_TITLE" /> — [ჩანაცვლების ველის ფრაზა]</translation>
 <translation id="6683022854667115063">ყურსასმენები</translation>
 <translation id="6683087162435654533">ყველა ჩანართის &amp;აღდგენა</translation>
 <translation id="6683433919380522900">ნებართვად განსაზღვრულია „<ph name="PERMISSION_STATE" />“</translation>
@@ -8842,6 +8851,7 @@
 <translation id="7330533963640151632">ფუნქციის „<ph name="FEATURE_NAME" />“ პარამეტრები <ph name="USER_NAME" />-ის მოწყობილობისთვის, გაზიარება ხორციელდება <ph name="USER_EMAIL" />-ის ანგარიშით.</translation>
 <translation id="7331646370422660166">alt + ქვემოთ მიმართული ისარი</translation>
 <translation id="7332053360324989309">Dedicated Worker: <ph name="SCRIPT_URL" /></translation>
+<translation id="7332138995369063163">დუბლირებული ჩანართები</translation>
 <translation id="7333388112938984914">ფაილები ვერ აიტვირთება, სანამ ლიმიტირებულ კავშირს იყენებთ.</translation>
 <translation id="7333669215417470379">თქვენი აპებისა და პარამეტრების სარეზერვო ასლების შექმნა და აღდგენა</translation>
 <translation id="7335974957018254119">მართლწერის შემოწმების გამოყენება შემდეგისთვის:</translation>
diff --git a/chrome/app/resources/generated_resources_lo.xtb b/chrome/app/resources/generated_resources_lo.xtb
index 47d26e0a..ad7a1524 100644
--- a/chrome/app/resources/generated_resources_lo.xtb
+++ b/chrome/app/resources/generated_resources_lo.xtb
@@ -1501,6 +1501,7 @@
 <translation id="202352106777823113">ການດາວໂຫຼດໃຊ້ເວລາດົນເກີນໄປ ແລະເຄືອຂ່າຍຢຸດໄວ້ແລ້ວ.</translation>
 <translation id="2024195579772565064">ລຶບໂປຣແກຣມຊອກຫາ</translation>
 <translation id="202500043506723828">EID</translation>
+<translation id="2025123106058020990">ການຄລິກຢ່າງຖືກຕ້ອງ</translation>
 <translation id="2025632980034333559"><ph name="APP_NAME" /> ​ໄດ້​ເກີດຂັດຂ້ອງ. ຄລິກປູມເປົ້ານີ້ເພື່ອໂຫຼດສ່ວນຂະຫຍາຍຄືນໃໝ່.</translation>
 <translation id="2026377162111110983">ສຽງໃນພື້ນທີ່</translation>
 <translation id="2028449514182362831">ຄຸນສົມບັດທີ່ຕ້ອງການໃຊ້ເຊັນເຊີກວດຈັບການເຄື່ອນໄຫວຈະໃຊ້ບໍ່ໄດ້</translation>
@@ -4762,6 +4763,7 @@
 <translation id="4324577459193912240">ໄຟລ໌ບໍ່ສົມບູນ</translation>
 <translation id="4325237902968425115">ກໍາລັງຖອນການຕິດຕັ້ງ <ph name="LINUX_APP_NAME" />...</translation>
 <translation id="4325433082696797523">ບ່ອນຈັດເກັບຂໍ້ມູນ ແລະ ພະລັງງານ</translation>
+<translation id="4325515113816851466">ຕົວເລືອກຂອງຜູ້ປົກຄອງຂອງທ່ານຈະບໍ່ມີຜົນນຳໃຊ້ຫຼັງຈາກທີ່ທ່ານອອກຈາກລະບົບ</translation>
 <translation id="4326146840124313313">ຄວາມປອດໄພທີ່ເຂັ້ມແຂງທີ່ສຸດຂອງ Chrome ເຮັດວຽກຫຼາຍຂຶ້ນເພື່ອປົກປ້ອງທ່ານຈາກເວັບໄຊ, ການດາວໂຫຼດ ແລະ ສ່ວນຂະຫຍາຍທີ່ເປັນອັນຕະລາຍ</translation>
 <translation id="4327380114687339519">ເມນູສ່ວນຂະຫຍາຍ</translation>
 <translation id="4330191372652740264">ນໍ້າກ້ອນ</translation>
@@ -4884,6 +4886,7 @@
 <translation id="4412992751769744546">ອະ​ນຸ​ຍາດ​ຄຸກ​ກີ້​ບຸກ​ຄົນ​ທີ​ສາມ</translation>
 <translation id="4413087696295876280">ອ່ານຂໍ້ມູນອຸປະກອນ ChromeOS Flex ແລະ ຂໍ້ມູນ</translation>
 <translation id="44137799675104237">ຟັງການອ່ານຂໍ້ຄວາມດ້ວຍສຽງທີ່ເປັນທຳມະຊາດ</translation>
+<translation id="4414051792721275732">ເມື່ອທ່ານເຮັດຕາມທ່າທາງເພື່ອຄລິກ, ຄວາມໄວເມົ້າຈະຫຼຸດລົງເພື່ອໃຫ້ຄວບຄຸມໄດ້ຫຼາຍຂຶ້ນ. ກະລຸນາເຮັດຕາມທ່າທາງອີກຄັ້ງເພື່ອຄລິກໃຫ້ສຳເລັດ.</translation>
 <translation id="441418754432585599"><ph name="MODIFIER_ONE" /> + <ph name="MODIFIER_TWO" /> + <ph name="KEY" /></translation>
 <translation id="44141919652824029">ອະນຸຍາດໃຫ້ "<ph name="APP_NAME" />" ໄດ້ຮັບລາຍການອຸປະກອນ USB ທີ່ຄັດຕິດຂອງທ່ານບໍ?</translation>
 <translation id="4414232939543644979">ໜ້າ​ຕ່າງທີ່ບໍ່ເຜີຍຕົວໃໝ່</translation>
@@ -5120,6 +5123,7 @@
 <translation id="4586275095964870617">ບໍ່ສາມາດເປີດ <ph name="URL" /> ໃນໂປຣແກຣມທ່ອງເວັບສຳຮອງໄດ້ ກະລຸນາຕິດຕໍ່ຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ.</translation>
 <translation id="4587589328781138893">ເວັບໄຊ</translation>
 <translation id="4588749726511456218">ການເລັ່ງຄວາມໄວຂອງການເລື່ອນ <ph name="LINK_BEGIN" />ສຶກສາເພີ່ມເຕີມ<ph name="LINK_END" /></translation>
+<translation id="4589197033939192905"><ph name="PASSWORD_DOMAIN" /> ແລະ <ph name="DOMAIN" /> ເບິ່ງຄືຈະກ່ຽວຂ້ອງກັນ. ກວດສອບວ່າທ່ານເຊື່ອຖື <ph name="DOMAIN" /> ໄດ້ກ່ອນທີ່ຈະໃຊ້ລະຫັດຜ່ານຂອງທ່ານ.</translation>
 <translation id="4589713469967853491">ຂຽນບັນທຶກໃສ່ແຟ້ມການດາວໂຫຼດສຳເລັດແລ້ວ.</translation>
 <translation id="4590785647529325123">ເພື່ອລຶບປະຫວັດການທ່ອງເວັບໃນໂໝດບໍ່ເປີດເຜີຍຕົວຕົນອອກຈາກອຸປະກອນຂອງທ່ານ, ໃຫ້ປິດແຖບບໍ່ເປີດເຜີຍຕົວຕົນທັງໝົດ</translation>
 <translation id="459204634473266369">ບໍ່ມີອຸປະກອນຖືກບັນທຶກໄວ້ໃນ <ph name="PRIMARY_EMAIL" /></translation>
@@ -5626,6 +5630,7 @@
 <translation id="4946998421534856407">ຕົວເປີດໃຊ້ + ລູກສອນຂຶ້ນ</translation>
 <translation id="4947376546135294974">ຂໍ້ມູນຈາກເວັບໄຊທີ່ທ່ານກຳລັງເຂົ້າເບິ່ງ</translation>
 <translation id="4950100687509657457">ສ້າງໂປຣໄຟລ໌</translation>
+<translation id="4950360215042327246">[ສະຕຣິງຕົວຍຶດບ່ອນ]</translation>
 <translation id="495164417696120157">{COUNT,plural, =1{ໄຟລ໌}other{# ໄຟລ໌}}</translation>
 <translation id="495170559598752135">ການກະທໍາ</translation>
 <translation id="4951966678293618079">ບໍ່ບັນທຶກລະຫັດຜ່ານສຳລັບເວັບໄຊນີ້ເດັດຂາດ</translation>
@@ -5764,6 +5769,7 @@
 <translation id="5061531353537614467">ທັນດຣາ</translation>
 <translation id="5062930723426326933">ລົງຊື່ເຂົ້າ​ໃຊ້ບໍ່ສໍາເລັດ, ກະລຸນາເຊື່ອມຕໍ່ກັບອິນເຕີເນັດ ແລະລອງໃໝ່ອີກ.</translation>
 <translation id="5063480226653192405">ການນໍາໃຊ້</translation>
+<translation id="5064921774605267982">ເປີດໂປຣໄຟລ໌ຂອງ <ph name="PROFILE_NAME" />. ຜູ້ປົກຄອງຂອງທ່ານເປັນຜູ້ຈັດການໂປຣໄຟລ໌ນີ້.</translation>
 <translation id="5065775832226780415">Smart Lock</translation>
 <translation id="5066100345385738837">ຈັດການ DNS ທີ່ປອດໄພໃນການຕັ້ງຄ່າ ChromeOS</translation>
 <translation id="5066534201484101197">ເລື່ອນກາຍເພື່ອນຳທາງລະຫວ່າງໜ້າ</translation>
@@ -6212,6 +6218,7 @@
 <translation id="5389224261615877010">ຮຸ້ງ</translation>
 <translation id="5389626883706033615">ເວັບໄຊຖືກບລັອກບໍ່ໃຫ້ຖາມທ່ານເພື່ອໃຊ້ຂໍ້ມູນທີ່ພວກມັນບັນທຶກໄວ້ກ່ຽວກັບທ່ານ</translation>
 <translation id="5389794555912875905">ເບິ່ງຄຳເຕືອນກ່ອນການເຂົ້າໄປຫາເວັບໄຊທີ່ບໍ່ປອດໄພ (ແນະນຳ)</translation>
+<translation id="5389943529251318913">ຫຼຸດຄວາມໄວເມົ້າລົງເຫຼືອ</translation>
 <translation id="5390112241331447203">ຮວມເອົາໄຟລ໌ system_logs.txt ທີ່ສົ່ງຢູ່ໃນລາຍງານຄຳຕິຊົມ.</translation>
 <translation id="5390677308841849479">ສີແດງເຂັ້ມ ແລະ ສີສົ້ມ</translation>
 <translation id="5392192690789334093">ໄດ້ຮັບອະນຸຍາດໃຫ້ສົ່ງການແຈ້ງເຕືອນ</translation>
@@ -7419,6 +7426,7 @@
 <translation id="6266984048393265562">ປັບແຕ່ງໂປຣໄຟລ໌</translation>
 <translation id="6267166720438879315">ເລືອກໃບຢັ້ງຢືນເພື່ອຮັບຮອງຕົວທ່ານເອງໃຫ້ <ph name="HOST_NAME" /></translation>
 <translation id="6268252012308737255">ເປີດດ້ວຍ <ph name="APP" /></translation>
+<translation id="6269050081341530851">ຈະເກັບສຳເນົາທີ່ເກົ່າທີ່ສຸດໄວ້ເມື່ອທ່ານປິດແຖບທີ່ຊ້ຳກັນ</translation>
 <translation id="6270309713620950855">ປິດສຽງການສະກິດ</translation>
 <translation id="6270391203985052864">ເວັບໄຊສາມາດຂໍໃຫ້ສົ່ງການແຈ້ງເຕືອນໄດ້</translation>
 <translation id="6270486800167535228">ປັກໝຸດສ່ວນຂະຫຍາຍແລ້ວ. ເລືອກເພື່ອເບິ່ງຕົວເລືອກເພີ່ມເຕີມ</translation>
@@ -7960,6 +7968,7 @@
 <translation id="6679947539429331601">ເຊື່ອງເປັນເວລາ 12 ຊົ່ວໂມງ</translation>
 <translation id="6680442031740878064">ມີໃຫ້: <ph name="AVAILABLE_SPACE" /></translation>
 <translation id="6680650203439190394">ໃຫ້ຄະແນນ</translation>
+<translation id="6682261381769522894"><ph name="WINDOW_TITLE" /> - [ສະຕຣິງຕົວຍຶດບ່ອນ]</translation>
 <translation id="6683022854667115063">ຫູຟັງ</translation>
 <translation id="6683087162435654533">ກູ້&amp;ທຸກແຖບຄືນມາ</translation>
 <translation id="6683433919380522900">ການອະນຸຍາດແມ່ນ <ph name="PERMISSION_STATE" /></translation>
@@ -8853,6 +8862,7 @@
 <translation id="7330533963640151632">ການຕັ້ງຄ່າ <ph name="FEATURE_NAME" /> ສຳລັບອຸປະກອນຂອງ <ph name="USER_NAME" /> ທີ່ແບ່ງປັນໂດຍໃຊ້ບັນຊີ <ph name="USER_EMAIL" />.</translation>
 <translation id="7331646370422660166">Alt + ລູກສອນລົງ</translation>
 <translation id="7332053360324989309">ຜູ້ເຮັດວຽກສະເພາະຢ່າງ: <ph name="SCRIPT_URL" /></translation>
+<translation id="7332138995369063163">ແຖບທີ່ຊ້ຳກັນ</translation>
 <translation id="7333388112938984914">ບໍ່ສາມາດອັບໂຫຼດໄຟລ໌ໄດ້ໃນລະຫວ່າງທີ່ໃຊ້ການເຊື່ອມຕໍ່ທີ່ມີການວັດແທກ.</translation>
 <translation id="7333669215417470379">ສຳຮອງຂໍ້ມູນ ແລະ ກູ້ຄືນແອັບ ແລະ ການຕັ້ງຄ່າຂອງທ່ານ</translation>
 <translation id="7335974957018254119">ໃຊ້ການກວດການສະກົດຄໍາສຳລັບ</translation>
diff --git a/chrome/app/resources/generated_resources_mr.xtb b/chrome/app/resources/generated_resources_mr.xtb
index 4ba2992..0406c89e0 100644
--- a/chrome/app/resources/generated_resources_mr.xtb
+++ b/chrome/app/resources/generated_resources_mr.xtb
@@ -1503,6 +1503,7 @@
 <translation id="202352106777823113">डाउनलोडला खूप वेळ लागत होता आणि नेटवर्कद्वारे थांबविले.</translation>
 <translation id="2024195579772565064">शोध इंजीन हटवा</translation>
 <translation id="202500043506723828">EID</translation>
+<translation id="2025123106058020990">अचूक क्लिक</translation>
 <translation id="2025632980034333559"><ph name="APP_NAME" /> क्रॅश झाला. एक्स्टेंशन रीलोड करण्यासाठी या फुग्यावर क्लिक करा.</translation>
 <translation id="2026377162111110983">भागातील आवाज</translation>
 <translation id="2028449514182362831">मोशन सेन्सरची आवश्यकता असलेली वैशिष्ट्ये काम करणार नाहीत</translation>
@@ -4760,6 +4761,7 @@
 <translation id="4324577459193912240">फाइल अपूर्ण आहे</translation>
 <translation id="4325237902968425115"><ph name="LINUX_APP_NAME" /> अनइंस्टॉल करत आहे...</translation>
 <translation id="4325433082696797523">स्टोरेज आणि पॉवर</translation>
+<translation id="4325515113816851466">तुम्ही साइन आउट केल्यानंतर तुमच्या पालकांच्या निवडी लागू होणार नाहीत</translation>
 <translation id="4326146840124313313">Chrome ची सर्वात मजबूत सुरक्षा धोकादायक वेबसाइट, डाउनलोड आणि एक्स्टेंशनपासून तुमचे संरक्षण करण्यासाठी बरेच काही करते</translation>
 <translation id="4327380114687339519">एक्स्टेंशन मेनू</translation>
 <translation id="4330191372652740264">बर्फाचे पाणी</translation>
@@ -4882,6 +4884,7 @@
 <translation id="4412992751769744546">तृतीय-पक्ष कुकीजना अनुमती द्या</translation>
 <translation id="4413087696295876280">ChromeOS Flex डिव्हाइसची माहिती आणि डेटा रीड करा</translation>
 <translation id="44137799675104237">नैसर्गिक आवाजामध्ये मजकूर ऐका</translation>
+<translation id="4414051792721275732">तुम्ही क्लिक करण्यासाठी जेश्चर करता, तेव्हा अधिक नियंत्रण पुरवण्यासाठी माउसचा वेग कमी होईल. क्लिक पूर्ण करण्यासाठी जेश्चर पुन्हा करा.</translation>
 <translation id="441418754432585599"><ph name="MODIFIER_ONE" /> + <ph name="MODIFIER_TWO" /> + <ph name="KEY" /></translation>
 <translation id="44141919652824029">"<ph name="APP_NAME" />" ला संलग्न केलेल्या USB डिव्हाइसची सूची मिळवण्याची अनुमती द्यायची?</translation>
 <translation id="4414232939543644979">नवीन &amp;गुप्त विंडो</translation>
@@ -6210,6 +6213,7 @@
 <translation id="5389224261615877010">इंद्रधनुष्य</translation>
 <translation id="5389626883706033615">तुमच्याविषयी सेव्ह केलेली माहिती वापरण्याची परवानगी मागण्यापासून साइटना ब्लॉक केले आहे</translation>
 <translation id="5389794555912875905">असुरक्षित साइटवर जाण्यापूर्वी चेतावणी पहा (शिफारस केलेले)</translation>
+<translation id="5389943529251318913">इतका माउसचा वेग कमी करा</translation>
 <translation id="5390112241331447203">फीडबॅक अहवालामध्ये पाठवलेल्या system_logs.txt फाइलचा समावेश करा.</translation>
 <translation id="5390677308841849479">गडद लाल आणि नारिंगी</translation>
 <translation id="5392192690789334093">सूचना पाठवण्याची अनुमती आहे</translation>
diff --git a/chrome/app/resources/generated_resources_ms.xtb b/chrome/app/resources/generated_resources_ms.xtb
index f3c652f..38b8ccc7 100644
--- a/chrome/app/resources/generated_resources_ms.xtb
+++ b/chrome/app/resources/generated_resources_ms.xtb
@@ -1504,6 +1504,7 @@
 <translation id="202352106777823113">Muat turun mengambil masa terlalu lama dan telah diberhentikan oleh rangkaian.</translation>
 <translation id="2024195579772565064">Padamkan enjin carian</translation>
 <translation id="202500043506723828">EID</translation>
+<translation id="2025123106058020990">Klik tepat</translation>
 <translation id="2025632980034333559"><ph name="APP_NAME" /> telah mengalami nahas. Klik belon ini untuk memuatkan semula sambungan.</translation>
 <translation id="2026377162111110983">Suara kawasan</translation>
 <translation id="2028449514182362831">Ciri yang memerlukan penderia gerakan tidak akan berfungsi</translation>
@@ -4763,6 +4764,7 @@
 <translation id="4324577459193912240">Fail tidak lengkap</translation>
 <translation id="4325237902968425115">Menyahpasang <ph name="LINUX_APP_NAME" />...</translation>
 <translation id="4325433082696797523">Storan dan kuasa</translation>
+<translation id="4325515113816851466">Pilihan ibu/bapa anda tidak akan digunakan selepas anda log keluar</translation>
 <translation id="4326146840124313313">Ciri keselamatan Chrome yang paling kukuh melakukan lebih banyak lagi untuk melindungi anda daripada laman web, muat turun dan sambungan yang berbahaya</translation>
 <translation id="4327380114687339519">Menu sambungan</translation>
 <translation id="4330191372652740264">Air ais</translation>
@@ -4885,6 +4887,7 @@
 <translation id="4412992751769744546">Benarkan kuki pihak ketiga</translation>
 <translation id="4413087696295876280">Baca maklumat dan data peranti ChromeOS Flex</translation>
 <translation id="44137799675104237">Dengar teks dengan suara semula jadi</translation>
+<translation id="4414051792721275732">Apabila anda melakukan gerak isyarat untuk mengklik, kelajuan tetikus akan berkurangan untuk memberikan lebih kawalan. Lakukan gerak isyarat sekali lagi untuk melengkapkan klik.</translation>
 <translation id="441418754432585599"><ph name="MODIFIER_ONE" /> + <ph name="MODIFIER_TWO" /> + <ph name="KEY" /></translation>
 <translation id="44141919652824029">Benarkan "<ph name="APP_NAME" />" mendapatkan senarai peranti anda yang ada USB?</translation>
 <translation id="4414232939543644979">Tetingkap &amp;Inkognito Baharu</translation>
@@ -6213,6 +6216,7 @@
 <translation id="5389224261615877010">Pelangi</translation>
 <translation id="5389626883706033615">Laman disekat daripada meminta anda menggunakan maklumat yang disimpan tentang anda</translation>
 <translation id="5389794555912875905">Berikan amaran sebelum mengakses laman yang tidak selamat (disyorkan)</translation>
+<translation id="5389943529251318913">Kurangkan kelajuan tetikus sebanyak</translation>
 <translation id="5390112241331447203">Sertakan fail system_logs.txt yang dihantar dalam laporan maklum balas.</translation>
 <translation id="5390677308841849479">Merah gelap dan jingga</translation>
 <translation id="5392192690789334093">Dibenarkan untuk menghantar pemberitahuan</translation>
diff --git a/chrome/app/resources/generated_resources_my.xtb b/chrome/app/resources/generated_resources_my.xtb
index 75ecd3f..678dbfb 100644
--- a/chrome/app/resources/generated_resources_my.xtb
+++ b/chrome/app/resources/generated_resources_my.xtb
@@ -1502,6 +1502,7 @@
 <translation id="202352106777823113">ဒေါင်းလုဒ်မှာ သိပ်ကြာနေခဲ့၍ ကွန်ရက်မှ ရပ်ပစ်ခဲ့သည်။</translation>
 <translation id="2024195579772565064">ရှာဖွေရေးအင်ဂျင် ဖျက်ခြင်း</translation>
 <translation id="202500043506723828">EID</translation>
+<translation id="2025123106058020990">အတိအကျနှိပ်ခြင်း</translation>
 <translation id="2025632980034333559"><ph name="APP_NAME" /> မှာ ပျက်စီးသွားပြီ။ တိုးချဲ့မှုကို ပြန်တင်ရန် ဒီပူဖောင်းကို န။</translation>
 <translation id="2026377162111110983">နေရာ၏ အသံ</translation>
 <translation id="2028449514182362831">လှုပ်ရှားမှုအာရုံခံစနစ် လိုအပ်သည့် ဝန်ဆောင်မှုများ အလုပ်လုပ်မည်မဟုတ်ပါ</translation>
@@ -4761,6 +4762,7 @@
 <translation id="4324577459193912240">ဖိုင်မပြည့်စုံပါ</translation>
 <translation id="4325237902968425115"><ph name="LINUX_APP_NAME" /> ကို ဖယ်ရှားနေသည်...</translation>
 <translation id="4325433082696797523">သိုလှောင်ခန်းနှင့် ပါဝါ</translation>
+<translation id="4325515113816851466">ထွက်ပြီးပါက သင့်မိဘ၏ ရွေးချယ်မှုများက သက်ရောက်မည်မဟုတ်ပါ</translation>
 <translation id="4326146840124313313">Chrome ၏ အတောင့်တင်းဆုံး လုံခြုံရေးသည် အန္တရာယ်ဝဘ်ဆိုက်၊ ဒေါင်းလုဒ်နှင့် နောက်ဆက်တွဲများရန်မှ ကာကွယ်ရန် ပိုမိုလုပ်ဆောင်ပေးသည်</translation>
 <translation id="4327380114687339519">နောက်ဆက်တွဲများ မီနူး</translation>
 <translation id="4330191372652740264">ရေခဲရေ</translation>
@@ -4883,6 +4885,7 @@
 <translation id="4412992751769744546">တတိယပါတီ ကွတ်ကီးများ ခွင့်ပြု</translation>
 <translation id="4413087696295876280">ChromeOS Flex စက်၏ အချက်အလက်နှင့် ဒေတာကို ဖတ်နိုင်သည်</translation>
 <translation id="44137799675104237">စာသားကို သဘာဝအသံဖြင့် နားထောင်ရန်</translation>
+<translation id="4414051792721275732">နှိပ်ရန် လက်ဟန်လုပ်သည့်အခါ ထိန်းချုပ်မှု ပိုပေးနိုင်ရန် မောက်စ်မြန်နှုန်း လျှော့ချမည်။ ကလစ်ကို အပြီးသတ်ရန် လက်ဟန် ထပ်မံပြုလုပ်ပါ။</translation>
 <translation id="441418754432585599"><ph name="MODIFIER_ONE" /> + <ph name="MODIFIER_TWO" /> + <ph name="KEY" /></translation>
 <translation id="44141919652824029">သင်ချိတ်ဆက်ထားသည့် USB စက်ပစ္စည်းစာရင်းကို "<ph name="APP_NAME" />" အား ရယူခွင့်ပြုလိုသလား။</translation>
 <translation id="4414232939543644979">ရုပ်ဖျက် &amp;ဝင်ဒိုး အသစ်</translation>
@@ -6211,6 +6214,7 @@
 <translation id="5389224261615877010">သက်သန့်</translation>
 <translation id="5389626883706033615">ဝဘ်ဆိုက်များကို ၎င်းတို့တွင် သိမ်းထားသော သင့်အချက်အလက်များ သုံးခွင့်တောင်းဆိုခြင်းမှ ပိတ်ထားသည်</translation>
 <translation id="5389794555912875905">လုံခြုံမှုမရှိသော ဝဘ်ဆိုက်များသို့မသွားမီ သတိပေးချက်များ မြင်ရရန် (အကြံပြုထားသည်)</translation>
+<translation id="5389943529251318913">လျှော့ချရန် မောက်စ်မြန်နှုန်း</translation>
 <translation id="5390112241331447203">ပေးပို့သော တုံ့ပြန်ချက်အစီရင်ခံစာများတွင် system_logs.txt ဖိုင် ထည့်သွင်းနိုင်သည်။</translation>
 <translation id="5390677308841849479">အနီရင့်နှင့် လိမ္မော်</translation>
 <translation id="5392192690789334093">အကြောင်းကြားချက်များ ပို့ရန် ခွင့်ပြုထားသည်</translation>
diff --git a/chrome/app/resources/generated_resources_nl.xtb b/chrome/app/resources/generated_resources_nl.xtb
index b9750c6f..3f241f4 100644
--- a/chrome/app/resources/generated_resources_nl.xtb
+++ b/chrome/app/resources/generated_resources_nl.xtb
@@ -2596,7 +2596,7 @@
 <translation id="2782104745158847185">Fout bij het installeren van de Linux-app</translation>
 <translation id="2783952358106015700">Je beveiligingssleutel gebruiken met <ph name="APP_NAME" /></translation>
 <translation id="2785267875302712148">Wachtwoordcheck</translation>
-<translation id="2785279781154577715">Weergave van voorbeelden voor pop-upkaarten voor tabbladen</translation>
+<translation id="2785279781154577715">Weergave van pop-upkaarten voor tabbladen</translation>
 <translation id="2785873697295365461">Bestandsdescriptors</translation>
 <translation id="2785975315093449168">GTK</translation>
 <translation id="2787354132612937472">—</translation>
@@ -2694,7 +2694,7 @@
 <translation id="2850672011315104382">Stijl van interpunctie</translation>
 <translation id="285237063405807022">(laden)</translation>
 <translation id="2853121255651601031">Wachtwoord opgeslagen</translation>
-<translation id="2855243985454069333">Hiermee wordt de geschiedenis van al je gesynchroniseerde apparaten verwijderd</translation>
+<translation id="2855243985454069333">Hiermee wordt de geschiedenis van al je gesynchroniseerde apparaten verwijderd.</translation>
 <translation id="2855812646048059450">Inloggen met <ph name="CREDENTIAL_PROVIDER" /></translation>
 <translation id="2856776373509145513">Een nieuwe container maken</translation>
 <translation id="2856907950922663165">URL-versleuteling uitzetten?</translation>
@@ -4137,10 +4137,10 @@
 <translation id="3875815154304214043">Er is ingesteld dat <ph name="APP_NAME" /> wordt geopend in een nieuw browsertabblad. Ondersteunde links worden ook geopend in de browser. <ph name="BEGIN_LINK_LEARN_MORE" />Meer informatie<ph name="END_LINK_LEARN_MORE" /></translation>
 <translation id="3876219572815410515">Vensters met gewijzigd formaat naar boven verplaatsen</translation>
 <translation id="3877075909000773256">Instellingen voor Dichtbij delen voor het apparaat van <ph name="USER_NAME" />, delen via het account <ph name="USER_EMAIL" />.</translation>
-<translation id="3877209288227498506">Kies of je geheugengebruik en afbeeldingen wilt tonen op voorbeelden voor pop-upkaarten voor tabbladen</translation>
+<translation id="3877209288227498506">Kies of je geheugengebruik en afbeeldingen wilt tonen op pop-upkaarten voor tabbladen</translation>
 <translation id="3878445208930547646">Kopiëren vanaf deze site is niet toegestaan</translation>
 <translation id="3879748587602334249">Downloadbeheer</translation>
-<translation id="3880513902716032002">Sommige pagina's die je bezoekt, zijn vooraf geladen</translation>
+<translation id="3880513902716032002">Sommige pagina's die je bezoekt, worden vooraf geladen</translation>
 <translation id="3884152383786131369">Voor webcontent die in meerdere talen beschikbaar is, wordt de eerste ondersteunde taal in deze lijst gebruikt. Deze voorkeuren worden gesynchroniseerd met je browserinstellingen. <ph name="BEGIN_LINK_LEARN_MORE" />Meer informatie<ph name="END_LINK_LEARN_MORE" /></translation>
 <translation id="3885112598747515383">Updates worden beheerd door je beheerder</translation>
 <translation id="3887022758415973389">Apparaatlijst bekijken</translation>
@@ -4648,7 +4648,7 @@
 <translation id="4254813446494774748">Doeltaal:</translation>
 <translation id="4255016471934258618">Je mond wijd opendoen</translation>
 <translation id="425573743389990240">Batterij-ontlading in Watt (een negatieve waarde betekent dat de batterij wordt opgeladen)</translation>
-<translation id="4255841059940367080">Realtime, AI-gestuurde bescherming tegen gevaarlijke sites, downloads en extensies op basis van je browsegegevens die naar Google worden gestuurd</translation>
+<translation id="4255841059940367080">Realtime, AI-gestuurde bescherming tegen gevaarlijke sites, downloads en extensies op basis van je browsegegevens die naar Google worden gestuurd.</translation>
 <translation id="4256316378292851214">&amp;Video opslaan als...</translation>
 <translation id="4258348331913189841">Bestandssystemen</translation>
 <translation id="4259388776256904261">Dit kan even duren</translation>
@@ -6394,7 +6394,7 @@
 <translation id="5521078259930077036">Is dit de homepage die je had verwacht?</translation>
 <translation id="5522156646677899028">Deze extensie bevat een groot beveiligingsprobleem.</translation>
 <translation id="5523149538118225875">{NUM_EXTENSIONS,plural, =1{Je beheerder heeft een extensie geïnstalleerd}other{Je beheerder heeft # extensies geïnstalleerd}}</translation>
-<translation id="5523532775593636291">Sites die je toevoegt, blijven altijd actief en er wordt geen geheugen vrijgemaakt op basis van deze sites</translation>
+<translation id="5523532775593636291">Sites die je toevoegt, blijven altijd actief en er wordt geen geheugen van vrijgemaakt.</translation>
 <translation id="5523558474028191231">De naam mag letters, cijfers en speciale tekens bevatten en mag maximaal <ph name="MAX_CHARACTER_COUNT" /> tekens lang zijn</translation>
 <translation id="5526745900034778153">Log opnieuw in om door te gaan met synchroniseren</translation>
 <translation id="5527463195266282916">Je probeert een oudere versie van de extensie te installeren.</translation>
diff --git a/chrome/app/resources/generated_resources_pa.xtb b/chrome/app/resources/generated_resources_pa.xtb
index 17b9aaf..ebc6d9a 100644
--- a/chrome/app/resources/generated_resources_pa.xtb
+++ b/chrome/app/resources/generated_resources_pa.xtb
@@ -1505,6 +1505,7 @@
 <translation id="202352106777823113">ਡਾਊਨਲੋਡ ਵਿੱਚ ਬਹੁਤ ਜ਼ਿਆਦਾ ਸਮਾਂ ਲੱਗ ਰਿਹਾ ਸੀ ਅਤੇ ਇਹ ਨੈੱਟਵਰਕ ਵੱਲੋਂ ਰੋਕ ਦਿੱਤੀ ਗਈ ਸੀ।</translation>
 <translation id="2024195579772565064">ਖੋਜ ਇੰਜਣ ਮਿਟਾਓ</translation>
 <translation id="202500043506723828">EID</translation>
+<translation id="2025123106058020990">ਸਟੀਕ ਕਲਿੱਕ</translation>
 <translation id="2025632980034333559"><ph name="APP_NAME" /> ਕ੍ਰੈਸ਼ ਹੋ ਗਈ ਹੈ। ਐਕਸਟੈਂਸ਼ਨ ਨੂੰ ਰੀਲੋਡ ਕਰਨ ਲਈ ਇਸ ਬਲੂਨ 'ਤੇ ਕਲਿੱਕ ਕਰੋ।</translation>
 <translation id="2026377162111110983">ਖੇਤਰ ਦੀ ਅਵਾਜ਼</translation>
 <translation id="2028449514182362831">ਜਿਹੜੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਲਈ ਮੋਸ਼ਨ ਸੈਂਸਰਾਂ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ ਉਹ ਕੰਮ ਨਹੀਂ ਕਰਨਗੀਆਂ</translation>
@@ -4765,6 +4766,7 @@
 <translation id="4324577459193912240">ਅਧੂਰੀ ਫ਼ਾਈਲ</translation>
 <translation id="4325237902968425115"><ph name="LINUX_APP_NAME" /> ਨੂੰ ਅਣਸਥਾਪਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ...</translation>
 <translation id="4325433082696797523">ਸਟੋਰੇਜ ਅਤੇ ਪਾਵਰ</translation>
+<translation id="4325515113816851466">ਤੁਹਾਡੇ ਸਾਈਨ-ਆਊਟ ਹੋਣ ਤੋਂ ਬਾਅਦ ਤੁਹਾਡੇ ਮਾਂ-ਪਿਓ ਦੀਆਂ ਚੋਣਾਂ ਲਾਗੂ ਨਹੀਂ ਹੋਣਗੀਆਂ</translation>
 <translation id="4326146840124313313">Chrome ਦੀ ਸਭ ਤੋਂ ਮਜ਼ਬੂਤ ਸੁਰੱਖਿਆ ਖਤਰਨਾਕ ਵੈੱਬਸਾਈਟਾਂ ਅਤੇ ਡਾਊਨਲੋਡਾਂ ਅਤੇ ਐਕਸਟੈਂਸ਼ਨਾਂ ਤੋਂ ਤੁਹਾਡੀ ਰੱਖਿਆ ਕਰਨ ਲਈ ਬਹੁਤ ਕੁਝ ਕਰਦੀ ਹੈ</translation>
 <translation id="4327380114687339519">ਐਕਸਟੈਂਸ਼ਨ ਮੀਨੂ</translation>
 <translation id="4330191372652740264">ਠੰਡਾ ਪਾਣੀ</translation>
@@ -4887,6 +4889,7 @@
 <translation id="4412992751769744546">ਤੀਜੀ-ਪਾਰਟੀ ਕੁਕੀਜ਼ ਦੀ ਆਗਿਆ ਦਿਓ</translation>
 <translation id="4413087696295876280">ChromeOS Flex ਦੀ ਡੀਵਾਈਸ ਜਾਣਕਾਰੀ ਅਤੇ ਡਾਟੇ ਨੂੰ ਪੜ੍ਹੋ</translation>
 <translation id="44137799675104237">ਲਿਖਤ ਨੂੰ ਕੁਦਰਤੀ ਅਵਾਜ਼ ਵਿੱਚ ਸੁਣੋ</translation>
+<translation id="4414051792721275732">ਜਦੋਂ ਤੁਸੀਂ ਕਲਿੱਕ ਕਰਨ ਲਈ ਕੋਈ ਇਸ਼ਾਰਾ ਕਰਦੇ ਹੋ, ਤਾਂ ਹੋਰ ਕੰਟਰੋਲ ਮੁਹੱਈਆ ਕਰਵਾਉਣ ਲਈ ਮਾਊਸ ਸਪੀਡ ਘੱਟ ਜਾਵੇਗੀ। ਕਲਿੱਕ ਨੂੰ ਪੂਰਾ ਕਰਨ ਲਈ ਦੁਬਾਰਾ ਇਸ਼ਾਰਾ ਕਰੋ।</translation>
 <translation id="441418754432585599"><ph name="MODIFIER_ONE" /> + <ph name="MODIFIER_TWO" /> + <ph name="KEY" /></translation>
 <translation id="44141919652824029">ਕੀ "<ph name="APP_NAME" />" ਨੂੰ ਅਟੈਚ ਕੀਤੇ ਆਪਣੇ USB ਡੀਵਾਈਸਾਂ ਦੀ ਸੂਚੀ ਪ੍ਰਾਪਤ ਕਰਨ ਦੇਣੀ ਹੈ?</translation>
 <translation id="4414232939543644979">ਨਵੀਂ &amp;ਗੁਮਨਾਮ Window</translation>
@@ -6214,6 +6217,7 @@
 <translation id="5389224261615877010">ਸਤਰੰਗ</translation>
 <translation id="5389626883706033615">ਸਾਈਟਾਂ ਨੂੰ ਤੁਹਾਨੂੰ ਉਨ੍ਹਾਂ ਵੱਲੋਂ ਤੁਹਾਡੇ ਬਾਰੇ ਜਾਣਕਾਰੀ ਦੀ ਵਰਤੋਂ ਕਰਨ ਵਾਸਤੇ ਕਹਿਣ ਤੋਂ ਬਲਾਕ ਕੀਤਾ ਗਿਆ ਹੈ</translation>
 <translation id="5389794555912875905">ਅਸੁਰੱਖਿਅਤ ਸਾਈਟਾਂ 'ਤੇ ਜਾਣ ਤੋਂ ਪਹਿਲਾਂ ਚਿਤਾਵਨੀਆਂ ਦੇਖੋ (ਸਿਫ਼ਾਰਸ਼ੀ)</translation>
+<translation id="5389943529251318913">ਮਾਊਸ ਸਪੀਡ ਨੂੰ ਇੰਨਾ ਘਟਾਓ</translation>
 <translation id="5390112241331447203">ਵਿਚਾਰ ਰਿਪੋਰਟਾਂ ਵਿੱਚ ਭੇਜੀ system_logs.txt ਫ਼ਾਈਲ ਨੂੰ ਸ਼ਾਮਲ ਕਰੋ।</translation>
 <translation id="5390677308841849479">ਗੂੜ੍ਹਾ ਲਾਲ ਅਤੇ ਸੰਤਰੀ</translation>
 <translation id="5392192690789334093">ਸੂਚਨਾਵਾਂ ਭੇਜਣ ਦੀ ਇਜਾਜ਼ਤ ਹੈ</translation>
diff --git a/chrome/app/resources/generated_resources_sl.xtb b/chrome/app/resources/generated_resources_sl.xtb
index ce401c2a..1c03db51 100644
--- a/chrome/app/resources/generated_resources_sl.xtb
+++ b/chrome/app/resources/generated_resources_sl.xtb
@@ -790,7 +790,7 @@
 <translation id="1546031833947068368">{COUNT,plural, =1{Anonimno okno se ne bo znova odprlo.}one{# anonimno okno se ne bo znova odprlo.}two{# anonimni okni se ne bosta znova odprli.}few{# anonimna okna se ne bodo znova odprla.}other{# anonimnih oken se ne bo znova odprlo.}}</translation>
 <translation id="1546280085599573572">Zaradi te razširitve se je spremenila stran, ki je prikazana, ko kliknete gumb za začetno stran.</translation>
 <translation id="1546452108651444655"><ph name="CHILD_NAME" /> želi namestiti <ph name="EXTENSION_TYPE" />, ki zahteva ta dovoljenja:</translation>
-<translation id="1547123415014299762">Piškotki drugih spletnih mest so dovoljeni.</translation>
+<translation id="1547123415014299762">Piškotki tretjih oseb so dovoljeni.</translation>
 <translation id="1547808936554660006">Razumem, da s postopkom Powerwash nameščeni profili za eSIM ne bodo odstranjeni.</translation>
 <translation id="1547936895218027488">Kliknite ikono stranskega podokna, če ga želite odpreti.</translation>
 <translation id="1549275686094429035">ARC je omogočen</translation>
@@ -1801,7 +1801,7 @@
 <translation id="2234065144797002621">Potok</translation>
 <translation id="2234827758954819389">Vodnik po zasebnosti</translation>
 <translation id="2234876718134438132">Sinhronizacija in Googlove storitve</translation>
-<translation id="2235344399760031203">Piškotki drugih spletnih mest so blokirani</translation>
+<translation id="2235344399760031203">Piškotki tretjih oseb so blokirani</translation>
 <translation id="2238379619048995541">Podatki o stanju frekvence</translation>
 <translation id="2241053333139545397">Branje in spreminjanje vaših podatkov na več spletnih mestih</translation>
 <translation id="2241634353105152135">Samo enkrat</translation>
@@ -3504,7 +3504,7 @@
 <translation id="3445925074670675829">Naprava USB-C</translation>
 <translation id="3446274660183028131">Zaženite program Parallels Desktop, če želite namestiti sistem Windows.</translation>
 <translation id="344630545793878684">Branje vaših podatkov na več spletnih mestih</translation>
-<translation id="3447644283769633681">Blokiraj vse piškotke drugih spletnih mest</translation>
+<translation id="3447644283769633681">Blokiraj vse piškotke tretjih oseb</translation>
 <translation id="3447644827015694497">Želite pregledati neaktivne zavihke?</translation>
 <translation id="3447797901512053632">Predvajanje zavihka <ph name="TAB_NAME" /> v napravi <ph name="DEVICE_NAME" />.</translation>
 <translation id="3448492834076427715">Posodobi račun</translation>
@@ -3706,7 +3706,7 @@
 <translation id="3593152357631900254">Omogoči način enakozvočnega pinjina</translation>
 <translation id="3593965109698325041">Omejitve imena potrdila</translation>
 <translation id="3596012367874587041">Nastavitve aplikacije</translation>
-<translation id="3596414637720633074">Blokiranje piškotkov drugih mest v anonimnem načinu</translation>
+<translation id="3596414637720633074">Blokiranje piškotkov tretjih oseb v anonimnem načinu</translation>
 <translation id="3599221874935822507">Dvignjeno</translation>
 <translation id="3600051066689725006">Podatki o spletni zahtevi</translation>
 <translation id="3600956933576601730">Če želite uporabljati te funkcije, morate prebrati in sprejeti pogoje</translation>
@@ -4885,7 +4885,7 @@
 <translation id="4412547955014928315">Želite izbrisati podatke spletnega mesta in dovoljenja za <ph name="SITE_NAME" /> in vsa njegova podrejena spletna mesta?</translation>
 <translation id="4412632005703201014">Aplikacije za Chrome se selijo v moderne spletne aplikacije. To aplikacijo za Chrome je v brskalnik namestila organizacija. Če želite odpreti moderno spletno aplikacijo na seznamu aplikacij, se najprej obrnite na skrbnika in ga prosite, naj odstrani aplikacijo za Chrome. V tem času lahko obiščete spletno mesto <ph name="EXTENSION_LAUNCH_URL" /> in odprete razširitev <ph name="EXTENSION_NAME" /> v spletu.</translation>
 <translation id="4412698727486357573">Center za pomoč</translation>
-<translation id="4412992751769744546">Omogočanje piškotkov drugih spletnih mest</translation>
+<translation id="4412992751769744546">Omogočanje piškotkov tretjih oseb</translation>
 <translation id="4413087696295876280">Branje podatkov o napravi ChromeOS Flex in podatkov</translation>
 <translation id="44137799675104237">Poslušajte besedilo z naravnim glasom</translation>
 <translation id="441418754432585599"><ph name="MODIFIER_ONE" /> + <ph name="MODIFIER_TWO" /> + <ph name="KEY" /></translation>
@@ -6156,7 +6156,7 @@
 <translation id="5338338064218053691">Z anonimnim oknom lahko zasebno brskate.</translation>
 <translation id="5338503421962489998">Lokalna shramba</translation>
 <translation id="5340787663756381836">&amp;Iskanje in urejanje</translation>
-<translation id="5341793073192892252">Ti piškotki so bili blokirani (piškotki drugih mest se blokirajo brez izjeme)</translation>
+<translation id="5341793073192892252">Ti piškotki so bili blokirani (piškotki tretjih oseb se blokirajo brez izjeme)</translation>
 <translation id="5342091991439452114">Koda PIN mora imeti vsaj toliko števk: <ph name="MINIMUM" /></translation>
 <translation id="5344036115151554031">Obnavljanje Linuxa</translation>
 <translation id="5344128444027639014"><ph name="BATTERY_PERCENTAGE" /> % (desna)</translation>
@@ -6674,7 +6674,7 @@
 <translation id="5722086096420375088">Zelena in bela</translation>
 <translation id="572328651809341494">Nedavni zavihki</translation>
 <translation id="5723508132121499792">Noben program se ne izvaja v ozadju</translation>
-<translation id="5723967018671998714">Piškotki drugih spletnih mest so blokirani v anonimnem načinu</translation>
+<translation id="5723967018671998714">Piškotki tretjih oseb so blokirani v anonimnem načinu</translation>
 <translation id="5725112283692663422">Pošljite povratne informacije o ustvarjanju teme z umetno inteligenco</translation>
 <translation id="5727728807527375859">Razširitve, aplikacije in teme lahko škodujejo računalniku. Ali ste prepričani, da želite nadaljevati?</translation>
 <translation id="5728072125198221967">Povezane Googlove storitve</translation>
@@ -7315,7 +7315,7 @@
 <translation id="6195155925303302899">Poravnaj na sredino</translation>
 <translation id="6195163219142236913">Piškotki tretjih oseb so omejeni</translation>
 <translation id="6195693561221576702">Te naprave ni mogoče nastaviti v predstavitvenem načinu brez povezave.</translation>
-<translation id="6196640612572343990">Blokiraj piškotke drugih spletnih mest</translation>
+<translation id="6196640612572343990">Blokiraj piškotke tretjih oseb</translation>
 <translation id="6196854373336333322">Razširitev »<ph name="EXTENSION_NAME" />« je prevzela nadzor nad nastavitvami strežnika proxy, kar pomeni, da lahko spremeni, prekine ali nadzoruje vse, kar počnete v spletu. Če ne veste, zakaj je prišlo do te spremembe, je verjetno nezaželena.</translation>
 <translation id="6197128521826316819">Ustvari kodo QR za to stran</translation>
 <translation id="6198223452299275399">Pomikanje med stranmi z vlečenjem</translation>
diff --git a/chrome/app/resources/generated_resources_uk.xtb b/chrome/app/resources/generated_resources_uk.xtb
index 5ad5d0c6..92c4c43 100644
--- a/chrome/app/resources/generated_resources_uk.xtb
+++ b/chrome/app/resources/generated_resources_uk.xtb
@@ -1507,6 +1507,7 @@
 <translation id="202352106777823113">Завантаження тривало задовго, тому було припинене мережею.</translation>
 <translation id="2024195579772565064">Видалити пошукову систему</translation>
 <translation id="202500043506723828">EID</translation>
+<translation id="2025123106058020990">Точне натискання</translation>
 <translation id="2025632980034333559">Відбулося аварійне завершення роботи розширення <ph name="APP_NAME" />. Натисніть цю спливаючу підказку, щоб перезавантажити розширення.</translation>
 <translation id="2026377162111110983">Чіткіший голос</translation>
 <translation id="2028449514182362831">Функції, яким потрібні датчики руху, не працюватимуть</translation>
@@ -4766,6 +4767,7 @@
 <translation id="4324577459193912240">Файл неповний</translation>
 <translation id="4325237902968425115">Видаляється <ph name="LINUX_APP_NAME" />…</translation>
 <translation id="4325433082696797523">Сховище й живлення</translation>
+<translation id="4325515113816851466">Якщо вийти з профілю, вибрані батьками налаштування більше не застосовуватимуться.</translation>
 <translation id="4326146840124313313">Найнадійніша система безпеки Chrome захищає вас від небезпечних веб-сайтів, завантажень і розширень</translation>
 <translation id="4327380114687339519">Меню розширень</translation>
 <translation id="4330191372652740264">Крижана вода</translation>
@@ -4888,6 +4890,7 @@
 <translation id="4412992751769744546">Дозволити сторонні файли cookie</translation>
 <translation id="4413087696295876280">Переглядати інформацію про пристрій із ChromeOS Flex і дані на ньому</translation>
 <translation id="44137799675104237">Слухати текст природним голосом</translation>
+<translation id="4414051792721275732">Коли ви виконуватимете жест, щоб натиснути кнопкою миші, її швидкість зменшуватиметься для покращення точності. Щоб завершити натискання, повторіть жест.</translation>
 <translation id="441418754432585599"><ph name="MODIFIER_ONE" /> + <ph name="MODIFIER_TWO" /> + <ph name="KEY" /></translation>
 <translation id="44141919652824029">Дозволити додатку <ph name="APP_NAME" /> отримувати список підключених пристроїв USB?</translation>
 <translation id="4414232939543644979">Нове &amp;анонімне вікно</translation>
@@ -6214,6 +6217,7 @@
 <translation id="5389224261615877010">Веселка</translation>
 <translation id="5389626883706033615">Сайтам заборонено запитувати дозвіл на використання збереженої про вас інформації</translation>
 <translation id="5389794555912875905">Показувати попередження, перш ніж переходити на незахищені сайти (рекомендовано)</translation>
+<translation id="5389943529251318913">Зменшити швидкість миші на</translation>
 <translation id="5390112241331447203">Включити файл system_logs.txt, який надіслано у звітах про відгуки.</translation>
 <translation id="5390677308841849479">Темно-червоний і оранжевий</translation>
 <translation id="5392192690789334093">Дозволено надсилати сповіщення</translation>
diff --git a/chrome/app/resources/generated_resources_zh-CN.xtb b/chrome/app/resources/generated_resources_zh-CN.xtb
index b0f33d1..ae78925 100644
--- a/chrome/app/resources/generated_resources_zh-CN.xtb
+++ b/chrome/app/resources/generated_resources_zh-CN.xtb
@@ -889,7 +889,7 @@
 <translation id="1611432201750675208">您的设备已锁定</translation>
 <translation id="1611649489706141841">前进</translation>
 <translation id="1612019740169791082">您的容器配置不支持调整磁盘空间大小。若要调整预留给 Linux 的空间,请先备份旧容器中的内容,然后再将这些内容恢复到新容器中。</translation>
-<translation id="1612179176000108678">仅在电池电量不高于 <ph name="PERCENT" />% 时开启</translation>
+<translation id="1612179176000108678">仅在电池电量为 <ph name="PERCENT" />% 或以下时开启</translation>
 <translation id="1613019471223620622">显示 <ph name="USERNAME" /> 在 <ph name="DOMAIN" /> 上的密码</translation>
 <translation id="1613149688105334014">2022 年 12 月之后,多款旧版 Chrome 应用将无法开启。您可查看是否有可用的新版本。</translation>
 <translation id="1614511179807650956">您的移动数据流量配额可能已经用完。若想购买更多流量,请前往“<ph name="NAME" />”激活门户网站</translation>
@@ -1399,7 +1399,7 @@
     <ph name="BEGIN_PARAGRAPH2" />您随时可在 ChromeOS 设备的设置中开始或停止发送这些报告。如果您是网域管理员,则可在管理控制台中更改这一设置。<ph name="END_PARAGRAPH2" />
     <ph name="BEGIN_PARAGRAPH3" />如果您已为自己的 Google 账号开启“网络与应用活动记录”设置,您的 Android 数据可能会保存到您的 Google 账号中。您可在 account.google.com 上查看和删除您的数据以及更改您的账号设置。<ph name="END_PARAGRAPH3" /></translation>
 <translation id="1971694696800660479">所有数据都将被删除。此操作无法撤消</translation>
-<translation id="1972313920920745320">您添加的网站将始终保持活跃状态,且系统不会从它们中释放内存。<ph name="BEGIN_LINK" />详细了解如何让特定网站保持活跃状态<ph name="END_LINK" /></translation>
+<translation id="1972313920920745320">您添加的网站将始终保持活跃状态,且系统不会释放它们占用的内存。<ph name="BEGIN_LINK" />详细了解如何让特定网站保持活跃状态<ph name="END_LINK" /></translation>
 <translation id="1972325230031091483">您的浏览速度会更快,因为系统会根据您当前访问的网页主动加载内容</translation>
 <translation id="197288927597451399">保留</translation>
 <translation id="1973886230221301399">ChromeVox</translation>
@@ -3302,7 +3302,7 @@
 <translation id="3319306431415395200">使用 <ph name="VISUAL_SEARCH_PROVIDER" /> 翻译图片中的文字</translation>
 <translation id="3319863571062685443">您的地址已保存</translation>
 <translation id="3320271870899888245">无法连接到 OneDrive。请重试。</translation>
-<translation id="3320630259304269485">安全浏览(保护您免受危险网站的侵害)和其他安全设置</translation>
+<translation id="3320630259304269485">安全浏览(防范危险网站)和其他安全设置</translation>
 <translation id="3320957378743864387">不得提供写作帮助</translation>
 <translation id="3321460131042519426">启用自动换行</translation>
 <translation id="3321494112580110651">找不到您的打印机?</translation>
@@ -3414,7 +3414,7 @@
 <translation id="3406290648907941085">允许使用虚拟现实设备和数据</translation>
 <translation id="3406396172897554194">按语言或输入法名称搜索</translation>
 <translation id="3406605057700382950">显示书签栏(&amp;S)</translation>
-<translation id="3407392651057365886">预加载更多网页。被其他网站请求的网页可能会通过 Google 服务器预加载。</translation>
+<translation id="3407392651057365886">预加载更多网页。其他网站请求访问的网页可能会通过 Google 服务器预加载。</translation>
 <translation id="3407967630066378878">若要设置指纹,请让您的孩子轻触此 <ph name="DEVICE_TYPE" /> 左侧的指纹传感器。您孩子的指纹数据会安全地存储在此 <ph name="DEVICE_TYPE" /> 上,绝不会外泄。</translation>
 <translation id="3408555740610481810">正在使用摄像头和麦克风</translation>
 <translation id="3409513286451883969">将所选内容翻译为<ph name="LANGUAGE" />(&amp;T)</translation>
@@ -4132,7 +4132,7 @@
 <translation id="3877209288227498506">选择在标签页悬停预览卡片中显示内存用量和图片</translation>
 <translation id="3878445208930547646">不允许从该网站复制</translation>
 <translation id="3879748587602334249">下载管理器</translation>
-<translation id="3880513902716032002">在您访问的网页中,有一些是预加载的网页</translation>
+<translation id="3880513902716032002">预加载您访问的部分网页</translation>
 <translation id="3884152383786131369">能以多种语言显示的网页内容将会使用此列表中第一项受支持的语言。这些偏好设置会与您的浏览器设置同步。<ph name="BEGIN_LINK_LEARN_MORE" />了解详情<ph name="END_LINK_LEARN_MORE" /></translation>
 <translation id="3885112598747515383">更新是由您的管理员管理</translation>
 <translation id="3887022758415973389">显示设备列表</translation>
@@ -4868,7 +4868,7 @@
 <translation id="4415213869328311284">您现在可以开始使用 <ph name="DEVICE_TYPE" /> 了。</translation>
 <translation id="4415276339145661267">管理您的 Google 账号</translation>
 <translation id="4415748029120993980">SECG 椭圆曲线 secp384r1(又称 NIST P-384)</translation>
-<translation id="4415815425191869676">始终让这些网站保持活动状态</translation>
+<translation id="4415815425191869676">始终让以下网站保持活跃状态</translation>
 <translation id="4416582610654027550">请输入一个有效网址</translation>
 <translation id="4421932782753506458">猫咪</translation>
 <translation id="4423376891418188461">还原设置</translation>
@@ -4893,7 +4893,7 @@
 <translation id="4432621511648257259">密码不正确</translation>
 <translation id="4434611816075088065">目前没有任何其他需要您注意的事项</translation>
 <translation id="443475966875174318">更新或卸载不兼容的应用</translation>
-<translation id="443503224864902151">将您从大多数网站中退出账号。您的 Google 账号仍会保持登录状态,以便删除您的已同步数据。</translation>
+<translation id="443503224864902151">您会从大多数网站中退出账号。您的 Google 账号仍会保持登录状态,以便删除已同步的数据。</translation>
 <translation id="4437879751057074691">提示保存密码和通行密钥</translation>
 <translation id="4437947179446780764">添加自定义 DNS 服务提供商</translation>
 <translation id="4438043733494739848">透明</translation>
@@ -5384,7 +5384,7 @@
 <translation id="4807098396393229769">持卡人姓名</translation>
 <translation id="4807122856660838973">开启安全浏览</translation>
 <translation id="4807514039636325497">DBus 详情</translation>
-<translation id="4808525520374557629">针对检测到的性能问题获取改进建议通知。<ph name="BEGIN_LINK" />详细了解性能问题提醒<ph name="END_LINK" /></translation>
+<translation id="4808525520374557629">系统检测到性能问题时显示改进建议通知。<ph name="BEGIN_LINK" />详细了解性能问题提醒<ph name="END_LINK" /></translation>
 <translation id="4808667324955055115">已拦截弹出式窗口:</translation>
 <translation id="4809079943450490359">您的设备管理员温馨提示:</translation>
 <translation id="4809447465126035330">删除</translation>
@@ -6386,7 +6386,7 @@
 <translation id="5521078259930077036">这是您想要的主页吗?</translation>
 <translation id="5522156646677899028">该扩展程序存在严重的安全漏洞。</translation>
 <translation id="5523149538118225875">{NUM_EXTENSIONS,plural, =1{您的管理员已安装了 1 个扩展程序}other{您的管理员已安装了 # 个扩展程序}}</translation>
-<translation id="5523532775593636291">您添加的网站将始终保持活跃状态,且系统不会从它们中释放内存</translation>
+<translation id="5523532775593636291">您添加的网站将始终保持活跃状态,且系统不会释放它们占用的内存</translation>
 <translation id="5523558474028191231">名称可以使用字母、数字和特殊字符,并且不得超过 <ph name="MAX_CHARACTER_COUNT" /> 个字符</translation>
 <translation id="5526745900034778153">需重新登录才能继续同步</translation>
 <translation id="5527463195266282916">已尝试对扩展程序降级。</translation>
diff --git a/chrome/app/resources/generated_resources_zh-HK.xtb b/chrome/app/resources/generated_resources_zh-HK.xtb
index 1a8a39a..531dd63 100644
--- a/chrome/app/resources/generated_resources_zh-HK.xtb
+++ b/chrome/app/resources/generated_resources_zh-HK.xtb
@@ -1504,6 +1504,7 @@
 <translation id="202352106777823113">下載時間太長,已被網絡停止。</translation>
 <translation id="2024195579772565064">刪除搜尋引擎</translation>
 <translation id="202500043506723828">EID</translation>
+<translation id="2025123106058020990">精確點擊</translation>
 <translation id="2025632980034333559"><ph name="APP_NAME" /> 當機了,請按一下這個提示框來重新載入擴充功能。</translation>
 <translation id="2026377162111110983">區域語音</translation>
 <translation id="2028449514182362831">需要動作感應器的功能將無法運作</translation>
@@ -4753,6 +4754,7 @@
 <translation id="4324577459193912240">檔案未完成下載</translation>
 <translation id="4325237902968425115">正在解除安裝 <ph name="LINUX_APP_NAME" />…</translation>
 <translation id="4325433082696797523">儲存空間和電源</translation>
+<translation id="4325515113816851466">你登出後,系統就不會套用家長的選擇</translation>
 <translation id="4326146840124313313">Chrome 最強大的安全功能可進一步保護您免受危險網站、下載檔案和擴充程式威脅</translation>
 <translation id="4327380114687339519">擴充程式選單</translation>
 <translation id="4330191372652740264">冰水</translation>
@@ -4875,6 +4877,7 @@
 <translation id="4412992751769744546">允許第三方 Cookie</translation>
 <translation id="4413087696295876280">讀取 ChromeOS Flex 裝置資訊和資料</translation>
 <translation id="44137799675104237">聽下用自然語音朗讀嘅文字</translation>
+<translation id="4414051792721275732">使用手勢點選時,滑鼠速度會降低,讓你更容易控制。請再次做出手勢來完成點擊動作。</translation>
 <translation id="441418754432585599"><ph name="MODIFIER_ONE" /> + <ph name="MODIFIER_TWO" /> + <ph name="KEY" /> 鍵</translation>
 <translation id="44141919652824029">允許「<ph name="APP_NAME" />」取得已連結 USB 裝置的清單嗎?</translation>
 <translation id="4414232939543644979">新增無痕式視窗(&amp;I)</translation>
@@ -5111,6 +5114,7 @@
 <translation id="4586275095964870617"><ph name="URL" /> 無法在替代瀏覽器中開啟。請聯絡您的系統管理員。</translation>
 <translation id="4587589328781138893">網站</translation>
 <translation id="4588749726511456218">捲動加速功能 <ph name="LINK_BEGIN" />瞭解詳情<ph name="LINK_END" /></translation>
+<translation id="4589197033939192905"><ph name="PASSWORD_DOMAIN" /> 和 <ph name="DOMAIN" /> 似乎有關聯。請確認你信任 <ph name="DOMAIN" />,再使用這個密碼。</translation>
 <translation id="4589713469967853491">記錄已成功寫入「下載」目錄。</translation>
 <translation id="4590785647529325123">如要刪除裝置上的無痕瀏覽記錄,請關閉所有無痕式分頁</translation>
 <translation id="459204634473266369"><ph name="PRIMARY_EMAIL" /> 中未儲存任何裝置</translation>
@@ -5616,6 +5620,7 @@
 <translation id="4946998421534856407">啟動器鍵 + 向上箭咀鍵</translation>
 <translation id="4947376546135294974">來自你正在瀏覽網站的資料</translation>
 <translation id="4950100687509657457">建立設定檔</translation>
+<translation id="4950360215042327246">[預留位置字串]</translation>
 <translation id="495164417696120157">{COUNT,plural, =1{1 個檔案}other{# 個檔案}}</translation>
 <translation id="495170559598752135">動作</translation>
 <translation id="4951966678293618079">一律不儲存此網站的密碼</translation>
@@ -5754,6 +5759,7 @@
 <translation id="5061531353537614467">凍原</translation>
 <translation id="5062930723426326933">無法登入,請重新連線至互聯網,然後再試一次。</translation>
 <translation id="5063480226653192405">使用狀況</translation>
+<translation id="5064921774605267982">開啟<ph name="PROFILE_NAME" />的設定檔。這個設定檔是由你的家長管理。</translation>
 <translation id="5065775832226780415">Smart Lock</translation>
 <translation id="5066100345385738837">在 Chrome OS 設定中管理安全 DNS</translation>
 <translation id="5066534201484101197">捲動回彈即可瀏覽頁面</translation>
@@ -6201,6 +6207,7 @@
 <translation id="5389224261615877010">彩虹</translation>
 <translation id="5389626883706033615">已禁止網站要求使用與你相關的既有資料</translation>
 <translation id="5389794555912875905">前往不安全的網站前先顯示警告 (建議)</translation>
+<translation id="5389943529251318913">將滑鼠速度降低</translation>
 <translation id="5390112241331447203">在意見報告中包含 system_logs.txt 檔案進行傳送。</translation>
 <translation id="5390677308841849479">深紅色和橙色</translation>
 <translation id="5392192690789334093">已允許傳送通知</translation>
@@ -7406,6 +7413,7 @@
 <translation id="6266984048393265562">自訂個人檔案</translation>
 <translation id="6267166720438879315">請選取您在 <ph name="HOST_NAME" /> 的驗證憑證</translation>
 <translation id="6268252012308737255">使用 <ph name="APP" /> 開啟</translation>
+<translation id="6269050081341530851">關閉重複的分頁時,系統會保留最舊的副本</translation>
 <translation id="6270309713620950855">靜音自動提醒</translation>
 <translation id="6270391203985052864">網站將可以要求向您傳送通知</translation>
 <translation id="6270486800167535228">固定咗擴充程式。揀就可以睇多啲選項</translation>
@@ -7947,6 +7955,7 @@
 <translation id="6679947539429331601">隱藏 12 小時</translation>
 <translation id="6680442031740878064">可用空間:<ph name="AVAILABLE_SPACE" /></translation>
 <translation id="6680650203439190394">語速</translation>
+<translation id="6682261381769522894"><ph name="WINDOW_TITLE" /> - [預留位置字串]</translation>
 <translation id="6683022854667115063">耳機</translation>
 <translation id="6683087162435654533">還原所有分頁</translation>
 <translation id="6683433919380522900">權限係<ph name="PERMISSION_STATE" /></translation>
@@ -8841,6 +8850,7 @@
 <translation id="7330533963640151632">「<ph name="USER_NAME" />」裝置的「<ph name="FEATURE_NAME" />」設定,所用分享帳戶為 <ph name="USER_EMAIL" />。</translation>
 <translation id="7331646370422660166">Alt 鍵 + 向下箭咀鍵</translation>
 <translation id="7332053360324989309">專用工作程式:<ph name="SCRIPT_URL" /></translation>
+<translation id="7332138995369063163">重複的分頁</translation>
 <translation id="7333388112938984914">使用 metered connection 時無法上載檔案。</translation>
 <translation id="7333669215417470379">備份及還原應用程式和設定</translation>
 <translation id="7335974957018254119">使用拼字檢查的語言:</translation>
diff --git a/chrome/app/resources/generated_resources_zh-TW.xtb b/chrome/app/resources/generated_resources_zh-TW.xtb
index 51d03a59..22de6c1 100644
--- a/chrome/app/resources/generated_resources_zh-TW.xtb
+++ b/chrome/app/resources/generated_resources_zh-TW.xtb
@@ -972,7 +972,7 @@
 <translation id="1654580009054503925">不允許顯示要求</translation>
 <translation id="1654713139320245449">找不到投放目的地。需要協助嗎?</translation>
 <translation id="1656528038316521561">背景不透明度</translation>
-<translation id="1657406563541664238">只要自動傳送使用統計資料及當機報告給 Google,就能助我們一臂之力,讓「<ph name="PRODUCT_NAME" />」更臻完美</translation>
+<translation id="1657406563541664238">只要自動傳送使用統計資料及當機報告給 Google,就能助我們一臂之力,讓 <ph name="PRODUCT_NAME" /> 更臻完美</translation>
 <translation id="1657937299377480641">你必須要求家長授予權限,才能再次登入帳戶並存取教育資源</translation>
 <translation id="1658424621194652532">這個網頁正在存取你的麥克風。</translation>
 <translation id="1660763353352708040">電源變壓器發生問題</translation>
@@ -1262,7 +1262,7 @@
 <translation id="1865769994591826607">僅限同網站連線</translation>
 <translation id="186594096341696655">降低取樣率</translation>
 <translation id="186612162884103683">「<ph name="EXTENSION" />」對於勾選位置中的圖片、影片和聲音檔,具有讀取和寫入權限。</translation>
-<translation id="1867780286110144690">「<ph name="PRODUCT_NAME" />」已準備好完成安裝程序</translation>
+<translation id="1867780286110144690"><ph name="PRODUCT_NAME" /> 已準備好完成安裝程序</translation>
 <translation id="1868553836791672080">Chromium 不支援密碼檢查功能</translation>
 <translation id="1868617395637139709">允許 Android 應用程式和服務使用位置資訊。</translation>
 <translation id="1869433484041798909">書籤按鈕</translation>
@@ -1494,6 +1494,7 @@
 <translation id="202352106777823113">下載時間過長,網路已中止下載。</translation>
 <translation id="2024195579772565064">刪除搜尋引擎</translation>
 <translation id="202500043506723828">EID</translation>
+<translation id="2025123106058020990">精確點擊</translation>
 <translation id="2025632980034333559"><ph name="APP_NAME" /> 當機了,請按一下這個提示框來重新載入擴充功能。</translation>
 <translation id="2026377162111110983">場域收音</translation>
 <translation id="2028449514182362831">需要動作感應器的功能將無法運作</translation>
@@ -4746,6 +4747,7 @@
 <translation id="4324577459193912240">檔案未完成下載</translation>
 <translation id="4325237902968425115">正在解除安裝「<ph name="LINUX_APP_NAME" />」...</translation>
 <translation id="4325433082696797523">儲存空間與電源</translation>
+<translation id="4325515113816851466">你登出後,系統就不會套用家長的選擇</translation>
 <translation id="4326146840124313313">Chrome 最強大的安全防護功能可進一步協助你防範危險的網站、下載內容和擴充功能</translation>
 <translation id="4327380114687339519">擴充功能選單</translation>
 <translation id="4330191372652740264">冰水</translation>
@@ -4868,6 +4870,7 @@
 <translation id="4412992751769744546">允許第三方 Cookie</translation>
 <translation id="4413087696295876280">讀取 ChromeOS Flex 裝置資訊和資料</translation>
 <translation id="44137799675104237">聆聽以自然語音朗讀的文字</translation>
+<translation id="4414051792721275732">使用手勢點選時,滑鼠速度會降低,讓你更容易控制。請再次做出手勢來完成點擊動作。</translation>
 <translation id="441418754432585599"><ph name="MODIFIER_ONE" /> + <ph name="MODIFIER_TWO" /> + <ph name="KEY" /> 鍵</translation>
 <translation id="44141919652824029">要允許「<ph name="APP_NAME" />」取得已連結 USB 裝置的清單嗎?</translation>
 <translation id="4414232939543644979">新增無痕視窗(&amp;I)</translation>
@@ -5104,6 +5107,7 @@
 <translation id="4586275095964870617">無法在替代瀏覽器中開啟 <ph name="URL" />。請與你的系統管理員聯絡。</translation>
 <translation id="4587589328781138893">網站</translation>
 <translation id="4588749726511456218">捲動加速功能 <ph name="LINK_BEGIN" />瞭解詳情<ph name="LINK_END" /></translation>
+<translation id="4589197033939192905"><ph name="PASSWORD_DOMAIN" /> 和 <ph name="DOMAIN" /> 似乎有關聯。請確認你信任 <ph name="DOMAIN" />,再使用這個密碼。</translation>
 <translation id="4589713469967853491">記錄已成功寫入「下載」目錄。</translation>
 <translation id="4590785647529325123">如要刪除裝置上的無痕模式瀏覽記錄,請關閉所有無痕分頁</translation>
 <translation id="459204634473266369"><ph name="PRIMARY_EMAIL" /> 中未儲存任何裝置</translation>
@@ -5609,6 +5613,7 @@
 <translation id="4946998421534856407">啟動鍵 + 向上鍵</translation>
 <translation id="4947376546135294974">來自你所造訪網站的資料</translation>
 <translation id="4950100687509657457">建立設定檔</translation>
+<translation id="4950360215042327246">[預留位置字串]</translation>
 <translation id="495164417696120157">{COUNT,plural, =1{1 個檔案}other{# 個檔案}}</translation>
 <translation id="495170559598752135">動作</translation>
 <translation id="4951966678293618079">一律不儲存這個網站的密碼</translation>
@@ -5747,6 +5752,7 @@
 <translation id="5061531353537614467">凍原</translation>
 <translation id="5062930723426326933">無法登入,請重新連線至網際網路並再試一次。</translation>
 <translation id="5063480226653192405">用量</translation>
+<translation id="5064921774605267982">開啟<ph name="PROFILE_NAME" />的設定檔。這個設定檔是由你的家長管理。</translation>
 <translation id="5065775832226780415">Smart Lock</translation>
 <translation id="5066100345385738837">在 Chrome OS 設定中管理安全 DNS</translation>
 <translation id="5066534201484101197">使用過度捲動效果瀏覽不同頁面</translation>
@@ -6194,6 +6200,7 @@
 <translation id="5389224261615877010">彩虹</translation>
 <translation id="5389626883706033615">已禁止網站要求使用與你相關的既有資訊</translation>
 <translation id="5389794555912875905">前往不安全的網站前發出警告 (建議)</translation>
+<translation id="5389943529251318913">將滑鼠速度降低</translation>
 <translation id="5390112241331447203">納入透過使用狀況報告所傳送的 system_logs.txt 檔案。</translation>
 <translation id="5390677308841849479">深紅色與橘色</translation>
 <translation id="5392192690789334093">允許傳送通知</translation>
@@ -7398,6 +7405,7 @@
 <translation id="6266984048393265562">自訂設定檔</translation>
 <translation id="6267166720438879315">請選取你在 <ph name="HOST_NAME" /> 的驗證憑證</translation>
 <translation id="6268252012308737255">使用「<ph name="APP" />」開啟</translation>
+<translation id="6269050081341530851">關閉重複的分頁時,系統會保留最舊的副本</translation>
 <translation id="6270309713620950855">將自動提醒設為靜音</translation>
 <translation id="6270391203985052864">網站可以要求傳送通知給你</translation>
 <translation id="6270486800167535228">擴充功能已固定。選取即可查看更多選項</translation>
@@ -7939,6 +7947,7 @@
 <translation id="6679947539429331601">隱藏 12 小時</translation>
 <translation id="6680442031740878064">可用空間:<ph name="AVAILABLE_SPACE" /></translation>
 <translation id="6680650203439190394">語速</translation>
+<translation id="6682261381769522894"><ph name="WINDOW_TITLE" /> - [預留位置字串]</translation>
 <translation id="6683022854667115063">耳罩式耳機</translation>
 <translation id="6683087162435654533">還原所有分頁</translation>
 <translation id="6683433919380522900">權限為<ph name="PERMISSION_STATE" /></translation>
@@ -8832,6 +8841,7 @@
 <translation id="7330533963640151632"><ph name="USER_NAME" />在裝置上的<ph name="FEATURE_NAME" />設定,透過 <ph name="USER_EMAIL" /> 帳戶分享。</translation>
 <translation id="7331646370422660166">alt + 向下鍵</translation>
 <translation id="7332053360324989309">專有 Worker:<ph name="SCRIPT_URL" /></translation>
+<translation id="7332138995369063163">重複的分頁</translation>
 <translation id="7333388112938984914">使用計量付費連線時無法上傳檔案。</translation>
 <translation id="7333669215417470379">備份及還原應用程式和設定</translation>
 <translation id="7335974957018254119">使用拼字檢查的語言:</translation>
diff --git a/chrome/app/resources/google_chrome_strings_ar.xtb b/chrome/app/resources/google_chrome_strings_ar.xtb
index f454d34..75e6b4f 100644
--- a/chrome/app/resources/google_chrome_strings_ar.xtb
+++ b/chrome/app/resources/google_chrome_strings_ar.xtb
@@ -566,7 +566,7 @@
 <translation id="7959172989483770734">‏إدارة الملفات الشخصية على Chrome</translation>
 <translation id="7962368738413920945">‏على الأرجح ستعمل المواقع الإلكترونية على النحو المتوقَّع، ولكنها لن تحفظ بياناتك بعد إغلاق جميع نوافذ Chrome.</translation>
 <translation id="7962410387636238736">‏لن يستلم جهاز الكمبيوتر هذا تحديثات Google Chrome لأن Windows XP وWindows Vista أصبحا غير مدعومين.</translation>
-<translation id="8005666035647241369">‏حفظ كلمة المرور في "مدير كلمات المرور" من Google على هذا الجهاز</translation>
+<translation id="8005666035647241369">‏في "مدير كلمات المرور في Google" على هذا الجهاز</translation>
 <translation id="8008534537613507642">‏إعادة تثبيت Chrome</translation>
 <translation id="8009904340233602924">‏استخدام Chrome بدون حساب</translation>
 <translation id="8010081455002666927">الرصد التلقائي</translation>
diff --git a/chrome/app/resources/google_chrome_strings_es.xtb b/chrome/app/resources/google_chrome_strings_es.xtb
index d3a3727d5..36b28abd 100644
--- a/chrome/app/resources/google_chrome_strings_es.xtb
+++ b/chrome/app/resources/google_chrome_strings_es.xtb
@@ -496,7 +496,7 @@
 <translation id="7106741999175697885">Administrador de tareas de Google Chrome</translation>
 <translation id="7140653346177713799">{COUNT,plural, =0{Hay una nueva actualización de Chrome disponible que se aplicará cuando reinicies el navegador.}=1{Hay una nueva actualización de Chrome disponible que se aplicará cuando reinicies el navegador. La ventana de Incógnito no se volverá a abrir.}other{Hay una nueva actualización de Chrome disponible que se aplicará cuando reinicies el navegador. Las # ventanas de Incógnito no se volverán a abrir.}}</translation>
 <translation id="7155997830309522122">Si es así, edita la contraseña guardada en Chrome para que coincida con la nueva.</translation>
-<translation id="7161904924553537242">Bienvenido a Google Chrome</translation>
+<translation id="7161904924553537242">Te damos la bienvenida a Google Chrome</translation>
 <translation id="7177959540995930968">Puedes obtener más información sobre estas funciones en la configuración de Chrome.</translation>
 <translation id="7193885263065350793">Tu organización cierra Chrome cuando lleva <ph name="TIMEOUT_DURATION" /> sin usarse.</translation>
 <translation id="7242029209006116544">Vas a iniciar sesión con una cuenta gestionada, lo que significa que proporcionarás a su administrador control sobre tu perfil de Google Chrome. Tus datos de Chrome como, por ejemplo, tus aplicaciones, tus marcadores, tu historial, tus contraseñas y otras opciones se vincularán de forma permanente a la cuenta <ph name="USER_NAME" />. Podrás eliminar estos datos a través del Panel de control de cuentas de Google, pero no podrás asociar estos datos a otra cuenta. De forma opcional, puedes crear un nuevo perfil para mantener separados tus datos de Chrome. <ph name="LEARN_MORE" /></translation>
diff --git a/chrome/app/resources/google_chrome_strings_fr.xtb b/chrome/app/resources/google_chrome_strings_fr.xtb
index 4f0abf4..9c5f667 100644
--- a/chrome/app/resources/google_chrome_strings_fr.xtb
+++ b/chrome/app/resources/google_chrome_strings_fr.xtb
@@ -323,7 +323,7 @@
 <translation id="4918844574251943176">Image copiée</translation>
 <translation id="492720062778050435">Chrome vous recommande d'examiner cette extension</translation>
 <translation id="4951177103388687412">Restez organisé et concentré grâce aux groupes d'onglets</translation>
-<translation id="4953650215774548573">Définir Google Chrome en tant que navigateur par défaut</translation>
+<translation id="4953650215774548573">Définir Google Chrome comme navigateur par défaut</translation>
 <translation id="495931528404527476">Dans Chrome</translation>
 <translation id="4969674060580488087">ChromeOS Flex n'a pas pu synchroniser vos données, car les infos de connexion de votre compte sont obsolètes.</translation>
 <translation id="4970761609246024540">Bienvenue sur la page de profils Chrome</translation>
diff --git a/chrome/app/resources/google_chrome_strings_it.xtb b/chrome/app/resources/google_chrome_strings_it.xtb
index 9557b08..91e81fa0 100644
--- a/chrome/app/resources/google_chrome_strings_it.xtb
+++ b/chrome/app/resources/google_chrome_strings_it.xtb
@@ -487,7 +487,7 @@
 <translation id="7106741999175697885">Task Manager - Google Chrome</translation>
 <translation id="7140653346177713799">{COUNT,plural, =0{È disponibile un nuovo aggiornamento di Chrome che verrà installato appena eseguirai il riavvio.}=1{È disponibile un nuovo aggiornamento di Chrome che verrà installato appena eseguirai il riavvio. La finestra di navigazione in incognito non verrà riaperta.}other{È disponibile un nuovo aggiornamento di Chrome che verrà installato appena eseguirai il riavvio. Le # finestre di navigazione in incognito non verranno riaperte.}}</translation>
 <translation id="7155997830309522122">In questo caso, modifica la password salvata su Chrome in modo che corrisponda alla nuova password.</translation>
-<translation id="7161904924553537242">Benvenuto in Google Chrome</translation>
+<translation id="7161904924553537242">Ti diamo il benvenuto in Google Chrome</translation>
 <translation id="7177959540995930968">Puoi scoprire di più su queste funzionalità nelle impostazioni di Chrome.</translation>
 <translation id="7193885263065350793">La tua organizzazione chiude Chrome quando non viene utilizzato per <ph name="TIMEOUT_DURATION" />.</translation>
 <translation id="7242029209006116544">Stai per accedere con un account gestito e per dare al relativo amministratore il controllo del tuo profilo Google Chrome. I tuoi dati di Chrome, come app, Preferiti, cronologia, password e altre impostazioni, verranno collegati definitivamente a <ph name="USER_NAME" />. Potrai eliminare questi dati tramite la Dashboard di Google Account, ma non potrai associare questi dati a un altro account. Se preferisci puoi creare un nuovo profilo per mantenere separati i dati di Chrome esistenti. <ph name="LEARN_MORE" /></translation>
diff --git a/chrome/app/resources/google_chrome_strings_ka.xtb b/chrome/app/resources/google_chrome_strings_ka.xtb
index 6a7096c1..28e2ee8 100644
--- a/chrome/app/resources/google_chrome_strings_ka.xtb
+++ b/chrome/app/resources/google_chrome_strings_ka.xtb
@@ -262,6 +262,7 @@
 <translation id="4147555960264124640">თქვენ სისტემაში შედიხართ მართული ანგარიშზით და მის ადმინისტრატორს აძლევთ თქვენი Google Chrome-ის პროფილის კონტროლის შესაძლებლობას. თქვენი Chrome მონაცემები, როგორიცაა თქვენი პროგრამები, სანიშნეები, ისტორია, პაროლები, და სხვა პარამეტრები გახდება მუდმივად <ph name="USER_NAME" />-თან მიბმული. თქვენ შეძლებთ ამ მონაცემების წაშლას Google Accounts Dashboard-ის მეშვეობით, მაგრამ თქვენ ვერ შეძლებთ ამ მონაცემების დაკავშირებას სხვა ანგარიშთან. <ph name="LEARN_MORE" /></translation>
 <translation id="4148957013307229264">ინსტალაცია…</translation>
 <translation id="4149882025268051530">ინსტალაციის პროგრამამ ვერ ამოიღო ფაილები არქივიდან. ხელახლა ჩამოტვირთეთ Google Chrome.</translation>
+<translation id="415112847282352845">შედით Chrome-ში, რომ მიიღოთ მისამართები და სხვა მონაცემები თქვენს ყველა მოწყობილობაზე. შესვლის შემდეგ ეს მისამართი შეინახება თქვენს Google ანგარიშში.</translation>
 <translation id="4153934450158521343">Chrome მალე დაიხურება, ხოლო მონაცემები წაიშლება</translation>
 <translation id="4173512894976930765">საიტები, სავარაუდოდ, არ იმუშავებს მოლოდინისამებრ. Chrome-ის ყველა ფანჯრის დახურვისას სისტემიდან გამოხვალთ საიტების უმეტესობაზე, გამონაკლისია თქვენი Google ანგარიში, თუ მასში შესული ხართ Chrome-იდან.</translation>
 <translation id="4175922240926474352">Chrome-მა დაბლოკა ეს ჩამოტვირთვა, რადგან ეს საიტი არ იყენებს დაცულ კავშირს, ამიტომ ფაილი, შესაძლოა, მოდიფიცირებული იყოს</translation>
diff --git a/chrome/app/resources/google_chrome_strings_lo.xtb b/chrome/app/resources/google_chrome_strings_lo.xtb
index 47216573..3ee1d72b 100644
--- a/chrome/app/resources/google_chrome_strings_lo.xtb
+++ b/chrome/app/resources/google_chrome_strings_lo.xtb
@@ -262,6 +262,7 @@
 <translation id="4147555960264124640">ທ່ານກໍາລັງລົງຊື່ເຂົ້າໃຊ້ດ້ວຍບັນຊີຄຸ້ມຄອງ ແລະໃຫ້ຜູ້ຄວບຄູມຂອງມັນຄວບຄຸມໂປຣໄຟລ໌ Google Chrome ຂອງທ່ານ. ຂໍ້ມູນ Chrome ຂອງທ່ານ, ເຊັ່ນ ແອັບ, ບຸກມາກສ໌, ປະຫວັດ, ລະຫັດຜ່ານ, ແລະການຕັ້ງອື່ນຂອງທ່ານຈະຖືກຜູກ​ມັດ​ກັບ <ph name="USER_NAME" /> ຢ່າງຖາວອນ. ທ່ານຈະສາມາດລຶບຂໍ້ມູນນີ້ໄດ້ຜ່ານ Google Accounts Dashboard, ແຕ່ທ່ານຈະບໍ່ສາມາດນໍາເອົາຂໍ້ມູນນີ້ມາກ່ຽວຂ້ອງກັບບັນຊີອື່ນໄດ້. <ph name="LEARN_MORE" /></translation>
 <translation id="4148957013307229264">ກໍາລັງ​ຕິດ​ຕັ້ງ...</translation>
 <translation id="4149882025268051530">ຕົວຕິດຕັ້ງບໍ່ສາມາດ​ຄາຍ​ການບີບອັດຈາກຄັງເກັບມ້ຽນ. ກະລຸນາດາວໂຫຼດ Google Chrome ອີກ.</translation>
+<translation id="415112847282352845">ເພື່ອຮັບທີ່ຢູ່ ແລະ ຂໍ້ມູນອື່ນໆຂອງທ່ານໃນອຸປະກອນທຸກເຄື່ອງຂອງທ່ານ, ໃຫ້ເຂົ້າສູ່ລະບົບ Chrome. ລະບົບຈະບັນທຶກທີ່ຢູ່ນີ້ໄວ້ໃນບັນຊີ Google ຂອງທ່ານຫຼັງຈາກທີ່ທ່ານເຂົ້າສູ່ລະບົບ.</translation>
 <translation id="4153934450158521343">Chrome ຈະປິດ ແລະ ລຶບຂໍ້ມູນໃນໄວໆນີ້</translation>
 <translation id="4173512894976930765">ເວັບໄຊອາດເຮັດວຽກຕາມທີ່ຄາດໄວ້. ທ່ານຈະອອກຈາກລະບົບຂອງເວັບໄຊສ່ວນໃຫຍ່ເມື່ອທ່ານປິດໜ້າຈໍ Chrome ທັງໝົດຍົກເວັ້ນບັນຊີ Google ຂອງທ່ານຫາກທ່ານເຂົ້າສູ່ລະບົບ Chrome.</translation>
 <translation id="4175922240926474352">Chrome ບລັອກການດາວໂຫຼດນີ້ ເນື່ອງຈາກເວັບໄຊບໍ່ໄດ້ໃຊ້ການເຊື່ອມຕໍ່ທີ່ປອດໄພ ແລະ ໄຟລ໌ອາດມີການດັດແປງ</translation>
diff --git a/chrome/app/resources/google_chrome_strings_zh-CN.xtb b/chrome/app/resources/google_chrome_strings_zh-CN.xtb
index 330230f..1c65129 100644
--- a/chrome/app/resources/google_chrome_strings_zh-CN.xtb
+++ b/chrome/app/resources/google_chrome_strings_zh-CN.xtb
@@ -60,7 +60,7 @@
 <translation id="1722488837206509557">这样,您就可以从可用设备中选择并在这些设备上显示内容。</translation>
 <translation id="1734234790201236882">Chrome 会将此密码保存在您的 Google 账号中,因此您不必记住它。</translation>
 <translation id="1786003790898721085">请确保您已在“<ph name="TARGET_DEVICE_NAME" />”上登录 Chrome,然后再次尝试发送。</translation>
-<translation id="1786044937610313874">在 Chrome 中打开快捷方式</translation>
+<translation id="1786044937610313874">快捷方式会在 Chrome 中打开</translation>
 <translation id="178701303897325119">此扩展程序已不再受支持。Chrome 建议您移除它。</translation>
 <translation id="1812689907177901597">关闭此设置后,您无需登录 Chrome 即可登录 Gmail 等 Google 网站</translation>
 <translation id="1860536484129686729">Chrome 需要获得相应权限,才能允许此网站使用您的摄像头</translation>
diff --git a/chrome/app/resources/google_chrome_strings_zh-HK.xtb b/chrome/app/resources/google_chrome_strings_zh-HK.xtb
index 9d9ebb73..6cae6eb 100644
--- a/chrome/app/resources/google_chrome_strings_zh-HK.xtb
+++ b/chrome/app/resources/google_chrome_strings_zh-HK.xtb
@@ -261,6 +261,7 @@
 <translation id="4147555960264124640">您已登入受管理的帳戶,並將管理控制權授予您的 Chrome 設定檔。您的 Chrome 數據 (例如應用程式、書籤、記錄、密碼和其他設定) 均將永久與 <ph name="USER_NAME" /> 建立關聯。您可以透過 Google 帳戶資訊主頁刪除這些數據,但您無法將這些數據與其他帳戶建立關聯。<ph name="LEARN_MORE" /></translation>
 <translation id="4148957013307229264">安裝中…</translation>
 <translation id="4149882025268051530">安裝程式無法解壓縮封存檔案,請再次下載 Google Chrome。</translation>
+<translation id="415112847282352845">如要在所有裝置上使用你的地址和其他資料,請登入 Chrome。登入後,這個地址就會儲存到 Google 帳戶。</translation>
 <translation id="4153934450158521343">Chrome 即將關閉並刪除資料</translation>
 <translation id="4173512894976930765">網站可能會正常運作。關閉所有 Chrome 視窗後,系統會將你登出所有網站,但如果你已登入 Chrome,Google 帳戶就會維持登入狀態。</translation>
 <translation id="4175922240926474352">由於此網站未使用安全連線,且檔案可能已被篡改,因此 Chrome 已禁止下載</translation>
diff --git a/chrome/app/resources/google_chrome_strings_zh-TW.xtb b/chrome/app/resources/google_chrome_strings_zh-TW.xtb
index 3ade311..061377c6 100644
--- a/chrome/app/resources/google_chrome_strings_zh-TW.xtb
+++ b/chrome/app/resources/google_chrome_strings_zh-TW.xtb
@@ -258,6 +258,7 @@
 <translation id="4147555960264124640">你已登入管理化環境下的帳戶,並將管理控制權授予你的 Chrome 設定檔。你的 Chrome 資料 (例如應用程式、書籤、記錄、密碼和其他設定) 均將永久與 <ph name="USER_NAME" /> 建立關聯。你可以透過 Google 帳戶資訊主頁刪除這些資料,但你無法將這些資料與其他帳戶建立關聯。<ph name="LEARN_MORE" /></translation>
 <translation id="4148957013307229264">安裝中...</translation>
 <translation id="4149882025268051530">安裝程式無法解壓縮封存檔案,請再次下載 Google Chrome。</translation>
+<translation id="415112847282352845">如要在所有裝置上使用你的地址和其他資料,請登入 Chrome。登入後,這個地址就會儲存到 Google 帳戶。</translation>
 <translation id="4153934450158521343">Chrome 即將關閉並刪除資料</translation>
 <translation id="4173512894976930765">網站可能會正常運作。關閉所有 Chrome 視窗後,系統會將你登出大部分網站,但如果你已登入 Chrome,Google 帳戶就會維持登入狀態。</translation>
 <translation id="4175922240926474352">這個網站沒有使用安全連線,檔案可能已經遭人竄改,因此 Chrome 已禁止下載</translation>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 0e22dc9..eed17e4 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -3111,6 +3111,7 @@
       "search_resumption/start_suggest_service_factory.cc",
       "search_resumption/start_suggest_service_factory.h",
       "segmentation_platform/android/contextual_page_action_controller_android.cc",
+      "segmentation_platform/android/home_modules_ranking_helper.cc",
       "segmentation_platform/android/segmentation_platform_service_factory_android.cc",
       "segmentation_platform/client_util/tab_data_collection_util.cc",
       "segmentation_platform/client_util/tab_data_collection_util.h",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 604c5f97..218a5ee 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -386,6 +386,10 @@
 #include "skia/rusty_png_feature.h"
 #endif
 
+#if !BUILDFLAG(IS_CHROMEOS)
+#include "components/variations/net/variations_command_line.h"
+#endif
+
 using flags_ui::FeatureEntry;
 using flags_ui::kDeprecated;
 using flags_ui::kOsAndroid;
@@ -4155,6 +4159,17 @@
          std::size(kSecurePaymentConfirmationNetworkAndIssuerIcons_Rows),
          nullptr}};
 
+const FeatureEntry::FeatureParam kSkiaGraphite_ValidationEnabled[] = {
+    {"dawn_skip_validation", "false"}};
+const FeatureEntry::FeatureParam kSkiaGraphite_ValidationDisabled[] = {
+    {"dawn_skip_validation", "true"}};
+
+const FeatureEntry::FeatureVariation kSkiaGraphiteVariations[] = {
+    {"dawn frontend validation enabled", kSkiaGraphite_ValidationEnabled,
+     std::size(kSkiaGraphite_ValidationEnabled), nullptr},
+    {"dawn frontend validation disabled", kSkiaGraphite_ValidationDisabled,
+     std::size(kSkiaGraphite_ValidationDisabled), nullptr}};
+
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
 const FeatureEntry::FeatureParam kTranslationAPI_SkipLanguagePackLimit[] = {
     {"TranslationAPIAcceptLanguagesCheck", "false"},
@@ -4409,6 +4424,13 @@
     {"show-overdraw-feedback", flag_descriptions::kShowOverdrawFeedbackName,
      flag_descriptions::kShowOverdrawFeedbackDescription, kOsAll,
      SINGLE_VALUE_TYPE(switches::kShowOverdrawFeedback)},
+#if !BUILDFLAG(IS_CHROMEOS)
+    {"feedback-include-variations",
+     flag_descriptions::kFeedbackIncludeVariationsName,
+     flag_descriptions::kFeedbackIncludeVariationsDescription,
+     kOsWin | kOsLinux | kOsMac,
+     FEATURE_VALUE_TYPE(variations::kFeedbackIncludeVariations)},
+#endif
     {"ui-disable-partial-swap", flag_descriptions::kUiPartialSwapName,
      flag_descriptions::kUiPartialSwapDescription, kOsAll,
      SINGLE_DISABLE_VALUE_TYPE(switches::kUIDisablePartialSwap)},
@@ -7388,11 +7410,6 @@
      flag_descriptions::kTabDragDropDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(chrome::android::kTabDragDropAndroid)},
 
-    {"enable-tablet-toolbar-reordering",
-     flag_descriptions::kTabletToolbarReorderingAndroidName,
-     flag_descriptions::kTabletToolbarReorderingAndroidDescription, kOsAndroid,
-     FEATURE_VALUE_TYPE(chrome::android::kTabletToolbarReordering)},
-
     {"enable-delay-temp-strip-removal",
      flag_descriptions::kDelayTempStripRemovalName,
      flag_descriptions::kDelayTempStripRemovalDescription, kOsAndroid,
@@ -7910,10 +7927,6 @@
      flag_descriptions::kFastPairHandshakeLongTermRefactorDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(ash::features::kFastPairHandshakeLongTermRefactor)},
 
-    {"fast-pair-hid", flag_descriptions::kFastPairHIDName,
-     flag_descriptions::kFastPairHIDDescription, kOsCrOS,
-     FEATURE_VALUE_TYPE(ash::features::kFastPairHID)},
-
     {"fast-pair-keyboards", flag_descriptions::kFastPairKeyboardsName,
      flag_descriptions::kFastPairKeyboardsDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(ash::features::kFastPairKeyboards)},
@@ -9265,7 +9278,9 @@
 
     {"skia-graphite", flag_descriptions::kSkiaGraphiteName,
      flag_descriptions::kSkiaGraphiteDescription, kOsAll,
-     FEATURE_VALUE_TYPE(features::kSkiaGraphite)},
+     FEATURE_WITH_PARAMS_VALUE_TYPE(features::kSkiaGraphite,
+                                    kSkiaGraphiteVariations,
+                                    "SkiaGraphite")},
 
     {"skia-graphite-precompilation",
      flag_descriptions::kSkiaGraphitePrecompilationName,
@@ -11098,13 +11113,6 @@
          kThreadedScrollPreventRenderingStarvationVariations,
          "ThreadedScrollPreventRenderingStarvation")},
 
-#if BUILDFLAG(IS_CHROMEOS)
-    {"allow-fpmcu-beta-firmware",
-     flag_descriptions::kAllowFpmcuBetaFirmwareName,
-     flag_descriptions::kAllowFpmcuBetaFirmwareDescription, kOsCrOS,
-     PLATFORM_FEATURE_NAME_TYPE("CrOSLateBootAllowFpmcuBetaFirmware")},
-#endif  // BUILDFLAG(IS_CHROMEOS)
-
     {"autofill-upload-card-request-timeout",
      flag_descriptions::kAutofillUploadCardRequestTimeoutName,
      flag_descriptions::kAutofillUploadCardRequestTimeoutDescription, kOsAll,
diff --git a/chrome/browser/android/browsing_data/browsing_data_counter_bridge.cc b/chrome/browser/android/browsing_data/browsing_data_counter_bridge.cc
index 8bdc6e77..c4486c5b 100644
--- a/chrome/browser/android/browsing_data/browsing_data_counter_bridge.cc
+++ b/chrome/browser/android/browsing_data/browsing_data_counter_bridge.cc
@@ -22,6 +22,7 @@
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
     Profile* profile,
+    jint selected_time_period,
     jint data_type,
     jint clear_browsing_data_tab)
     : jobject_(obj) {
@@ -51,14 +52,27 @@
   if (!counter_)
     return;
 
-  counter_->Init(
+  counter_->InitWithoutPeriodPref(
       profile_->GetPrefs(), clear_browsing_data_tab_,
+      CalculateBeginDeleteTime(
+          static_cast<browsing_data::TimePeriod>(selected_time_period)),
       base::BindRepeating(&BrowsingDataCounterBridge::onCounterFinished,
                           base::Unretained(this)));
   counter_->Restart();
 }
 
-BrowsingDataCounterBridge::~BrowsingDataCounterBridge() {
+BrowsingDataCounterBridge::~BrowsingDataCounterBridge() = default;
+
+void BrowsingDataCounterBridge::SetSelectedTimePeriod(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint selected_time_period) {
+  if (!counter_) {
+    return;
+  }
+
+  counter_->SetBeginTime(CalculateBeginDeleteTime(
+      static_cast<browsing_data::TimePeriod>(selected_time_period)));
 }
 
 void BrowsingDataCounterBridge::Destroy(JNIEnv* env,
@@ -75,12 +89,14 @@
                                                                   profile_));
 }
 
-static jlong JNI_BrowsingDataCounterBridge_Init(
+static jlong JNI_BrowsingDataCounterBridge_InitWithoutPeriodPref(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
     Profile* profile,
+    jint selected_time_period,
     jint data_type,
     jint clear_browsing_data_tab) {
-  return reinterpret_cast<intptr_t>(new BrowsingDataCounterBridge(
-      env, obj, profile, data_type, clear_browsing_data_tab));
+  return reinterpret_cast<intptr_t>(
+      new BrowsingDataCounterBridge(env, obj, profile, selected_time_period,
+                                    data_type, clear_browsing_data_tab));
 }
diff --git a/chrome/browser/android/browsing_data/browsing_data_counter_bridge.h b/chrome/browser/android/browsing_data/browsing_data_counter_bridge.h
index ae15196f..d839411c 100644
--- a/chrome/browser/android/browsing_data/browsing_data_counter_bridge.h
+++ b/chrome/browser/android/browsing_data/browsing_data_counter_bridge.h
@@ -21,6 +21,7 @@
   BrowsingDataCounterBridge(JNIEnv* env,
                             const base::android::JavaParamRef<jobject>& obj,
                             Profile* profile,
+                            jint selected_time_period,
                             jint data_type,
                             jint clear_browsing_data_tab);
 
@@ -30,8 +31,12 @@
 
   ~BrowsingDataCounterBridge();
 
-  // Destroys the BrowsingDataCounterBridge object. This needs to be called on
-  // the java side when the object is not in use anymore.
+  void SetSelectedTimePeriod(JNIEnv* env,
+                             const base::android::JavaParamRef<jobject>& obj,
+                             jint selected_time_period);
+
+  // Destroys the BrowsingDataCounterBridge object. This needs to be called
+  // on the java side when the object is not in use anymore.
   void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
 
  private:
diff --git a/chrome/browser/ash/app_mode/BUILD.gn b/chrome/browser/ash/app_mode/BUILD.gn
index b8d7486..1b92dcd 100644
--- a/chrome/browser/ash/app_mode/BUILD.gn
+++ b/chrome/browser/ash/app_mode/BUILD.gn
@@ -74,6 +74,7 @@
     "//chrome/browser/ash/system",
     "//chrome/browser/extensions:cws_item_service_proto",
     "//chrome/browser/web_applications",
+    "//chromeos/ash/components/dbus/cros_disks",
     "//chromeos/ash/components/dbus/userdataauth",
     "//chromeos/ash/components/disks",
     "//chromeos/ash/components/install_attributes",
diff --git a/chrome/browser/ash/app_mode/kiosk_chrome_app_manager.cc b/chrome/browser/ash/app_mode/kiosk_chrome_app_manager.cc
index aa660d1..4f1442db 100644
--- a/chrome/browser/ash/app_mode/kiosk_chrome_app_manager.cc
+++ b/chrome/browser/ash/app_mode/kiosk_chrome_app_manager.cc
@@ -10,6 +10,8 @@
 #include <memory>
 #include <optional>
 #include <string>
+#include <string_view>
+#include <tuple>
 #include <utility>
 #include <vector>
 
@@ -278,9 +280,10 @@
 
 void KioskChromeAppManager::OnExternalCacheDamaged(const std::string& app_id) {
   CHECK(external_cache_);
-  base::FilePath crx_path;
-  std::string version;
-  GetCachedCrx(app_id, &crx_path, &version);
+  auto crx_info = GetCachedCrx(app_id);
+  // TODO(crbug.com/383090254): Consider making this a CHECK.
+  DUMP_WILL_BE_CHECK(crx_info.has_value());
+  auto [crx_path, _] = std::move(crx_info).value_or(CachedCrxInfo());
   external_cache_->OnDamagedFileDetected(crx_path);
 }
 
@@ -370,15 +373,16 @@
 }
 
 bool KioskChromeAppManager::HasCachedCrx(const std::string& app_id) const {
-  base::FilePath crx_path;
-  std::string version;
-  return GetCachedCrx(app_id, &crx_path, &version);
+  return GetCachedCrx(app_id).has_value();
 }
 
-bool KioskChromeAppManager::GetCachedCrx(const std::string& app_id,
-                                         base::FilePath* file_path,
-                                         std::string* version) const {
-  return external_cache_->GetExtension(app_id, file_path, version);
+std::optional<KioskChromeAppManager::CachedCrxInfo>
+KioskChromeAppManager::GetCachedCrx(std::string_view app_id) const {
+  base::FilePath path;
+  std::string version;
+  return external_cache_->GetExtension(std::string(app_id), &path, &version)
+             ? std::make_optional(std::make_tuple(path, version))
+             : std::nullopt;
 }
 
 crosapi::mojom::AppInstallParams
@@ -577,13 +581,12 @@
       apps_.push_back(std::move(old_it->second));
       old_apps.erase(old_it);
     } else {
-      base::FilePath cached_crx;
-      std::string version;
-      GetCachedCrx(device_local_account.kiosk_app_id, &cached_crx, &version);
+      auto [crx_path, _] = GetCachedCrx(device_local_account.kiosk_app_id)
+                               .value_or(CachedCrxInfo());
 
       apps_.push_back(std::make_unique<KioskAppData>(
           *this, device_local_account.kiosk_app_id, account_id,
-          GURL(device_local_account.kiosk_app_update_url), cached_crx));
+          GURL(device_local_account.kiosk_app_update_url), crx_path));
       apps_.back()->Load();
     }
     KioskCryptohomeRemover::CancelDelayedCryptohomeRemoval(account_id);
@@ -632,9 +635,8 @@
     return;
   }
 
-  base::FilePath crx_path;
-  std::string version;
-  if (GetCachedCrx(id, &crx_path, &version)) {
+  if (auto crx_info = GetCachedCrx(id); crx_info.has_value()) {
+    auto& [crx_path, _] = crx_info.value();
     app_data->SetCachedCrx(crx_path);
   }
 
diff --git a/chrome/browser/ash/app_mode/kiosk_chrome_app_manager.h b/chrome/browser/ash/app_mode/kiosk_chrome_app_manager.h
index 78dc5c7..d5925de7 100644
--- a/chrome/browser/ash/app_mode/kiosk_chrome_app_manager.h
+++ b/chrome/browser/ash/app_mode/kiosk_chrome_app_manager.h
@@ -8,6 +8,8 @@
 #include <memory>
 #include <optional>
 #include <string>
+#include <string_view>
+#include <tuple>
 #include <vector>
 
 #include "base/time/time.h"
@@ -48,6 +50,9 @@
 class KioskChromeAppManager : public KioskAppManagerBase,
                               public chromeos::ExternalCacheDelegate {
  public:
+  // A tuple with the path and version string of a CRX in the external cache.
+  using CachedCrxInfo = std::tuple<base::FilePath, std::string>;
+
   // Result of downloading primary app from ExternalCache. Should be in sync
   // with extensions::ExtensionDownloaderDelegate::Error. Used in UMA metrics.
   enum class PrimaryAppDownloadResult {
@@ -149,11 +154,9 @@
   // Returns true if the app is found in cache.
   bool HasCachedCrx(const std::string& app_id) const;
 
-  // Gets the path and version of the cached crx with `app_id`.
-  // Returns true if the app is found in cache.
-  bool GetCachedCrx(const std::string& app_id,
-                    base::FilePath* file_path,
-                    std::string* version) const;
+  // Returns the path and version of the cached CRX with `app_id`, or `nullopt`
+  // if the app is not found in cache.
+  std::optional<CachedCrxInfo> GetCachedCrx(std::string_view app_id) const;
 
   crosapi::mojom::AppInstallParams CreatePrimaryAppInstallData(
       const std::string& id) const;
diff --git a/chrome/browser/ash/app_mode/kiosk_chrome_app_manager_browsertest.cc b/chrome/browser/ash/app_mode/kiosk_chrome_app_manager_browsertest.cc
index 45909102..e094a7c0 100644
--- a/chrome/browser/ash/app_mode/kiosk_chrome_app_manager_browsertest.cc
+++ b/chrome/browser/ash/app_mode/kiosk_chrome_app_manager_browsertest.cc
@@ -13,6 +13,7 @@
 
 #include <iterator>
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 
@@ -286,12 +287,6 @@
                                  base::Value(std::move(device_local_accounts)));
   }
 
-  bool GetCachedCrx(const std::string& app_id,
-                    base::FilePath* file_path,
-                    std::string* version) {
-    return manager()->GetCachedCrx(app_id, file_path, version);
-  }
-
   void UpdateAppsFromPolicy() { manager()->UpdateAppsFromPolicy(); }
 
   void CheckAppData(const std::string& app_id,
@@ -356,9 +351,9 @@
     EXPECT_EQ(waiter.data_load_failure_count(), 0);
 
     // Check CRX file is cached.
-    base::FilePath crx_path;
-    std::string crx_version;
-    EXPECT_TRUE(GetCachedCrx(id, &crx_path, &crx_version));
+    auto crx_info = manager()->GetCachedCrx(id);
+    ASSERT_TRUE(crx_info.has_value());
+    auto& [crx_path, crx_version] = crx_info.value();
     {
       base::ScopedAllowBlockingForTesting allow_io;
       EXPECT_TRUE(base::PathExists(crx_path));
@@ -700,14 +695,15 @@
   // Add a new app.
   RunAddNewAppTest(kTestLocalFsKioskApp, "1.0.0", kTestLocalFsKioskAppName, "");
   ASSERT_EQ(1u, manager()->GetApps().size());
-  base::FilePath crx_path;
-  std::string version;
-  EXPECT_TRUE(GetCachedCrx(kTestLocalFsKioskApp, &crx_path, &version));
+
+  auto crx_info = manager()->GetCachedCrx(kTestLocalFsKioskApp);
+  ASSERT_TRUE(crx_info.has_value());
+  auto& [crx_path, crx_version] = crx_info.value();
   {
     base::ScopedAllowBlockingForTesting allow_io;
     EXPECT_TRUE(base::PathExists(crx_path));
   }
-  EXPECT_EQ("1.0.0", version);
+  EXPECT_EQ("1.0.0", crx_version);
 
   // Remove the app now.
   RemoveConsumerKioskChromeAppForTesting(
@@ -719,7 +715,7 @@
     base::ScopedAllowBlockingForTesting allow_io;
     EXPECT_FALSE(base::PathExists(crx_path));
   }
-  EXPECT_FALSE(GetCachedCrx(kTestLocalFsKioskApp, &crx_path, &version));
+  EXPECT_EQ(manager()->GetCachedCrx(kTestLocalFsKioskApp), std::nullopt);
 }
 
 IN_PROC_BROWSER_TEST_F(ChromeAppKioskAppManagerTest, UpdateApp) {
@@ -731,14 +727,15 @@
   // Add a version 1 app first.
   RunAddNewAppTest(kTestLocalFsKioskApp, "1.0.0", kTestLocalFsKioskAppName, "");
   ASSERT_EQ(1u, manager()->GetApps().size());
-  base::FilePath crx_path;
-  std::string version;
-  EXPECT_TRUE(GetCachedCrx(kTestLocalFsKioskApp, &crx_path, &version));
+
+  auto crx_info = manager()->GetCachedCrx(kTestLocalFsKioskApp);
+  ASSERT_TRUE(crx_info.has_value());
+  auto& [crx_path, crx_version] = crx_info.value();
   {
     base::ScopedAllowBlockingForTesting allow_io;
     EXPECT_TRUE(base::PathExists(crx_path));
   }
-  EXPECT_EQ("1.0.0", version);
+  EXPECT_EQ("1.0.0", crx_version);
 
   // Update to version 2.
   fake_cws()->SetUpdateCrx(
@@ -752,14 +749,16 @@
 
   // Verify the app has been updated to v2.
   ASSERT_EQ(1u, manager()->GetApps().size());
-  base::FilePath new_crx_path;
-  std::string new_version;
-  EXPECT_TRUE(GetCachedCrx(kTestLocalFsKioskApp, &new_crx_path, &new_version));
-  EXPECT_EQ("2.0.0", new_version);
+
+  auto new_crx_info = manager()->GetCachedCrx(kTestLocalFsKioskApp);
+  ASSERT_TRUE(new_crx_info.has_value());
+  auto& [new_crx_path, new_crx_version] = new_crx_info.value();
   {
     base::ScopedAllowBlockingForTesting allow_io;
     EXPECT_TRUE(base::PathExists(new_crx_path));
   }
+  EXPECT_EQ("2.0.0", new_crx_version);
+
   // Get original version 2 source download crx file path.
   base::FilePath test_data_dir;
   base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
@@ -782,14 +781,15 @@
   // Add a version 1 app first.
   RunAddNewAppTest(kTestLocalFsKioskApp, "1.0.0", kTestLocalFsKioskAppName, "");
   ASSERT_EQ(1u, manager()->GetApps().size());
-  base::FilePath v1_crx_path;
-  std::string version;
-  EXPECT_TRUE(GetCachedCrx(kTestLocalFsKioskApp, &v1_crx_path, &version));
+
+  auto v1_crx_info = manager()->GetCachedCrx(kTestLocalFsKioskApp);
+  ASSERT_TRUE(v1_crx_info.has_value());
+  auto& [v1_crx_path, v1_crx_version] = v1_crx_info.value();
   {
     base::ScopedAllowBlockingForTesting allow_io;
     EXPECT_TRUE(base::PathExists(v1_crx_path));
   }
-  EXPECT_EQ("1.0.0", version);
+  EXPECT_EQ("1.0.0", v1_crx_version);
 
   // Update to version 2.
   fake_cws()->SetUpdateCrx(
@@ -803,12 +803,12 @@
 
   // Verify the app has been updated to v2.
   ASSERT_EQ(1u, manager()->GetApps().size());
-  base::FilePath v2_crx_path;
-  std::string new_version;
-  EXPECT_TRUE(GetCachedCrx(kTestLocalFsKioskApp, &v2_crx_path, &new_version));
-  EXPECT_EQ("2.0.0", new_version);
-  // Verify both v1 and v2 crx files exist.
+  auto v2_crx_info = manager()->GetCachedCrx(kTestLocalFsKioskApp);
+  ASSERT_TRUE(v2_crx_info.has_value());
+  auto& [v2_crx_path, v2_crx_version] = v2_crx_info.value();
+  EXPECT_EQ("2.0.0", v2_crx_version);
   {
+    // Verify both v1 and v2 crx files exist.
     base::ScopedAllowBlockingForTesting allow_io;
     EXPECT_TRUE(base::PathExists(v1_crx_path));
     EXPECT_TRUE(base::PathExists(v2_crx_path));
@@ -826,7 +826,7 @@
     EXPECT_FALSE(base::PathExists(v1_crx_path));
     EXPECT_FALSE(base::PathExists(v2_crx_path));
   }
-  EXPECT_FALSE(GetCachedCrx(kTestLocalFsKioskApp, &v2_crx_path, &version));
+  EXPECT_EQ(manager()->GetCachedCrx(kTestLocalFsKioskApp), std::nullopt);
 }
 
 IN_PROC_BROWSER_TEST_F(ChromeAppKioskAppManagerTest,
diff --git a/chrome/browser/ash/app_mode/kiosk_external_updater.cc b/chrome/browser/ash/app_mode/kiosk_external_updater.cc
index 3623fba..1f12f9b 100644
--- a/chrome/browser/ash/app_mode/kiosk_external_updater.cc
+++ b/chrome/browser/ash/app_mode/kiosk_external_updater.cc
@@ -4,21 +4,34 @@
 
 #include "chrome/browser/ash/app_mode/kiosk_external_updater.h"
 
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/check.h"
+#include "base/check_deref.h"
+#include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/functional/bind.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/notreached.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/sequenced_task_runner.h"
+#include "base/values.h"
 #include "base/version.h"
+#include "base/version_info/version_info.h"
 #include "chrome/browser/ash/app_mode/kiosk_chrome_app_manager.h"
+#include "chrome/browser/ash/app_mode/kiosk_external_update_validator.h"
 #include "chrome/browser/ash/notifications/kiosk_external_update_notification.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/version_info/version_info.h"
+#include "chromeos/ash/components/dbus/cros_disks/cros_disks_client.h"
+#include "chromeos/ash/components/disks/disk_mount_manager.h"
 #include "content/public/browser/browser_thread.h"
+#include "extensions/browser/crx_file_info.h"
 #include "extensions/browser/sandboxed_unpacker.h"
-#include "extensions/common/extension.h"
 #include "extensions/common/verifier_formats.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -205,17 +218,19 @@
     const ParseManifestResult& result) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
+  auto& manager = CHECK_DEREF(KioskChromeAppManager::Get());
+
   const base::Value& parsed_manifest = result.first;
   ErrorCode parsing_error = result.second;
   if (parsing_error == ErrorCode::kNoManifest) {
-    KioskChromeAppManager::Get()->OnKioskAppExternalUpdateComplete(false);
+    manager.OnKioskAppExternalUpdateComplete(false);
     return;
   }
   if (parsing_error == ErrorCode::kInvalidManifest) {
     NotifyKioskUpdateProgress(
         ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
             IDS_KIOSK_EXTERNAL_UPDATE_INVALID_MANIFEST));
-    KioskChromeAppManager::Get()->OnKioskAppExternalUpdateComplete(false);
+    manager.OnKioskAppExternalUpdateComplete(false);
     return;
   }
 
@@ -224,15 +239,16 @@
           IDS_KIOSK_EXTERNAL_UPDATE_IN_PROGRESS));
 
   external_update_path_ = external_update_dir;
+
   for (auto manifest : parsed_manifest.GetDict()) {
     std::string app_id = manifest.first;
-    std::string cached_version_str;
-    base::FilePath cached_crx;
-    if (!KioskChromeAppManager::Get()->GetCachedCrx(app_id, &cached_crx,
-                                                    &cached_version_str)) {
+
+    auto crx_info = manager.GetCachedCrx(app_id);
+    if (!crx_info.has_value()) {
       LOG(WARNING) << "Can't find app in existing cache " << app_id;
       continue;
     }
+    auto& [_, cached_crx_version] = crx_info.value();
 
     if (!manifest.second.is_dict()) {
       LOG(ERROR) << "Found bad entry in manifest type "
@@ -250,7 +266,7 @@
     const std::string* external_version_str =
         extension.FindString(kExternalVersion);
     if (external_version_str) {
-      if (!ShouldUpdateForHigherVersion(cached_version_str,
+      if (!ShouldUpdateForHigherVersion(cached_crx_version,
                                         *external_version_str, false)) {
         LOG(WARNING) << "External app " << app_id
                      << " is at the same or lower version comparing to "
@@ -261,7 +277,7 @@
 
     ExternalUpdate update;
     KioskChromeAppManager::App app;
-    if (KioskChromeAppManager::Get()->GetApp(app_id, &app)) {
+    if (manager.GetApp(app_id, &app)) {
       update.app_name = app.name;
     } else {
       NOTREACHED();
@@ -278,7 +294,7 @@
     NotifyKioskUpdateProgress(
         ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
             IDS_KIOSK_EXTERNAL_UPDATE_NO_UPDATES));
-    KioskChromeAppManager::Get()->OnKioskAppExternalUpdateComplete(false);
+    manager.OnKioskAppExternalUpdateComplete(false);
     return;
   }
 
@@ -334,11 +350,13 @@
     const std::string& min_browser_version) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  std::string existing_version_str;
-  base::FilePath existing_path;
-  bool cached = KioskChromeAppManager::Get()->GetCachedCrx(
-      app_id, &existing_path, &existing_version_str);
-  DCHECK(cached);
+  auto& manager = CHECK_DEREF(KioskChromeAppManager::Get());
+  auto crx_info = manager.GetCachedCrx(app_id);
+  // TODO(crbug.com/383090254): Replace with CHECK.
+  DUMP_WILL_BE_CHECK(crx_info.has_value());
+  DCHECK(crx_info.has_value());
+  auto [_, existing_version_str] =
+      std::move(crx_info).value_or(KioskChromeAppManager::CachedCrxInfo());
 
   // Compare app version.
   ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
diff --git a/chrome/browser/ash/app_mode/test/BUILD.gn b/chrome/browser/ash/app_mode/test/BUILD.gn
index 24cd56ed..12ca3773 100644
--- a/chrome/browser/ash/app_mode/test/BUILD.gn
+++ b/chrome/browser/ash/app_mode/test/BUILD.gn
@@ -11,6 +11,7 @@
   defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
   sources = [
     "kiosk_browsertest.cc",
+    "kiosk_file_system_volumes_browsertest.cc",
     "kiosk_web_app_offline_enabled_browsertest.cc",
     "new_windows_in_kiosk_allowed_browsertest.cc",
     "splash_screen_browsertest.cc",
diff --git a/chrome/browser/ash/app_mode/test/kiosk_file_system_volumes_browsertest.cc b/chrome/browser/ash/app_mode/test/kiosk_file_system_volumes_browsertest.cc
new file mode 100644
index 0000000..111f08b
--- /dev/null
+++ b/chrome/browser/ash/app_mode/test/kiosk_file_system_volumes_browsertest.cc
@@ -0,0 +1,68 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <cstddef>
+#include <optional>
+#include <string_view>
+#include <vector>
+
+#include "base/check_deref.h"
+#include "base/strings/strcat.h"
+#include "chrome/browser/ash/app_mode/test/kiosk_mixin.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/test/base/mixin_based_in_process_browser_test.h"
+#include "content/public/test/browser_test.h"
+#include "extensions/test/result_catcher.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ash {
+
+namespace {
+
+// The "Get Volume List" Chrome app to be configured in `KioskMixin`.
+//
+// This app verifies the file system volumes available in Kiosk via the
+// chrome.fileSystem.getVolumeList API.
+//
+// The code is in:
+//   //chrome/test/data/chromeos/app_mode/apps_and_extensions/get_volume_list
+KioskMixin::CwsChromeAppOption VolumeListChromeApp() {
+  constexpr static std::string_view kAppId = "enelnimkndkcejhjnpaofdlbbfmdnagi";
+  return KioskMixin::CwsChromeAppOption{
+      /*account_id=*/"volume-list-chrome-app@localhost",
+      /*app_id=*/kAppId,
+      /*crx_filename=*/base::StrCat({kAppId, ".crx"}),
+      /*crx_version=*/"0.1"};
+}
+
+}  // namespace
+
+// Verifies the chrome.fileSystem.getVolumeList extension API works in Kiosk.
+class KioskFileSystemVolumesTest : public MixinBasedInProcessBrowserTest {
+ public:
+  KioskFileSystemVolumesTest() = default;
+  KioskFileSystemVolumesTest(const KioskFileSystemVolumesTest&) = delete;
+  KioskFileSystemVolumesTest& operator=(const KioskFileSystemVolumesTest&) =
+      delete;
+
+  ~KioskFileSystemVolumesTest() override = default;
+
+  KioskMixin kiosk_{
+      &mixin_host_,
+      /*cached_configuration=*/KioskMixin::Config{/*name=*/{},
+                                                  /*auto_launch_account_id=*/{},
+                                                  {VolumeListChromeApp()}}};
+};
+
+IN_PROC_BROWSER_TEST_F(KioskFileSystemVolumesTest, GetVolumeList) {
+  extensions::ResultCatcher catcher;
+  ASSERT_TRUE(kiosk_.LaunchManually(VolumeListChromeApp().account_id));
+  // Note this Chrome app has no UI. That means `kiosk_.WaitSessionLaunched()`
+  // would fail since Kiosk launch waits for the app window to appear. This test
+  // remains in splash screen.
+  ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
+}
+
+}  // namespace ash
diff --git a/chrome/browser/ash/bruschetta/bruschetta_util.cc b/chrome/browser/ash/bruschetta/bruschetta_util.cc
index e7e557e..f8bb6a6 100644
--- a/chrome/browser/ash/bruschetta/bruschetta_util.cc
+++ b/chrome/browser/ash/bruschetta/bruschetta_util.cc
@@ -50,20 +50,25 @@
 
 const char kBruschettaVmName[] = "bru";
 
-const char* BruschettaResultString(const BruschettaResult res) {
-#define ENTRY(name)            \
-  case BruschettaResult::name: \
-    return #name
+const std::string BruschettaResultString(const BruschettaResult res) {
   switch (res) {
-    ENTRY(kUnknown);
-    ENTRY(kSuccess);
-    ENTRY(kDlcInstallError);
-    ENTRY(kStartVmFailed);
-    ENTRY(kTimeout);
-    ENTRY(kForbiddenByPolicy);
-    ENTRY(kConciergeUnavailable);
+    case BruschettaResult::kUnknown:
+      return l10n_util::GetStringUTF8(IDS_BRUSCHETTA_RESULT_UNKNOWN);
+    case BruschettaResult::kSuccess:
+      return l10n_util::GetStringUTF8(IDS_BRUSCHETTA_RESULT_SUCCESS);
+    case BruschettaResult::kDlcInstallError:
+      return l10n_util::GetStringUTF8(IDS_BRUSCHETTA_RESULT_DLC_INSTALL_ERROR);
+    case BruschettaResult::kStartVmFailed:
+      return l10n_util::GetStringUTF8(IDS_BRUSCHETTA_RESULT_START_VM_FAILED);
+    case BruschettaResult::kTimeout:
+      return l10n_util::GetStringUTF8(IDS_BRUSCHETTA_RESULT_TIMEOUT);
+    case BruschettaResult::kForbiddenByPolicy:
+      return l10n_util::GetStringUTF8(
+          IDS_BRUSCHETTA_RESULT_FORBIDDEN_BY_POLICY);
+    case BruschettaResult::kConciergeUnavailable:
+      return l10n_util::GetStringUTF8(
+          IDS_BRUSCHETTA_RESULT_CONCIERGE_UNAVAILABLE);
   }
-#undef ENTRY
   return "unknown code";
 }
 
diff --git a/chrome/browser/ash/bruschetta/bruschetta_util.h b/chrome/browser/ash/bruschetta/bruschetta_util.h
index 52dbb9b6..1480dd4 100644
--- a/chrome/browser/ash/bruschetta/bruschetta_util.h
+++ b/chrome/browser/ash/bruschetta/bruschetta_util.h
@@ -45,7 +45,7 @@
 using InstallableConfig = std::pair<std::string, base::Value::Dict>;
 
 // Returns the string name of the BruschettaResult.
-const char* BruschettaResultString(const BruschettaResult res);
+const std::string BruschettaResultString(const BruschettaResult res);
 
 guest_os::GuestId GetBruschettaAlphaId();
 
diff --git a/chrome/browser/ash/dbus/org.chromium.ChromeFeaturesService.conf b/chrome/browser/ash/dbus/org.chromium.ChromeFeaturesService.conf
index eee7301..4859637 100644
--- a/chrome/browser/ash/dbus/org.chromium.ChromeFeaturesService.conf
+++ b/chrome/browser/ash/dbus/org.chromium.ChromeFeaturesService.conf
@@ -150,11 +150,4 @@
            send_member="IsFeatureEnabled"/>
   </policy>
 
-  <!-- limit biod visibility to only IsFeatureEnabled. -->
-  <policy user="biod">
-    <allow send_destination="org.chromium.ChromeFeaturesService"
-           send_interface="org.chromium.ChromeFeaturesServiceInterface"
-           send_member="IsFeatureEnabled"/>
-  </policy>
-
 </busconfig>
diff --git a/chrome/browser/ash/login/app_mode/test/auto_launched_kiosk_browsertest.cc b/chrome/browser/ash/login/app_mode/test/auto_launched_kiosk_browsertest.cc
index de81c7c..69ffe624 100644
--- a/chrome/browser/ash/login/app_mode/test/auto_launched_kiosk_browsertest.cc
+++ b/chrome/browser/ash/login/app_mode/test/auto_launched_kiosk_browsertest.cc
@@ -3,25 +3,23 @@
 // found in the LICENSE file.
 
 #include <memory>
-#include <optional>
 #include <string>
 #include <string_view>
+#include <utility>
 #include <vector>
 
 #include "apps/test/app_window_waiter.h"
+#include "base/auto_reset.h"
 #include "base/callback_list.h"
 #include "base/command_line.h"
-#include "base/files/file_path.h"
+#include "base/functional/callback_helpers.h"
 #include "base/run_loop.h"
-#include "base/strings/strcat.h"
 #include "base/test/gtest_tags.h"
-#include "base/values.h"
 #include "chrome/browser/ash/app_mode/app_launch_utils.h"
 #include "chrome/browser/ash/app_mode/fake_cws.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_launch_error.h"
 #include "chrome/browser/ash/app_mode/kiosk_chrome_app_manager.h"
 #include "chrome/browser/ash/app_mode/kiosk_test_helper.h"
-#include "chrome/browser/ash/app_mode/test/kiosk_session_initialized_waiter.h"
 #include "chrome/browser/ash/login/app_mode/test/kiosk_apps_mixin.h"
 #include "chrome/browser/ash/login/app_mode/test/kiosk_base_test.h"
 #include "chrome/browser/ash/login/test/device_state_mixin.h"
@@ -35,12 +33,11 @@
 #include "chrome/browser/lifetime/termination_notification.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/webui/ash/login/reset_screen_handler.h"
-#include "chrome/common/chrome_constants.h"
 #include "chrome/common/pref_names.h"
-#include "chromeos/ash/components/dbus/dbus_thread_manager.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/mixin_based_in_process_browser_test.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
-#include "chromeos/ash/components/dbus/shill/shill_manager_client.h"
-#include "chromeos/ash/components/install_attributes/stub_install_attributes.h"
+#include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
 #include "components/crx_file/crx_verifier.h"
 #include "components/policy/core/common/device_local_account_type.h"
 #include "content/public/test/browser_test.h"
@@ -52,17 +49,12 @@
 #include "extensions/test/extension_test_message_listener.h"
 #include "extensions/test/result_catcher.h"
 #include "net/dns/mock_host_resolver.h"
-#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
 
-using testing::UnorderedElementsAre;
-
 namespace {
 
-namespace em = ::enterprise_management;
-
 // Primary kiosk app that runs tests for chrome.management API.
 // The tests are run on the kiosk app launch event.
 // It has a secondary test kiosk app, which is loaded alongside the app. The
@@ -87,47 +79,6 @@
 constexpr char kTestManagementApiSecondaryApp[] =
     "kajpgkhinciaiihghpdamekpjpldgpfi";
 
-AccountId GetAccountId(std::string_view account_id,
-                       policy::DeviceLocalAccountType type) {
-  return AccountId::FromUserEmail(
-      policy::GenerateDeviceLocalAccountUserId(account_id, type));
-}
-
-AccountId GetWebKioskAccountId(std::string_view account_id) {
-  return GetAccountId(account_id, policy::DeviceLocalAccountType::kWebKioskApp);
-}
-
-AccountId GetChromeAppAccountId(std::string_view account_id) {
-  return GetAccountId(account_id, policy::DeviceLocalAccountType::kKioskApp);
-}
-
-std::vector<std::string> DeviceLocalAccountIdsFromPolicy(
-    DeviceStateMixin& device_state) {
-  auto scoped_policy_update = device_state.RequestDevicePolicyUpdate();
-  auto* policy = scoped_policy_update->policy_payload();
-
-  std::vector<std::string> account_ids;
-  for (int i = 0; i < policy->device_local_accounts().account_size(); i++) {
-    auto& account = policy->device_local_accounts().account(i);
-    if (!account.has_account_id()) {
-      continue;
-    }
-    account_ids.push_back(account.account_id());
-  }
-
-  return account_ids;
-}
-
-std::optional<std::string> AutoLoginAccountIdFromPolicy(
-    DeviceStateMixin& device_state) {
-  auto scoped_policy_update = device_state.RequestDevicePolicyUpdate();
-  auto* policy = scoped_policy_update->policy_payload();
-  if (policy->device_local_accounts().has_auto_login_id()) {
-    return policy->device_local_accounts().auto_login_id();
-  }
-  return std::nullopt;
-}
-
 }  // namespace
 
 class AutoLaunchedKioskTest : public OobeBaseTest {
@@ -431,124 +382,4 @@
   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
 }
 
-// Used to test lacros migration of a web-app. The migration will force logout
-// the kiosk session after the migration, at which point the app must be auto
-// launched once (even if it wasn't an auto-launch app to start with).
-class AutoLaunchWebAppAfterMigration : public AutoLaunchedKioskTest,
-                                       public LocalStateMixin::Delegate {
- public:
-  static constexpr char kMigratedWebAppAccountId[] =
-      "account-id-of-migrated-web@app";
-
-  AutoLaunchWebAppAfterMigration() = default;
-  ~AutoLaunchWebAppAfterMigration() override = default;
-
-  void SetUpInProcessBrowserTestFixture() override {
-    AutoLaunchedKioskTest::SetUpInProcessBrowserTestFixture();
-
-    // Create web app
-    std::unique_ptr<ScopedDevicePolicyUpdate> scoped_policy_update =
-        device_state_.RequestDevicePolicyUpdate();
-    KioskAppsMixin::AppendWebKioskAccount(
-        scoped_policy_update->policy_payload(), "http://web.app",
-        kMigratedWebAppAccountId);
-  }
-
-  void SetUpLocalState() override {
-    // Pretend there was a lacros migration of our web app.
-    SetOneTimeAutoLaunchKioskAppId(
-        *g_browser_process->local_state(),
-        KioskAppId::ForWebApp(GetWebKioskAccountId(kMigratedWebAppAccountId)));
-  }
-
- private:
-  LocalStateMixin local_state_mixin_{&mixin_host_, this};
-};
-
-IN_PROC_BROWSER_TEST_F(AutoLaunchWebAppAfterMigration,
-                       ShouldLaunchMigratedWebApp) {
-  KioskSessionInitializedWaiter().Wait();
-
-  // Check the correct app is launched.
-  const auto* active_user = user_manager::UserManager::Get()->GetActiveUser();
-  ASSERT_NE(active_user, nullptr);
-  EXPECT_EQ(active_user->GetAccountId(),
-            GetWebKioskAccountId(kMigratedWebAppAccountId));
-}
-
-// Used to test lacros migration of a chrome-app. The migration will force
-// logout the kiosk session after the migration, at which point the app must be
-// auto launched once (even if it wasn't an auto-launch app to start with).
-class AutoLaunchChromeAppAfterMigration : public AutoLaunchedKioskTest,
-                                          public LocalStateMixin::Delegate {
- public:
-  // This ID refers to the `offline_enabled_kiosk_app` implemented under
-  // chrome/test/data/chromeos/app_mode/apps_and_extensions/.
-  //
-  // When configured in `fake_cws_`, the corresponding CRX gets downloaded from
-  // chrome/test/data/chromeos/app_mode/webstore/downloads/.
-  static constexpr std::string_view kMigratedChromeAppId =
-      "iiigpodgfihagabpagjehoocpakbnclp";
-  static constexpr std::string_view kMigratedChromeAppAccountId =
-      "kiosk-app@localhost";
-
-  AutoLaunchChromeAppAfterMigration() = default;
-  ~AutoLaunchChromeAppAfterMigration() override = default;
-
-  void SetUpInProcessBrowserTestFixture() override {
-    // The base class sets up `GetTestAppId()` in policies to auto launch.
-    // Additionally, this configures the `kMigratedChromeAppId` Kiosk app.
-    {
-      std::unique_ptr<ScopedDevicePolicyUpdate> scoped_policy_update =
-          device_state_.RequestDevicePolicyUpdate();
-
-      KioskAppsMixin::AppendKioskAccount(scoped_policy_update->policy_payload(),
-                                         kMigratedChromeAppId,
-                                         kMigratedChromeAppAccountId);
-      // Setup the app on CWS so Kiosk can download and launch it.
-      fake_cws_.SetUpdateCrx(std::string(kMigratedChromeAppId),
-                             base::StrCat({kMigratedChromeAppId, "_v1.crx"}),
-                             "1.0.0");
-
-      scoped_policy_update.reset();
-    }
-
-    AutoLaunchedKioskTest::SetUpInProcessBrowserTestFixture();
-  }
-
-  void SetUpLocalState() override {
-    // Pretend there was a lacros migration of our Chrome app.
-    SetOneTimeAutoLaunchKioskAppId(
-        *g_browser_process->local_state(),
-        KioskAppId::ForChromeApp(
-            kMigratedChromeAppId,
-            GetChromeAppAccountId(kMigratedChromeAppAccountId)));
-  }
-
- private:
-  LocalStateMixin local_state_mixin_{&mixin_host_, this};
-};
-
-IN_PROC_BROWSER_TEST_F(AutoLaunchChromeAppAfterMigration,
-                       ShouldLaunchMigratedChromeApp) {
-  // Verify the pre-conditions:
-  // * There are two Chrome apps configured in policies.
-  // * One of them is the migrated app.
-  // * The non-migrated app is configured for auto launch.
-  ASSERT_NE(kMigratedChromeAppId, GetTestAppId());
-  ASSERT_NE(kMigratedChromeAppAccountId, GetTestAppAccountId());
-  ASSERT_THAT(
-      DeviceLocalAccountIdsFromPolicy(device_state_),
-      UnorderedElementsAre(GetTestAppAccountId(), kMigratedChromeAppAccountId));
-  ASSERT_EQ(AutoLoginAccountIdFromPolicy(device_state_), GetTestAppAccountId());
-
-  KioskSessionInitializedWaiter().Wait();
-
-  // Check the migrated app launched instead of the auto launch app.
-  const auto* active_user = user_manager::UserManager::Get()->GetActiveUser();
-  ASSERT_NE(active_user, nullptr);
-  EXPECT_EQ(active_user->GetAccountId(),
-            GetChromeAppAccountId(kMigratedChromeAppAccountId));
-}
-
 }  // namespace ash
diff --git a/chrome/browser/ash/login/app_mode/test/kiosk_device_owned_browsertest.cc b/chrome/browser/ash/login/app_mode/test/kiosk_device_owned_browsertest.cc
index 408f42b..9eb0294 100644
--- a/chrome/browser/ash/login/app_mode/test/kiosk_device_owned_browsertest.cc
+++ b/chrome/browser/ash/login/app_mode/test/kiosk_device_owned_browsertest.cc
@@ -69,13 +69,6 @@
 const test::UIPath kSplashScreenLaunchText = {"app-launch-splash",
                                               "launchText"};
 
-// An app to test local access to file systems via the
-// chrome.fileSystem.requestFileSystem API.
-// Webstore data json is in
-//     chrome/test/data/chromeos/app_mode/webstore/inlineinstall/
-//         detail/enelnimkndkcejhjnpaofdlbbfmdnagi
-const char kTestGetVolumeListKioskAppId[] = "enelnimkndkcejhjnpaofdlbbfmdnagi";
-
 constexpr char kSettingsPage1[] = "chrome://os-settings/manageAccessibility";
 constexpr char kSettingsPage2[] =
     "chrome-extension://mndnfokpggljbaajbnioimlmbfngpief/chromevox/options/"
@@ -241,15 +234,6 @@
   WaitForAppLaunchSuccess();
 }
 
-// Verifies available volumes for kiosk apps in kiosk session.
-IN_PROC_BROWSER_TEST_F(KioskDeviceOwnedTest, GetVolumeList) {
-  SetTestApp(kTestGetVolumeListKioskAppId, /*version=*/"0.1");
-
-  extensions::ResultCatcher catcher;
-  StartAppLaunchFromLoginScreen(NetworkStatus::kOnline);
-  ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
-}
-
 IN_PROC_BROWSER_TEST_F(KioskDeviceOwnedTest, SettingsWindow) {
   StartAppLaunchFromLoginScreen(NetworkStatus::kOnline);
   WaitForAppLaunchWithOptions(/*check_launch_data=*/true,
diff --git a/chrome/browser/ash/login/app_mode/test/kiosk_update_browsertest.cc b/chrome/browser/ash/login/app_mode/test/kiosk_update_browsertest.cc
index 405d4c067..78c1f71 100644
--- a/chrome/browser/ash/login/app_mode/test/kiosk_update_browsertest.cc
+++ b/chrome/browser/ash/login/app_mode/test/kiosk_update_browsertest.cc
@@ -2,17 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <memory>
 #include <string>
 #include <vector>
 
+#include "base/check.h"
 #include "base/files/file_path.h"
 #include "base/functional/callback_helpers.h"
+#include "base/json/json_writer.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/test/gtest_tags.h"
 #include "base/test/scoped_chromeos_version_info.h"
+#include "chrome/browser/ash/app_mode/kiosk_app_manager_observer.h"
 #include "chrome/browser/ash/app_mode/kiosk_chrome_app_manager.h"
 #include "chrome/browser/ash/app_mode/test_kiosk_extension_builder.h"
 #include "chrome/browser/ash/login/app_mode/test/kiosk_base_test.h"
@@ -30,8 +34,8 @@
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/manifest.h"
-#include "extensions/common/mojom/manifest.mojom-shared.h"
 #include "extensions/test/result_catcher.h"
+#include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
 
@@ -229,9 +233,10 @@
       waiter.Wait();
     }
     EXPECT_TRUE(waiter.loaded());
-    std::string cached_version;
-    base::FilePath file_path;
-    EXPECT_TRUE(manager->GetCachedCrx(app_id, &file_path, &cached_version));
+
+    auto crx_info = manager->GetCachedCrx(app_id);
+    ASSERT_TRUE(crx_info.has_value());
+    auto& [_, cached_version] = crx_info.value();
     EXPECT_EQ(version, cached_version);
   }
 
@@ -245,10 +250,10 @@
     KioskChromeAppManager::Get()->UpdateExternalCache();
     waiter.Wait();
     EXPECT_TRUE(waiter.loaded());
-    std::string cached_version;
-    base::FilePath file_path;
-    EXPECT_TRUE(
-        manager->GetCachedCrx(test_app_id(), &file_path, &cached_version));
+
+    auto crx_info = manager->GetCachedCrx(test_app_id());
+    ASSERT_TRUE(crx_info.has_value());
+    auto& [_, cached_version] = crx_info.value();
     EXPECT_EQ(version, cached_version);
   }
 
@@ -589,10 +594,10 @@
 
   // The v2 kiosk app is loaded into external cache, but won't be installed
   // until next time the device is started.
-  base::FilePath crx_path;
-  std::string cached_version;
-  EXPECT_TRUE(KioskChromeAppManager::Get()->GetCachedCrx(
-      test_app_id(), &crx_path, &cached_version));
+  auto crx_info = KioskChromeAppManager::Get()->GetCachedCrx(test_app_id());
+  ASSERT_TRUE(crx_info.has_value());
+  auto& [_, cached_version] = crx_info.value();
+
   EXPECT_EQ("2.0.0", cached_version);
   EXPECT_EQ("1.0.0", GetInstalledAppVersion().GetString());
 }
@@ -622,10 +627,9 @@
   EXPECT_FALSE(update_success);
 
   // Kiosk app is not updated.
-  base::FilePath crx_path;
-  std::string cached_version;
-  EXPECT_TRUE(KioskChromeAppManager::Get()->GetCachedCrx(
-      test_app_id(), &crx_path, &cached_version));
+  auto crx_info = KioskChromeAppManager::Get()->GetCachedCrx(test_app_id());
+  ASSERT_TRUE(crx_info.has_value());
+  auto& [_, cached_version] = crx_info.value();
   EXPECT_EQ("1.0.0", cached_version);
 }
 
@@ -643,10 +647,9 @@
   EXPECT_FALSE(update_success);
 
   // Kiosk app is not updated.
-  base::FilePath crx_path;
-  std::string cached_version;
-  EXPECT_TRUE(KioskChromeAppManager::Get()->GetCachedCrx(
-      test_app_id(), &crx_path, &cached_version));
+  auto crx_info = KioskChromeAppManager::Get()->GetCachedCrx(test_app_id());
+  ASSERT_TRUE(crx_info.has_value());
+  auto& [_, cached_version] = crx_info.value();
   EXPECT_EQ("1.0.0", cached_version);
 }
 
@@ -666,10 +669,9 @@
   EXPECT_FALSE(update_success);
 
   // Kiosk app is NOT updated to the lower version.
-  base::FilePath crx_path;
-  std::string cached_version;
-  EXPECT_TRUE(KioskChromeAppManager::Get()->GetCachedCrx(
-      test_app_id(), &crx_path, &cached_version));
+  auto crx_info = KioskChromeAppManager::Get()->GetCachedCrx(test_app_id());
+  ASSERT_TRUE(crx_info.has_value());
+  auto& [_, cached_version] = crx_info.value();
   EXPECT_EQ("2.0.0", cached_version);
 }
 
@@ -689,10 +691,9 @@
   EXPECT_FALSE(update_success);
 
   // Kiosk app is NOT updated to the lower version.
-  base::FilePath crx_path;
-  std::string cached_version;
-  EXPECT_TRUE(KioskChromeAppManager::Get()->GetCachedCrx(
-      test_app_id(), &crx_path, &cached_version));
+  auto crx_info = KioskChromeAppManager::Get()->GetCachedCrx(test_app_id());
+  ASSERT_TRUE(crx_info.has_value());
+  auto& [_, cached_version] = crx_info.value();
   EXPECT_EQ("2.0.0", cached_version);
 }
 
@@ -711,10 +712,9 @@
   EXPECT_FALSE(update_success);
 
   // Kiosk app is NOT updated.
-  base::FilePath crx_path;
-  std::string cached_version;
-  EXPECT_TRUE(KioskChromeAppManager::Get()->GetCachedCrx(
-      test_app_id(), &crx_path, &cached_version));
+  auto crx_info = KioskChromeAppManager::Get()->GetCachedCrx(test_app_id());
+  ASSERT_TRUE(crx_info.has_value());
+  auto& [_, cached_version] = crx_info.value();
   EXPECT_EQ("1.0.0", cached_version);
 }
 
diff --git a/chrome/browser/ash/login/app_mode/test/test_app_data_load_waiter.cc b/chrome/browser/ash/login/app_mode/test/test_app_data_load_waiter.cc
index 3cacef4a..983e11fe 100644
--- a/chrome/browser/ash/login/app_mode/test/test_app_data_load_waiter.cc
+++ b/chrome/browser/ash/login/app_mode/test/test_app_data_load_waiter.cc
@@ -2,13 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/browser/ash/login/app_mode/test/test_app_data_load_waiter.h"
+
 #include <memory>
 #include <string>
 
 #include "base/files/file_path.h"
 #include "base/run_loop.h"
 #include "chrome/browser/ash/app_mode/kiosk_chrome_app_manager.h"
-#include "chrome/browser/ash/login/app_mode/test/test_app_data_load_waiter.h"
 
 namespace ash {
 
@@ -79,14 +80,16 @@
     return;
   }
 
-  std::string cached_version;
-  base::FilePath file_path;
-  if (!manager_->GetCachedCrx(app_id_, &file_path, &cached_version)) {
+  auto info = manager_->GetCachedCrx(app_id_);
+  if (!info.has_value()) {
     return;
   }
+
+  auto& [_, cached_version] = info.value();
   if (version_ != cached_version) {
     return;
   }
+
   loaded_ = true;
   quit_ = true;
   if (runner_.get()) {
diff --git a/chrome/browser/ash/login/chrome_restart_request.cc b/chrome/browser/ash/login/chrome_restart_request.cc
index fe7e594..d6c1b65 100644
--- a/chrome/browser/ash/login/chrome_restart_request.cc
+++ b/chrome/browser/ash/login/chrome_restart_request.cc
@@ -223,8 +223,6 @@
       switches::kForceTabletPowerButton,
       switches::kFormFactor,
       switches::kHasChromeOSKeyboard,
-      switches::kLacrosChromeAdditionalArgs,
-      switches::kLacrosChromeAdditionalEnv,
       switches::kLacrosChromePath,
       ash::standalone_browser::kLacrosStabilitySwitch,
       switches::kLoginProfile,
diff --git a/chrome/browser/ash/note_taking/note_taking_helper_unittest.cc b/chrome/browser/ash/note_taking/note_taking_helper_unittest.cc
index 763b6026..94887a74 100644
--- a/chrome/browser/ash/note_taking/note_taking_helper_unittest.cc
+++ b/chrome/browser/ash/note_taking/note_taking_helper_unittest.cc
@@ -882,8 +882,6 @@
   EXPECT_TRUE(helper()->play_store_enabled());
   EXPECT_TRUE(helper()->android_apps_received());
   EXPECT_EQ(2, observer.num_updates());
-
-  profile_manager()->DeleteTestingProfile(kSecondProfileName);
 }
 
 TEST_F(NoteTakingHelperTest, ListAndroidApps) {
@@ -1105,7 +1103,6 @@
   EXPECT_EQ(1, observer.num_updates());
   UninstallExtension(second_keep_extension.get(), second_profile);
   EXPECT_EQ(2, observer.num_updates());
-  profile_manager()->DeleteTestingProfile(kSecondProfileName);
 }
 
 TEST_F(NoteTakingHelperTest, NotifyObserverAboutPreferredAppChanges) {
@@ -1169,8 +1166,6 @@
   EXPECT_EQ(std::vector<raw_ptr<Profile>>{second_profile},
             observer.preferred_app_updates());
   observer.clear_preferred_app_updates();
-
-  profile_manager()->DeleteTestingProfile(kSecondProfileName);
 }
 
 TEST_F(NoteTakingHelperTest, NoteTakingControllerClient) {
@@ -1231,8 +1226,6 @@
 
     UninstallExtension(extension2.get(), second_profile);
     EXPECT_TRUE(has_note_taking_apps());
-
-    profile_manager()->DeleteTestingProfile(kSecondProfileName);
   }
 }
 
diff --git a/chrome/browser/ash/system_web_apps/apps/sanitize_system_web_app_info.cc b/chrome/browser/ash/system_web_apps/apps/sanitize_system_web_app_info.cc
index 154a269e..80b613aa 100644
--- a/chrome/browser/ash/system_web_apps/apps/sanitize_system_web_app_info.cc
+++ b/chrome/browser/ash/system_web_apps/apps/sanitize_system_web_app_info.cc
@@ -60,6 +60,10 @@
   return false;
 }
 
+bool SanitizeSystemAppDelegate::ShouldAllowMaximize() const {
+  return false;
+}
+
 bool SanitizeSystemAppDelegate::ShouldShowInLauncher() const {
   return false;
 }
diff --git a/chrome/browser/ash/system_web_apps/apps/sanitize_system_web_app_info.h b/chrome/browser/ash/system_web_apps/apps/sanitize_system_web_app_info.h
index 40aa355..97c9c1d 100644
--- a/chrome/browser/ash/system_web_apps/apps/sanitize_system_web_app_info.h
+++ b/chrome/browser/ash/system_web_apps/apps/sanitize_system_web_app_info.h
@@ -22,6 +22,7 @@
   std::unique_ptr<web_app::WebAppInstallInfo> GetWebAppInfo() const override;
   bool ShouldCaptureNavigations() const override;
   bool ShouldAllowResize() const override;
+  bool ShouldAllowMaximize() const override;
   bool ShouldShowInLauncher() const override;
   bool ShouldAllowScriptsToCloseWindows() const override;
   gfx::Rect GetDefaultBounds(Browser* browser) const override;
diff --git a/chrome/browser/autofill/address_normalizer_factory.h b/chrome/browser/autofill/address_normalizer_factory.h
index 523e8e9..4d50587 100644
--- a/chrome/browser/autofill/address_normalizer_factory.h
+++ b/chrome/browser/autofill/address_normalizer_factory.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_AUTOFILL_ADDRESS_NORMALIZER_FACTORY_H_
 
 #include "base/lazy_instance.h"
-#include "components/autofill/core/browser/address_normalizer_impl.h"
+#include "components/autofill/core/browser/data_quality/addresses/address_normalizer_impl.h"
 
 namespace autofill {
 
diff --git a/chrome/browser/autofill/android/personal_data_manager_android.cc b/chrome/browser/autofill/android/personal_data_manager_android.cc
index 9531d09..2012c0169 100644
--- a/chrome/browser/autofill/android/personal_data_manager_android.cc
+++ b/chrome/browser/autofill/android/personal_data_manager_android.cc
@@ -25,13 +25,14 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "components/autofill/core/browser/address_data_manager.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_experiments.h"
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/bank_account.h"
 #include "components/autofill/core/browser/data_model/ewallet.h"
 #include "components/autofill/core/browser/data_model/payment_instrument.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/geo/address_i18n.h"
 #include "components/autofill/core/browser/geo/autofill_country.h"
@@ -39,7 +40,6 @@
 #include "components/autofill/core/browser/payments_data_manager.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/ui/autofill_resource_utils.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/autofill/core/common/autofill_payments_features.h"
diff --git a/chrome/browser/autofill/autofill_browsertest.cc b/chrome/browser/autofill/autofill_browsertest.cc
index 9f597fe7..9e63697 100644
--- a/chrome/browser/autofill/autofill_browsertest.cc
+++ b/chrome/browser/autofill/autofill_browsertest.cc
@@ -42,11 +42,11 @@
 #include "components/autofill/core/browser/browser_autofill_manager.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/personal_data_manager_observer.h"
 #include "components/autofill/core/browser/personal_data_manager_test_utils.h"
 #include "components/autofill/core/browser/test_autofill_manager_waiter.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h"
 #include "components/keyed_service/core/service_access_type.h"
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc
index b76749a4..7958207e 100644
--- a/chrome/browser/autofill/autofill_interactive_uitest.cc
+++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -60,9 +60,9 @@
 #include "components/autofill/core/browser/browser_autofill_manager_test_delegate.h"
 #include "components/autofill/core/browser/crowdsourcing/votes_uploader_test_api.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/mock_autofill_manager_observer.h"
 #include "components/autofill/core/browser/test_autofill_manager_waiter.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_util.h"
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc
index 3413230..9569917 100644
--- a/chrome/browser/chrome_browser_interface_binders.cc
+++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/buildflags.h"
 #include "chrome/browser/dom_distiller/dom_distiller_service_factory.h"
 #include "chrome/browser/history_clusters/history_clusters_service_factory.h"
+#include "chrome/browser/history_embeddings/history_embeddings_utils.h"
 #include "chrome/browser/media/media_engagement_score_details.mojom.h"
 #include "chrome/browser/navigation_predictor/navigation_predictor.h"
 #include "chrome/browser/optimization_guide/optimization_guide_internals_ui.h"
@@ -70,7 +71,6 @@
 #include "components/history_clusters/core/features.h"
 #include "components/history_clusters/core/history_clusters_service.h"
 #include "components/history_clusters/history_clusters_internals/webui/history_clusters_internals_ui.h"
-#include "components/history_embeddings/history_embeddings_features.h"
 #include "components/language_detection/content/common/language_detection.mojom.h"
 #include "components/lens/lens_features.h"
 #include "components/live_caption/caption_util.h"
@@ -1055,7 +1055,7 @@
                                            HistoryUI,
                                            HistoryClustersSidePanelUI>(map);
   }
-  if (history_embeddings::IsHistoryEmbeddingsEnabled()) {
+  if (history_embeddings::IsHistoryEmbeddingsFeatureEnabled()) {
     if (history_clusters_service &&
         history_clusters_service->is_journeys_feature_flag_enabled()) {
       RegisterWebUIControllerInterfaceBinder<
diff --git a/chrome/browser/component_updater/registration.cc b/chrome/browser/component_updater/registration.cc
index aada9ca8..a05936c6 100644
--- a/chrome/browser/component_updater/registration.cc
+++ b/chrome/browser/component_updater/registration.cc
@@ -38,6 +38,7 @@
 #include "chrome/browser/component_updater/subresource_filter_component_installer.h"
 #include "chrome/browser/component_updater/tpcd_metadata_component_installer.h"
 #include "chrome/browser/component_updater/trust_token_key_commitments_component_installer.h"
+#include "chrome/browser/history_embeddings/history_embeddings_utils.h"
 #include "chrome/common/buildflags.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_paths.h"
@@ -48,7 +49,6 @@
 #include "components/component_updater/installer_policies/optimization_hints_component_installer.h"
 #include "components/component_updater/installer_policies/plus_address_blocklist_component_installer.h"
 #include "components/component_updater/installer_policies/safety_tips_component_installer.h"
-#include "components/history_embeddings/history_embeddings_features.h"
 #include "components/nacl/common/buildflags.h"
 #include "components/safe_browsing/core/common/features.h"
 #include "components/services/on_device_translation/buildflags/buildflags.h"
@@ -154,7 +154,7 @@
   RegisterMaskedDomainListComponent(cus);
   RegisterPrivacySandboxAttestationsComponent(cus);
   RegisterAntiFingerprintingBlockedDomainListComponent(cus);
-  if (history_embeddings::IsHistoryEmbeddingsEnabled()) {
+  if (history_embeddings::IsHistoryEmbeddingsFeatureEnabled()) {
     RegisterHistorySearchStringsComponent(cus);
   }
 
@@ -163,7 +163,7 @@
     // Clean up any remaining desktop sharing hub state.
     component_updater::DeleteDesktopSharingHub(path);
 
-    if (!history_embeddings::IsHistoryEmbeddingsEnabled()) {
+    if (!history_embeddings::IsHistoryEmbeddingsFeatureEnabled()) {
       DeleteHistorySearchStringsComponent(path);
     }
 
diff --git a/chrome/browser/content_extraction/inner_html.h b/chrome/browser/content_extraction/inner_html.h
index 83997d5..726502b 100644
--- a/chrome/browser/content_extraction/inner_html.h
+++ b/chrome/browser/content_extraction/inner_html.h
@@ -27,6 +27,11 @@
 //
 // NOTE: This function services the request as soon as called, it does not wait
 // for the page to finish loading.
+//
+// IMPORTANT: The inner-html retrieved by this function is untrustworthy and
+// should not be processed in the browser process.
+// TODO(crbug.com/370820145): These fields should be annotated as untrustworthy
+// when possible.
 void GetInnerHtml(content::RenderFrameHost& host, InnerHtmlCallback callback);
 
 }  // namespace content_extraction
diff --git a/chrome/browser/content_extraction/inner_text.h b/chrome/browser/content_extraction/inner_text.h
index b7c2c6e9..1a50553 100644
--- a/chrome/browser/content_extraction/inner_text.h
+++ b/chrome/browser/content_extraction/inner_text.h
@@ -50,6 +50,11 @@
 //
 // NOTE: This function services the request as soon as called, it does not wait
 // for the page to finish loading.
+//
+// IMPORTANT: The inner-text retrieved by this function is untrustworthy and
+// should not be processed in the browser process.
+// TODO(crbug.com/370820145): These fields should be annotated as untrustworthy
+// when possible.
 void GetInnerText(content::RenderFrameHost& host,
                   std::optional<int> node_id,
                   InnerTextCallback callback);
diff --git a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
index 928bca7f..87799a38 100644
--- a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
+++ b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
@@ -77,6 +77,12 @@
 #include "base/mac/mac_util.h"
 #endif
 
+#if !BUILDFLAG(IS_CHROMEOS)
+#include "base/base64.h"
+#include "base/feature_list.h"
+#include "components/variations/net/variations_command_line.h"
+#endif
+
 namespace system_logs {
 
 namespace {
@@ -406,6 +412,11 @@
   PopulateSyncLogs(response.get());
   PopulateExtensionInfoLogs(response.get());
   PopulatePowerApiLogs(response.get());
+#if !BUILDFLAG(IS_CHROMEOS)
+  if (base::FeatureList::IsEnabled(variations::kFeedbackIncludeVariations)) {
+    PopulateVariations(response.get());
+  }
+#endif
 #if BUILDFLAG(IS_WIN)
   PopulateUsbKeyboardDetected(response.get());
   PopulateEnrolledToDomain(response.get());
@@ -539,6 +550,20 @@
     response->emplace(kPowerApiListKey, info);
 }
 
+#if !BUILDFLAG(IS_CHROMEOS)
+void ChromeInternalLogSource::PopulateVariations(SystemLogsResponse* response) {
+  std::vector<uint8_t> ciphertext;
+  auto status =
+      variations::VariationsCommandLine::GetForCurrentProcess().EncryptToString(
+          &ciphertext);
+  if (status == variations::VariationsStateEncryptionStatus::kSuccess) {
+    std::string base64_encoded =
+        base::Base64Encode(std::string(ciphertext.begin(), ciphertext.end()));
+    response->emplace("variations", base64_encoded);
+  }
+}
+#endif
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 void ChromeInternalLogSource::PopulateLocalStateSettings(
     SystemLogsResponse* response) {
diff --git a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h
index 7d034f46..fa2cff7d 100644
--- a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h
+++ b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h
@@ -34,6 +34,9 @@
   void PopulateExtensionInfoLogs(SystemLogsResponse* response);
   void PopulatePowerApiLogs(SystemLogsResponse* response);
   void PopulateDataReductionProxyLogs(SystemLogsResponse* response);
+#if !BUILDFLAG(IS_CHROMEOS)
+  void PopulateVariations(SystemLogsResponse* response);
+#endif
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   void PopulateLocalStateSettings(SystemLogsResponse* response);
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 5a9a5a5c..97666d8 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -123,11 +123,6 @@
     "expiry_milestone": 128
   },
   {
-    "name": "allow-fpmcu-beta-firmware",
-    "owners": [ "patrykd@google.com", "chromeos-fingerprint@google.com" ],
-    "expiry_milestone": 131
-  },
-  {
     "name": "allow-insecure-localhost",
     "owners": [ "cthomp@chromium.org", "security-dev@chromium.org" ],
     "expiry_milestone": 130
@@ -3925,11 +3920,6 @@
     "expiry_milestone": 140
   },
   {
-    "name": "enable-tablet-toolbar-reordering",
-    "owners": [ "zheliooo@google.com", "twellington@google.com", "nemco@google.com", "clank-app-team@google.com" ],
-    "expiry_milestone": 125
-  },
-  {
     "name": "enable-tabstate-flatbuffer",
     "owners": [ "chrome-shopping@google.com" ],
     "expiry_milestone": 131
@@ -4561,6 +4551,11 @@
     "expiry_milestone": 115
   },
   {
+    "name": "feedback-include-variations",
+    "owners": [ "svenzheng@google.com", "chrome-metrics-team@google.com" ],
+    "expiry_milestone": 145
+  },
+  {
     "name": "fetch-gaia-hash-on-sign-in",
     "owners":["nwokedi@chromium.org"],
     "expiry_milestone": 130
@@ -8111,7 +8106,7 @@
   {
     "name": "skia-graphite",
     "owners": [ "sunnyps@chromium.org", "blundell@chromium.org", "chrome-skia-graphite@google.com" ],
-    "expiry_milestone": 135
+    "expiry_milestone": 140
   },
   {
     "name": "skia-graphite-precompilation",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 2d438fa..53f20d43 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3500,6 +3500,12 @@
     "Visualize overdraw by color-coding elements based on if they have other "
     "elements drawn underneath.";
 
+#if !BUILDFLAG(IS_CHROMEOS)
+const char kFeedbackIncludeVariationsName[] = "Feedback include variations";
+const char kFeedbackIncludeVariationsDescription[] =
+    "In Chrome feedback report, include commandline variations.";
+#endif
+
 const char kSidePanelResizingFlagId[] = "side-panel-resizing";
 const char kSidePanelResizingName[] = "Side Panel Resizing";
 const char kSidePanelResizingDescription[] =
@@ -4833,13 +4839,6 @@
     "When enabled, the network interface with Google Payments supports "
     "handling multiple concurrent requests for Pix flows.";
 
-const char kTabletToolbarReorderingAndroidName[] =
-    "Tablet Toolbar Reordering Android.";
-const char kTabletToolbarReorderingAndroidDescription[] =
-    "Enable Tablet Toolbar Reordering on Android - Reorder the toolbar by "
-    "placing the Home button from 1st to the 4th position after the Refresh"
-    "button to match the Desktop toolbar";
-
 const char kCrossDeviceTabPaneAndroidName[] = "Cross Device Tab Pane Android";
 const char kCrossDeviceTabPaneAndroidDescription[] =
     "Enables showing a new pane in the hub that displays the pre-existing "
@@ -5754,11 +5753,6 @@
     "Improves debugging of Cross-Device features by recording more verbose "
     "logs and attaching these logs to filed Feedback reports.";
 
-const char kAllowFpmcuBetaFirmwareName[] =
-    "Allow using beta firmware for the FPMCU";
-const char kAllowFpmcuBetaFirmwareDescription[] =
-    "Allow using beta firmware for the Fingerprint MCU if available";
-
 const char kAllowScrollSettingsName[] =
     "Allow changes to scroll acceleration/sensitivity for mice.";
 const char kAllowScrollSettingsDescription[] =
@@ -6315,10 +6309,6 @@
     "Enables long term refactored handshake logic for Google Fast Pair "
     "service.";
 
-const char kFastPairHIDName[] = "Enable Fast Pair HID";
-const char kFastPairHIDDescription[] =
-    "Enables prototype support for Fast Pair HID (non-keyboard).";
-
 const char kFastPairKeyboardsName[] = "Enable Fast Pair Keyboards";
 const char kFastPairKeyboardsDescription[] =
     "Enables prototype support for Fast Pair for keyboards.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 8d33fdb..d74ed85 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -2006,6 +2006,11 @@
 extern const char kShowOverdrawFeedbackName[];
 extern const char kShowOverdrawFeedbackDescription[];
 
+#if !BUILDFLAG(IS_CHROMEOS)
+extern const char kFeedbackIncludeVariationsName[];
+extern const char kFeedbackIncludeVariationsDescription[];
+#endif
+
 extern const char kSidePanelResizingFlagId[];
 extern const char kSidePanelResizingName[];
 extern const char kSidePanelResizingDescription[];
@@ -2124,9 +2129,6 @@
 extern const char kTearOffWebAppAppTabOpensWebAppWindowName[];
 extern const char kTearOffWebAppAppTabOpensWebAppWindowDescription[];
 
-extern const char kTabletToolbarReorderingAndroidName[];
-extern const char kTabletToolbarReorderingAndroidDescription[];
-
 extern const char kTabResumptionModuleAndroidName[];
 extern const char kTabResumptionModuleAndroidDescription[];
 
@@ -3328,9 +3330,6 @@
 extern const char kLinkCrossDeviceInternalsName[];
 extern const char kLinkCrossDeviceInternalsDescription[];
 
-extern const char kAllowFpmcuBetaFirmwareName[];
-extern const char kAllowFpmcuBetaFirmwareDescription[];
-
 extern const char kAllowScrollSettingsName[];
 extern const char kAllowScrollSettingsDescription[];
 
@@ -3648,9 +3647,6 @@
 extern const char kFastPairHandshakeLongTermRefactorName[];
 extern const char kFastPairHandshakeLongTermRefactorDescription[];
 
-extern const char kFastPairHIDName[];
-extern const char kFastPairHIDDescription[];
-
 extern const char kFastPairKeyboardsName[];
 extern const char kFastPairKeyboardsDescription[];
 
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index 53f384ac..de629b9 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -323,7 +323,6 @@
     &kTabDragDropAndroid,
     &kToolbarPhoneCleanup,
     &kTabGroupCreationDialogAndroid,
-    &kTabletToolbarReordering,
     &kTabResumptionModuleAndroid,
     &kTabStateFlatBuffer,
     &kTabStripGroupCollapseAndroid,
@@ -998,10 +997,6 @@
              "TabGroupCreationDialogAndroid",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
-BASE_FEATURE(kTabletToolbarReordering,
-             "TabletToolbarReordering",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
 BASE_FEATURE(kTabStateFlatBuffer,
              "TabStateFlatBuffer",
              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 368659a6..904cfb3 100644
--- a/chrome/browser/flags/android/chrome_feature_list.h
+++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -171,7 +171,6 @@
 BASE_DECLARE_FEATURE(kTabDragDropAndroid);
 BASE_DECLARE_FEATURE(kToolbarPhoneCleanup);
 BASE_DECLARE_FEATURE(kTabGroupCreationDialogAndroid);
-BASE_DECLARE_FEATURE(kTabletToolbarReordering);
 BASE_DECLARE_FEATURE(kTabStateFlatBuffer);
 BASE_DECLARE_FEATURE(kTabStripGroupCollapseAndroid);
 BASE_DECLARE_FEATURE(kTabStripGroupContextMenuAndroid);
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 66aabf3..ad69e63 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
@@ -531,7 +531,6 @@
     public static final String TAB_STRIP_LAYOUT_OPTIMIZATION = "TabStripLayoutOptimization";
     public static final String TAB_STRIP_TRANSITION_IN_DESKTOP_WINDOW =
             "TabStripTransitionInDesktopWindow";
-    public static final String TABLET_TOOLBAR_REORDERING = "TabletToolbarReordering";
     public static final String TAB_STATE_FLAT_BUFFER = "TabStateFlatBuffer";
     public static final String TAB_WINDOW_MANAGER_INDEX_REASSIGNMENT_ACTIVITY_FINISHING =
             "TabWindowManagerIndexReassignmentActivityFinishing";
@@ -751,8 +750,6 @@
                     TAB_STRIP_LAYOUT_OPTIMIZATION,
                     /* defaultValue= */ false,
                     /* defaultValueInTests= */ true);
-    public static final CachedFlag sTabletToolbarReordering =
-            newCachedFlag(TABLET_TOOLBAR_REORDERING, false);
     public static final CachedFlag sTabStripGroupCollapse =
             newCachedFlag(TAB_STRIP_GROUP_COLLAPSE, false);
     public static final CachedFlag sTabWindowManagerIndexReassignmentActivityFinishing =
@@ -861,7 +858,6 @@
                     sTabStripGroupCollapse,
                     sTabStripIncognitoMigration,
                     sTabStripLayoutOptimization,
-                    sTabletToolbarReordering,
                     sTabWindowManagerIndexReassignmentActivityFinishing,
                     sTabWindowManagerIndexReassignmentActivityInSameTask,
                     sTabWindowManagerIndexReassignmentActivityNotInAppTasks,
diff --git a/chrome/browser/glic/BUILD.gn b/chrome/browser/glic/BUILD.gn
index e918845..f80f1208 100644
--- a/chrome/browser/glic/BUILD.gn
+++ b/chrome/browser/glic/BUILD.gn
@@ -8,9 +8,8 @@
     "glic_keyed_service.h",
     "glic_keyed_service_factory.h",
     "glic_page_context_fetcher.h",
-    "glic_profile.h",
+    "glic_profile_manager.h",
     "glic_window_controller.h",
-    "glic_window_manager.h",
     "guest_util.h",
   ]
   public_deps = [
@@ -31,9 +30,8 @@
     "glic_keyed_service.cc",
     "glic_keyed_service_factory.cc",
     "glic_page_context_fetcher.cc",
-    "glic_profile.cc",
+    "glic_profile_manager.cc",
     "glic_window_controller.cc",
-    "glic_window_manager.cc",
     "guest_util.cc",
   ]
   public_deps = [
@@ -42,6 +40,8 @@
   ]
   deps = [
     ":glic",
+    "//chrome/browser:browser_process",
+    "//chrome/browser:global_features",
     "//chrome/browser/ui:browser_list",
     "//chrome/browser/ui:browser_navigator_params_headers",
     "//chrome/common",
@@ -61,3 +61,21 @@
     "//chrome/common:chrome_features",
   ]
 }
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [
+    "glic_enabling_unittest.cc",
+    "glic_profile_manager_unittest.cc",
+  ]
+  deps = [
+    ":enabling",
+    ":glic",
+    "//base/test:test_support",
+    "//chrome/browser/ui",
+    "//chrome/common:chrome_features",
+    "//chrome/test:test_support",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+}
diff --git a/chrome/browser/glic/glic_keyed_service.cc b/chrome/browser/glic/glic_keyed_service.cc
index 79150f0..4a0559a 100644
--- a/chrome/browser/glic/glic_keyed_service.cc
+++ b/chrome/browser/glic/glic_keyed_service.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/browser/glic/glic_focused_tab_manager.h"
 #include "chrome/browser/glic/glic_page_context_fetcher.h"
+#include "chrome/browser/glic/glic_profile_manager.h"
 #include "chrome/browser/glic/glic_window_controller.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
@@ -21,13 +22,17 @@
 
 namespace glic {
 
-GlicKeyedService::GlicKeyedService(content::BrowserContext* browser_context)
+GlicKeyedService::GlicKeyedService(content::BrowserContext* browser_context,
+                                   GlicProfileManager* profile_manager)
     : browser_context_(browser_context),
-      focused_tab_manager_(Profile::FromBrowserContext(browser_context)) {}
+      focused_tab_manager_(Profile::FromBrowserContext(browser_context)),
+      profile_manager_(profile_manager) {}
 
 GlicKeyedService::~GlicKeyedService() = default;
 
 void GlicKeyedService::LaunchUI() {
+  profile_manager_->OnUILaunching(this);
+
   if (!window_controller_) {
     window_controller_ = std::make_unique<GlicWindowController>(
         Profile::FromBrowserContext(browser_context_));
@@ -107,4 +112,8 @@
   }
 }
 
+base::WeakPtr<GlicKeyedService> GlicKeyedService::GetWeakPtr() {
+  return weak_ptr_factory_.GetWeakPtr();
+}
+
 }  // namespace glic
diff --git a/chrome/browser/glic/glic_keyed_service.h b/chrome/browser/glic/glic_keyed_service.h
index f4c899e7..8a1d1bc 100644
--- a/chrome/browser/glic/glic_keyed_service.h
+++ b/chrome/browser/glic/glic_keyed_service.h
@@ -18,11 +18,13 @@
 
 namespace glic {
 class GlicFocusedTabManager;
+class GlicProfileManager;
 class GlicWindowController;
 
 class GlicKeyedService : public KeyedService {
  public:
-  explicit GlicKeyedService(content::BrowserContext* browser_context);
+  explicit GlicKeyedService(content::BrowserContext* browser_context,
+                            GlicProfileManager* profile_manager);
   GlicKeyedService(const GlicKeyedService&) = delete;
   GlicKeyedService& operator=(const GlicKeyedService&) = delete;
   ~GlicKeyedService() override;
@@ -37,7 +39,7 @@
                  bool open_in_background,
                  const std::optional<int32_t>& window_id,
                  glic::mojom::WebClientHandler::CreateTabCallback callback);
-  void ClosePanel();
+  virtual void ClosePanel();
   std::optional<gfx::Size> ResizePanel(const gfx::Size& size);
 
   void GetContextFromFocusedTab(
@@ -45,11 +47,16 @@
       bool include_viewport_screenshot,
       glic::mojom::WebClientHandler::GetContextFromFocusedTabCallback callback);
 
+  base::WeakPtr<GlicKeyedService> GetWeakPtr();
+
  private:
   raw_ptr<content::BrowserContext> browser_context_;
 
   std::unique_ptr<GlicWindowController> window_controller_;
   GlicFocusedTabManager focused_tab_manager_;
+  // Unowned
+  raw_ptr<GlicProfileManager> profile_manager_;
+  base::WeakPtrFactory<GlicKeyedService> weak_ptr_factory_{this};
 };
 
 }  // namespace glic
diff --git a/chrome/browser/glic/glic_keyed_service_factory.cc b/chrome/browser/glic/glic_keyed_service_factory.cc
index 6cd99b0..7fc041b 100644
--- a/chrome/browser/glic/glic_keyed_service_factory.cc
+++ b/chrome/browser/glic/glic_keyed_service_factory.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/glic/glic_keyed_service_factory.h"
 
+#include "chrome/browser/glic/glic_profile_manager.h"
+
 namespace glic {
 
 // static
@@ -32,7 +34,8 @@
 std::unique_ptr<KeyedService>
 GlicKeyedServiceFactory::BuildServiceInstanceForBrowserContext(
     content::BrowserContext* context) const {
-  return std::make_unique<GlicKeyedService>(context);
+  return std::make_unique<GlicKeyedService>(context,
+                                            GlicProfileManager::GetInstance());
 }
 
 }  // namespace glic
diff --git a/chrome/browser/glic/glic_profile.cc b/chrome/browser/glic/glic_profile.cc
deleted file mode 100644
index 204220c..0000000
--- a/chrome/browser/glic/glic_profile.cc
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_manager.h"
-
-Profile* LastActiveGlicProfile() {
-  // TODO(https://crbug.com/379165457): Use the last profile opened with glic/
-  // the pinned glic profile before using the last active profile.
-  return ProfileManager::GetLastUsedProfileAllowedByPolicy();
-}
diff --git a/chrome/browser/glic/glic_profile.h b/chrome/browser/glic/glic_profile.h
deleted file mode 100644
index 3805ade..0000000
--- a/chrome/browser/glic/glic_profile.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GLIC_GLIC_PROFILE_H_
-#define CHROME_BROWSER_GLIC_GLIC_PROFILE_H_
-
-class Profile;
-
-// TODO(https://crbug.com/379165457): Hang this off of GlobalFeatures once there
-// is state to make sure that it is appropriately scoped.
-
-// The profile to open the glic UI with. This will be the last profile used
-// with glic, but if that doesn't exist, fallback to the pinned glic profile,
-// and failing that, the last active profile.
-Profile* LastActiveGlicProfile();
-
-#endif  // CHROME_BROWSER_GLIC_GLIC_PROFILE_H_
diff --git a/chrome/browser/glic/glic_profile_manager.cc b/chrome/browser/glic/glic_profile_manager.cc
new file mode 100644
index 0000000..31df4a16
--- /dev/null
+++ b/chrome/browser/glic/glic_profile_manager.cc
@@ -0,0 +1,41 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/glic/glic_profile_manager.h"
+
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/glic/glic_keyed_service_factory.h"
+#include "chrome/browser/global_features.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+
+namespace glic {
+GlicProfileManager* GlicProfileManager::GetInstance() {
+  return g_browser_process->GetFeatures()->glic_profile_manager();
+}
+
+void GlicProfileManager::CloseGlicWindow() {
+  if (active_glic_) {
+    active_glic_->ClosePanel();
+    active_glic_.reset();
+  }
+}
+
+Profile* GlicProfileManager::GetProfileForLaunch() {
+  // TODO(https://crbug.com/379165457): Implement profile choice logic.
+  return ProfileManager::GetLastUsedProfileAllowedByPolicy();
+}
+
+void GlicProfileManager::OnUILaunching(GlicKeyedService* glic) {
+  if (active_glic_ && active_glic_.get() != glic) {
+    active_glic_->ClosePanel();
+  }
+  active_glic_ = glic->GetWeakPtr();
+}
+
+GlicProfileManager::GlicProfileManager() = default;
+
+GlicProfileManager::~GlicProfileManager() = default;
+
+}  // namespace glic
diff --git a/chrome/browser/glic/glic_profile_manager.h b/chrome/browser/glic/glic_profile_manager.h
new file mode 100644
index 0000000..58b5d5b6
--- /dev/null
+++ b/chrome/browser/glic/glic_profile_manager.h
@@ -0,0 +1,44 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_GLIC_GLIC_PROFILE_MANAGER_H_
+#define CHROME_BROWSER_GLIC_GLIC_PROFILE_MANAGER_H_
+
+#include "base/memory/raw_ptr.h"
+#include "chrome/browser/glic/glic_keyed_service.h"
+
+class Profile;
+
+namespace glic {
+
+// GlicProfileManager is a GlobalFeature that is responsible for determining
+// which profile to use for launching the glic panel and for ensuring just one
+// panel is shown across all profiles.
+class GlicProfileManager {
+ public:
+  GlicProfileManager();
+  ~GlicProfileManager();
+
+  // Returns the global instance.
+  static GlicProfileManager* GetInstance();
+
+  GlicProfileManager(const GlicProfileManager&) = delete;
+  GlicProfileManager& operator=(const GlicProfileManager&) = delete;
+
+  // Close the Glic window, if one exists.
+  void CloseGlicWindow();
+
+  // Return the profile that should be used to open glic. May be null if there
+  // is no eligible profile.
+  Profile* GetProfileForLaunch();
+
+  // Called by GlicKeyedService.
+  void OnUILaunching(GlicKeyedService* glic);
+
+ private:
+  base::WeakPtr<GlicKeyedService> active_glic_;
+};
+}  // namespace glic
+
+#endif  // CHROME_BROWSER_GLIC_GLIC_PROFILE_MANAGER_H_
diff --git a/chrome/browser/glic/glic_profile_manager_unittest.cc b/chrome/browser/glic/glic_profile_manager_unittest.cc
new file mode 100644
index 0000000..7f390cd
--- /dev/null
+++ b/chrome/browser/glic/glic_profile_manager_unittest.cc
@@ -0,0 +1,54 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/glic/glic_profile_manager.h"
+
+#include "chrome/browser/glic/glic_keyed_service.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace glic {
+namespace {
+
+class MockGlicKeyedService : public GlicKeyedService {
+ public:
+  MockGlicKeyedService(content::BrowserContext* browser_context,
+                       GlicProfileManager* profile_manager)
+      : GlicKeyedService(browser_context, profile_manager) {}
+  MOCK_METHOD(void, ClosePanel, (), (override));
+};
+
+TEST(GlicProfileManagerTest, OnUILaunching_SameProfile) {
+  content::BrowserTaskEnvironment task_environment;
+  GlicProfileManager profile_manager;
+  TestingProfile profile;
+  MockGlicKeyedService service(&profile, &profile_manager);
+
+  profile_manager.OnUILaunching(&service);
+
+  // Opening glic twice for the same profile shouldn't cause it to close.
+  EXPECT_CALL(service, ClosePanel()).Times(0);
+  profile_manager.OnUILaunching(&service);
+}
+
+TEST(GlicProfileManagerTest, OnUILaunching_DifferentProfiles) {
+  content::BrowserTaskEnvironment task_environment;
+  GlicProfileManager profile_manager;
+  TestingProfile profile1;
+  TestingProfile profile2;
+  MockGlicKeyedService service1(&profile1, &profile_manager);
+  MockGlicKeyedService service2(&profile2, &profile_manager);
+
+  profile_manager.OnUILaunching(&service1);
+
+  // Opening glic from a second profile should make the profile manager close
+  // the first one.
+  EXPECT_CALL(service1, ClosePanel());
+  profile_manager.OnUILaunching(&service2);
+}
+
+}  // namespace
+}  // namespace glic
diff --git a/chrome/browser/glic/glic_window_controller.cc b/chrome/browser/glic/glic_window_controller.cc
index 10be2ea..bfa1a2e 100644
--- a/chrome/browser/glic/glic_window_controller.cc
+++ b/chrome/browser/glic/glic_window_controller.cc
@@ -52,10 +52,6 @@
   glic_view_ = nullptr;
 }
 
-base::WeakPtr<GlicWindowController> GlicWindowController::GetWeakPtr() {
-  return weak_ptr_factory_.GetWeakPtr();
-}
-
 GlicWindowController::~GlicWindowController() = default;
 
 }  // namespace glic
diff --git a/chrome/browser/glic/glic_window_controller.h b/chrome/browser/glic/glic_window_controller.h
index b6af5563..8d5f799 100644
--- a/chrome/browser/glic/glic_window_controller.h
+++ b/chrome/browser/glic/glic_window_controller.h
@@ -40,17 +40,11 @@
   // Called to notify the controller that the window was requested to be closed.
   void Close();
 
-  // Returns a WeakPtr to this instance. It can be destroyed at any time if the
-  // profile is deleted or if the browser shuts down.
-  base::WeakPtr<GlicWindowController> GetWeakPtr();
-
  private:
   const raw_ptr<Profile> profile_;
   views::UniqueWidgetPtr widget_;
   // Owned by widget_.
   raw_ptr<glic::GlicView> glic_view_ = nullptr;
-
-  base::WeakPtrFactory<GlicWindowController> weak_ptr_factory_{this};
 };
 
 }  // namespace glic
diff --git a/chrome/browser/glic/glic_window_manager.cc b/chrome/browser/glic/glic_window_manager.cc
deleted file mode 100644
index ae68d514..0000000
--- a/chrome/browser/glic/glic_window_manager.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/glic/glic_window_manager.h"
-
-#include "chrome/browser/glic/glic_keyed_service_factory.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_manager.h"
-
-namespace glic {
-GlicWindowManager* GlicWindowManager::GetInstance() {
-  return base::Singleton<GlicWindowManager>::get();
-}
-
-void GlicWindowManager::ShowGlicWindowForProfile(Profile* profile) {
-  GlicKeyedService* service =
-      GlicKeyedServiceFactory::GetGlicKeyedService(profile);
-
-  // If there was already a controller, close the existing window before
-  // creating the next one.
-  if (glic_window_controller_ &&
-      glic_window_controller_.get() != service->window_controller()) {
-    CloseGlicWindow();
-  }
-
-  service->LaunchUI();
-  glic_window_controller_ = service->window_controller()->GetWeakPtr();
-}
-
-void GlicWindowManager::ShowGlicWindowForPinnedProfile() {
-  // TODO(crbug.com/380298150): Use pinned profile instead of last used.
-  ShowGlicWindowForProfile(ProfileManager::GetLastUsedProfileAllowedByPolicy());
-}
-
-void GlicWindowManager::CloseGlicWindow() {
-  if (glic_window_controller_) {
-    glic_window_controller_->Close();
-    glic_window_controller_.reset();
-  }
-}
-
-GlicWindowManager::GlicWindowManager() = default;
-
-GlicWindowManager::~GlicWindowManager() = default;
-
-}  // namespace glic
diff --git a/chrome/browser/glic/glic_window_manager.h b/chrome/browser/glic/glic_window_manager.h
deleted file mode 100644
index 3b3cfdb6..0000000
--- a/chrome/browser/glic/glic_window_manager.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GLIC_GLIC_WINDOW_MANAGER_H_
-#define CHROME_BROWSER_GLIC_GLIC_WINDOW_MANAGER_H_
-
-#include "base/memory/raw_ptr.h"
-#include "base/memory/singleton.h"
-#include "base/observer_list.h"
-#include "chrome/browser/glic/glic_window_controller.h"
-
-class GlicWindowController;
-class Profile;
-
-namespace glic {
-
-// GlicWindowManager is a singleton that guarantees that only one panel will be
-// present per Chrome instance regardless of the number of windows, tabs,
-// profiles, etc. In addition to guaranteeing one panel at a time, it is able to
-// choose a profile for launching the window as well as show the Profile Picker,
-// if needed.
-class GlicWindowManager {
- public:
-  // Returns the singleton instance.
-  static GlicWindowManager* GetInstance();
-
-  GlicWindowManager(const GlicWindowManager&) = delete;
-  GlicWindowManager& operator=(const GlicWindowManager&) = delete;
-
-  // Create a Glic window for profile, if there is any.
-  void ShowGlicWindowForProfile(Profile* profile);
-
-  // Show the Glic window for the pinned profile, if there is one.
-  void ShowGlicWindowForPinnedProfile();
-
-  // Close the Glic window, if one exists.
-  void CloseGlicWindow();
-
- private:
-  friend struct base::DefaultSingletonTraits<GlicWindowManager>;
-
-  GlicWindowManager();
-  ~GlicWindowManager();
-
-  base::WeakPtr<GlicWindowController> glic_window_controller_;
-};
-}  // namespace glic
-
-#endif  // CHROME_BROWSER_GLIC_GLIC_WINDOW_MANAGER_H_
diff --git a/chrome/browser/glic/launcher/BUILD.gn b/chrome/browser/glic/launcher/BUILD.gn
index 44a10d6a..a1166273 100644
--- a/chrome/browser/glic/launcher/BUILD.gn
+++ b/chrome/browser/glic/launcher/BUILD.gn
@@ -5,9 +5,13 @@
     "glic_controller.h",
   ]
 
+  # TODO(crbug.com/378487333): Replace extensions build target to use the
+  # updated version in ui/base
   deps = [
     "//base",
+    "//chrome/browser/extensions:extensions",
     "//components/prefs",
+    "//extensions/common:common",
     "//ui/base",
   ]
 }
@@ -22,11 +26,15 @@
   ]
 
   public_deps = [ "//chrome/browser:browser_public_dependencies" ]
+
+  # TODO(crbug.com/378487333): Replace extensions build target to use the
+  # updated version in ui/base/
   deps = [
     ":launcher",
     "//chrome/app:command_ids",
     "//chrome/app:generated_resources",
     "//chrome/browser:browser_process",
+    "//chrome/browser/extensions:extensions",
     "//chrome/browser/glic",
     "//chrome/browser/ui",
     "//chrome/common:constants",
@@ -48,6 +56,7 @@
     "//base/test:test_support",
     "//chrome/browser",
     "//chrome/browser:browser_process",
+    "//chrome/browser:global_features",
     "//chrome/common:chrome_features",
     "//chrome/common:constants",
     "//chrome/test:test_support_ui",
diff --git a/chrome/browser/glic/launcher/glic_background_mode_manager.cc b/chrome/browser/glic/launcher/glic_background_mode_manager.cc
index 7da919b..29d4d11 100644
--- a/chrome/browser/glic/launcher/glic_background_mode_manager.cc
+++ b/chrome/browser/glic/launcher/glic_background_mode_manager.cc
@@ -6,20 +6,24 @@
 
 #include <memory>
 
+#include "base/check.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/global_shortcut_listener.h"
 #include "chrome/browser/glic/launcher/glic_controller.h"
 #include "chrome/browser/glic/launcher/glic_status_icon.h"
 #include "components/keep_alive_registry/keep_alive_types.h"
 #include "components/keep_alive_registry/scoped_keep_alive.h"
+#include "ui/base/accelerators/accelerator.h"
 
 namespace glic {
 
 GlicBackgroundModeManager::GlicBackgroundModeManager(StatusTray* status_tray)
-    : status_tray_(status_tray) {
-  configuration_ = std::make_unique<GlicConfiguration>(this);
-  OnEnabledChanged(configuration_->IsEnabled());
-
-  controller_ = std::make_unique<GlicController>();
+    : configuration_(std::make_unique<GlicConfiguration>(this)),
+      controller_(std::make_unique<GlicController>()),
+      status_tray_(status_tray),
+      enabled_(configuration_->IsEnabled()),
+      expected_registered_hotkey_(configuration_->GetGlobalHotkey()) {
+  UpdateState();
 }
 
 GlicBackgroundModeManager::~GlicBackgroundModeManager() = default;
@@ -30,28 +34,78 @@
   }
 
   enabled_ = enabled;
-  if (enabled_) {
-    EnterBackgroundMode();
-  } else {
-    ExitBackgroundMode();
-  }
+  UpdateState();
   EnableLaunchOnStartup(enabled_);
 }
 
-void GlicBackgroundModeManager::EnterBackgroundMode() {
-  keep_alive_ = std::make_unique<ScopedKeepAlive>(
-      KeepAliveOrigin::GLIC_LAUNCHER, KeepAliveRestartOption::ENABLED);
+void GlicBackgroundModeManager::OnGlobalHotkeyChanged(ui::Accelerator hotkey) {
+  if (expected_registered_hotkey_ == hotkey) {
+    return;
+  }
 
-  status_icon_ =
-      std::make_unique<GlicStatusIcon>(controller_.get(), status_tray_);
+  expected_registered_hotkey_ = hotkey;
+  UpdateState();
+}
+
+void GlicBackgroundModeManager::OnKeyPressed(
+    const ui::Accelerator& accelerator) {
+  CHECK(accelerator == actual_registered_hotkey_);
+  CHECK(actual_registered_hotkey_ == expected_registered_hotkey_);
+  controller_->Show();
+}
+
+void GlicBackgroundModeManager::EnterBackgroundMode() {
+  if (!keep_alive_) {
+    keep_alive_ = std::make_unique<ScopedKeepAlive>(
+        KeepAliveOrigin::GLIC_LAUNCHER, KeepAliveRestartOption::ENABLED);
+  }
+
+  if (!status_icon_) {
+    status_icon_ =
+        std::make_unique<GlicStatusIcon>(controller_.get(), status_tray_);
+  }
 }
 
 void GlicBackgroundModeManager::ExitBackgroundMode() {
   status_icon_.reset();
-
   keep_alive_.reset();
 }
 
-void GlicBackgroundModeManager::EnableLaunchOnStartup(bool should_launch) {}
+void GlicBackgroundModeManager::EnableLaunchOnStartup(bool should_launch) {
+  // TODO(crbug.com/378140958): Implement function
+}
+
+void GlicBackgroundModeManager::RegisterHotkey(ui::Accelerator updated_hotkey) {
+  CHECK(!updated_hotkey.IsEmpty());
+  auto* const global_shortcut_listener =
+      extensions::GlobalShortcutListener::GetInstance();
+  CHECK(global_shortcut_listener);
+  if (global_shortcut_listener->RegisterAccelerator(updated_hotkey, this)) {
+    actual_registered_hotkey_ = updated_hotkey;
+  }
+}
+
+void GlicBackgroundModeManager::UnregisterHotkey() {
+  auto* const global_shortcut_listener =
+      extensions::GlobalShortcutListener::GetInstance();
+  CHECK(global_shortcut_listener);
+  if (!actual_registered_hotkey_.IsEmpty()) {
+    global_shortcut_listener->UnregisterAccelerator(actual_registered_hotkey_,
+                                                    this);
+  }
+  actual_registered_hotkey_ = ui::Accelerator();
+}
+
+void GlicBackgroundModeManager::UpdateState() {
+  UnregisterHotkey();
+  if (enabled_) {
+    EnterBackgroundMode();
+    if (!expected_registered_hotkey_.IsEmpty()) {
+      RegisterHotkey(expected_registered_hotkey_);
+    }
+  } else {
+    ExitBackgroundMode();
+  }
+}
 
 }  // namespace glic
diff --git a/chrome/browser/glic/launcher/glic_background_mode_manager.h b/chrome/browser/glic/launcher/glic_background_mode_manager.h
index b0b7640..9388edd4 100644
--- a/chrome/browser/glic/launcher/glic_background_mode_manager.h
+++ b/chrome/browser/glic/launcher/glic_background_mode_manager.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "base/memory/raw_ptr.h"
+#include "chrome/browser/extensions/global_shortcut_listener.h"
 #include "chrome/browser/glic/launcher/glic_configuration.h"
 
 class GlicController;
@@ -15,29 +16,49 @@
 class ScopedKeepAlive;
 class StatusTray;
 
+namespace ui {
+class Accelerator;
+}
+
 namespace glic {
 
 // This is a global feature in the browser process that manages the
 // enabling/disabling of glic background mode. When background mode is enabled,
 // chrome is set to keep alive the browser process, so that this class can
 // listen to a global hotkey, and provide a status icon for triggering the UI.
-class GlicBackgroundModeManager : public GlicConfiguration::Observer {
+class GlicBackgroundModeManager
+    : public GlicConfiguration::Observer,
+      public extensions::GlobalShortcutListener::Observer {
  public:
   explicit GlicBackgroundModeManager(StatusTray* status_tray);
   ~GlicBackgroundModeManager() override;
 
   // GlicConfiguration::Observer
   void OnEnabledChanged(bool enabled) override;
+  void OnGlobalHotkeyChanged(ui::Accelerator hotkey) override;
+
+  // extensions::GlobalShortcutListener::Observer
+  void OnKeyPressed(const ui::Accelerator& accelerator) override;
+
+  // TODO(crbug.com/378487333): Remove this method because this method is
+  // specific to the extensions version of the GlobalShortcutListener
+  void ExecuteCommand(const extensions::ExtensionId& extension_id,
+                      const std::string& command_id) override {}
+
+  ui::Accelerator RegisteredHotkeyForTesting() {
+    return actual_registered_hotkey_;
+  }
 
  private:
   void EnterBackgroundMode();
   void ExitBackgroundMode();
-
   void EnableLaunchOnStartup(bool should_launch);
+  void RegisterHotkey(ui::Accelerator updated_hotkey);
+  void UnregisterHotkey();
+  void UpdateState();
 
   // A helper class for observing pref changes.
   std::unique_ptr<GlicConfiguration> configuration_;
-  bool enabled_ = false;
 
   // An abstraction used to show/hide the UI.
   std::unique_ptr<GlicController> controller_;
@@ -50,6 +71,14 @@
   // Class that represents the glic status icon. Only exists when the background
   // mode is enabled.
   std::unique_ptr<GlicStatusIcon> status_icon_;
+
+  bool enabled_ = false;
+  // The actual registered hotkey may be different from the expected hotkey
+  // because the Glic launcher may be disabled or registration fails which
+  // results in no hotkey being registered and is represented with an empty
+  // accelerator.
+  ui::Accelerator expected_registered_hotkey_;
+  ui::Accelerator actual_registered_hotkey_;
 };
 }  // namespace glic
 
diff --git a/chrome/browser/glic/launcher/glic_background_mode_manager_browsertest.cc b/chrome/browser/glic/launcher/glic_background_mode_manager_browsertest.cc
index 51313ad..d424c99 100644
--- a/chrome/browser/glic/launcher/glic_background_mode_manager_browsertest.cc
+++ b/chrome/browser/glic/launcher/glic_background_mode_manager_browsertest.cc
@@ -5,7 +5,10 @@
 #include "chrome/browser/glic/launcher/glic_background_mode_manager.h"
 
 #include "base/test/scoped_feature_list.h"
+#include "base/values.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/glic/launcher/glic_configuration.h"
+#include "chrome/browser/global_features.h"
 #include "chrome/browser/status_icons/status_tray.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
@@ -15,9 +18,11 @@
 #include "components/prefs/pref_service.h"
 #include "content/public/test/browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/accelerators/accelerator.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/keycodes/keyboard_codes.h"
 
 namespace glic {
-namespace {
 
 class GlicBackgroundModeManagerBrowserTest : public InProcessBrowserTest {
  public:
@@ -26,6 +31,23 @@
     InProcessBrowserTest::SetUp();
   }
 
+  void TearDownOnMainThread() override {
+    // Disable glic so that the glic_background_mode_manager won't prevent the
+    // browser process from closing which causes the test to hang.
+    g_browser_process->local_state()->SetBoolean(prefs::kGlicLauncherEnabled,
+                                                 false);
+  }
+
+  void RegisterHotkey(ui::Accelerator updated_hotkey) {
+    auto hotkey_dictionary =
+        base::Value::Dict()
+            .Set(GlicConfiguration::kHotkeyKeyCode, updated_hotkey.key_code())
+            .Set(GlicConfiguration::kHotkeyModifiers,
+                 updated_hotkey.modifiers());
+    g_browser_process->local_state()->SetDict(prefs::kGlicLauncherGlobalHotkey,
+                                              std::move(hotkey_dictionary));
+  }
+
  private:
   base::test::ScopedFeatureList feature_list_;
 };
@@ -63,5 +85,48 @@
       StatusTray::StatusIconType::GLIC_ICON));
 }
 
-}  // namespace
+IN_PROC_BROWSER_TEST_F(GlicBackgroundModeManagerBrowserTest,
+                       UpdateHotkeyWhileEnabled) {
+  g_browser_process->local_state()->SetBoolean(prefs::kGlicLauncherEnabled,
+                                               true);
+  GlicBackgroundModeManager* const manager =
+      g_browser_process->GetFeatures()->glic_background_mode_manager();
+  EXPECT_EQ(ui::Accelerator(), manager->RegisteredHotkeyForTesting());
+
+  ui::Accelerator updated_hotkey(ui::VKEY_A, ui::EF_SHIFT_DOWN);
+  RegisterHotkey(updated_hotkey);
+  EXPECT_EQ(updated_hotkey, manager->RegisteredHotkeyForTesting());
+}
+
+IN_PROC_BROWSER_TEST_F(GlicBackgroundModeManagerBrowserTest,
+                       UpdateHotkeyWhileDisabled) {
+  PrefService* const pref_service = g_browser_process->local_state();
+  ASSERT_FALSE(pref_service->GetBoolean(prefs::kGlicLauncherEnabled));
+  GlicBackgroundModeManager* const manager =
+      g_browser_process->GetFeatures()->glic_background_mode_manager();
+  EXPECT_TRUE(manager->RegisteredHotkeyForTesting().IsEmpty());
+
+  // If the hotkey pref were to somehow change even while glic was disabled,
+  // the manager should not register the hotkey.
+  ui::Accelerator updated_hotkey(ui::VKEY_A, ui::EF_SHIFT_DOWN);
+  RegisterHotkey(updated_hotkey);
+  EXPECT_TRUE(manager->RegisteredHotkeyForTesting().IsEmpty());
+
+  // Re-enabling glic should register the updated hotkey pref.
+  pref_service->SetBoolean(prefs::kGlicLauncherEnabled, true);
+  EXPECT_EQ(updated_hotkey, manager->RegisteredHotkeyForTesting());
+}
+
+IN_PROC_BROWSER_TEST_F(GlicBackgroundModeManagerBrowserTest,
+                       RegisterInvalidAccelerator) {
+  g_browser_process->local_state()->SetBoolean(prefs::kGlicLauncherEnabled,
+                                               true);
+  GlicBackgroundModeManager* const manager =
+      g_browser_process->GetFeatures()->glic_background_mode_manager();
+
+  // Registering an invalid hotkey should fail.
+  ui::Accelerator updated_hotkey(ui::VKEY_A, ui::EF_NONE);
+  RegisterHotkey(updated_hotkey);
+  EXPECT_NE(updated_hotkey, manager->RegisteredHotkeyForTesting());
+}
 }  // namespace glic
diff --git a/chrome/browser/glic/launcher/glic_configuration.cc b/chrome/browser/glic/launcher/glic_configuration.cc
index a9301584..ff96ca1 100644
--- a/chrome/browser/glic/launcher/glic_configuration.cc
+++ b/chrome/browser/glic/launcher/glic_configuration.cc
@@ -4,10 +4,14 @@
 
 #include "chrome/browser/glic/launcher/glic_configuration.h"
 
+#include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
+#include "ui/base/accelerators/accelerator.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/keycodes/keyboard_codes.h"
 
 namespace glic {
 
@@ -18,6 +22,10 @@
         prefs::kGlicLauncherEnabled,
         base::BindRepeating(&GlicConfiguration::OnEnabledPrefChanged,
                             base::Unretained(this)));
+    pref_registrar_.Add(
+        prefs::kGlicLauncherGlobalHotkey,
+        base::BindRepeating(&GlicConfiguration::OnGlobalHotkeyPrefChanged,
+                            base::Unretained(this)));
   }
 }
 
@@ -26,6 +34,14 @@
 // static
 void GlicConfiguration::RegisterPrefs(PrefRegistrySimple* registry) {
   registry->RegisterBooleanPref(prefs::kGlicLauncherEnabled, false);
+  registry->RegisterBooleanPref(prefs::kGlicMicrophoneEnabled, false);
+  registry->RegisterBooleanPref(prefs::kGlicGeolocationEnabled, false);
+  registry->RegisterBooleanPref(prefs::kGlicTabContextEnabled, false);
+  registry->RegisterDictionaryPref(
+      prefs::kGlicLauncherGlobalHotkey,
+      base::Value::Dict()
+          .Set(kHotkeyKeyCode, ui::KeyboardCode::VKEY_UNKNOWN)
+          .Set(kHotkeyModifiers, ui::EF_NONE));
 }
 
 bool GlicConfiguration::IsEnabled() {
@@ -33,8 +49,30 @@
       prefs::kGlicLauncherEnabled);
 }
 
+ui::Accelerator GlicConfiguration::GetGlobalHotkey() {
+  const base::Value::Dict& hotkey_dictionary =
+      g_browser_process->local_state()->GetDict(
+          prefs::kGlicLauncherGlobalHotkey);
+  const int key_code = hotkey_dictionary.Find(kHotkeyKeyCode)->GetInt();
+  const int modifiers = hotkey_dictionary.Find(kHotkeyModifiers)->GetInt();
+  const ui::Accelerator hotkey =
+      ui::Accelerator(static_cast<ui::KeyboardCode>(key_code), modifiers);
+
+  // Return empty accelerator if an invalid modifier was set.
+  if (!hotkey.IsEmpty() &&
+      ui::Accelerator::MaskOutKeyEventFlags(modifiers) == 0) {
+    return ui::Accelerator();
+  }
+
+  return hotkey;
+}
+
 void GlicConfiguration::OnEnabledPrefChanged() {
   manager_->OnEnabledChanged(IsEnabled());
 }
 
+void GlicConfiguration::OnGlobalHotkeyPrefChanged() {
+  manager_->OnGlobalHotkeyChanged(GetGlobalHotkey());
+}
+
 }  // namespace glic
diff --git a/chrome/browser/glic/launcher/glic_configuration.h b/chrome/browser/glic/launcher/glic_configuration.h
index b146e6e..27002e0 100644
--- a/chrome/browser/glic/launcher/glic_configuration.h
+++ b/chrome/browser/glic/launcher/glic_configuration.h
@@ -24,6 +24,9 @@
     virtual void OnGlobalHotkeyChanged(ui::Accelerator hotkey) {}
   };
 
+  static constexpr char kHotkeyKeyCode[] = "keycode";
+  static constexpr char kHotkeyModifiers[] = "modifiers";
+
   explicit GlicConfiguration(Observer* manager);
   ~GlicConfiguration();
 
@@ -31,8 +34,11 @@
 
   bool IsEnabled();
 
+  ui::Accelerator GetGlobalHotkey();
+
  private:
   void OnEnabledPrefChanged();
+  void OnGlobalHotkeyPrefChanged();
 
   PrefChangeRegistrar pref_registrar_;
 
diff --git a/chrome/browser/glic/launcher/glic_controller.cc b/chrome/browser/glic/launcher/glic_controller.cc
index 46690aa..e156420 100644
--- a/chrome/browser/glic/launcher/glic_controller.cc
+++ b/chrome/browser/glic/launcher/glic_controller.cc
@@ -7,7 +7,8 @@
 #include "chrome/common/buildflags.h"
 
 #if BUILDFLAG(ENABLE_GLIC)
-#include "chrome/browser/glic/glic_window_manager.h"
+#include "chrome/browser/glic/glic_keyed_service_factory.h"
+#include "chrome/browser/glic/glic_profile_manager.h"
 #endif
 
 GlicController::GlicController() = default;
@@ -15,12 +16,21 @@
 
 void GlicController::Show() {
 #if BUILDFLAG(ENABLE_GLIC)
-  glic::GlicWindowManager::GetInstance()->ShowGlicWindowForPinnedProfile();
+  Profile* profile =
+      glic::GlicProfileManager::GetInstance()->GetProfileForLaunch();
+  if (!profile) {
+    // TODO(crbug.com/380095872): If there are no eligible profiles, show the
+    // profile picker to choose a profile in which to enter the first-run
+    // experience.
+    return;
+  }
+
+  glic::GlicKeyedServiceFactory::GetGlicKeyedService(profile)->LaunchUI();
 #endif
 }
 
 void GlicController::Hide() {
 #if BUILDFLAG(ENABLE_GLIC)
-  glic::GlicWindowManager::GetInstance()->CloseGlicWindow();
+  glic::GlicProfileManager::GetInstance()->CloseGlicWindow();
 #endif
 }
diff --git a/chrome/browser/glic/launcher/glic_status_icon.cc b/chrome/browser/glic/launcher/glic_status_icon.cc
index 178688ae..da37300 100644
--- a/chrome/browser/glic/launcher/glic_status_icon.cc
+++ b/chrome/browser/glic/launcher/glic_status_icon.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/glic/launcher/glic_status_icon.h"
 
 #include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/glic/glic_profile.h"
+#include "chrome/browser/glic/glic_profile_manager.h"
 #include "chrome/browser/glic/launcher/glic_controller.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/status_icons/status_icon.h"
@@ -67,13 +67,15 @@
     case IDC_GLIC_STATUS_ICON_MENU_CUSTOMIZE_KEYBOARD_SHORTCUT:
       // TODO(https://crbug.com/378143781): Use correct settings subpage and
       // show help bubble on the appropriate setting.
-      chrome::ShowSettingsSubPageForProfile(LastActiveGlicProfile(),
-                                            std::string());
+      chrome::ShowSettingsSubPageForProfile(
+          glic::GlicProfileManager::GetInstance()->GetProfileForLaunch(),
+          std::string());
       break;
     case IDC_GLIC_STATUS_ICON_MENU_SETTINGS:
       // TODO(https://crbug.com/378143780): Use the correct settings subpage.
-      chrome::ShowSettingsSubPageForProfile(LastActiveGlicProfile(),
-                                            std::string());
+      chrome::ShowSettingsSubPageForProfile(
+          glic::GlicProfileManager::GetInstance()->GetProfileForLaunch(),
+          std::string());
       break;
     default:
       NOTREACHED();
diff --git a/chrome/browser/global_features.cc b/chrome/browser/global_features.cc
index 290f774..527a9dd 100644
--- a/chrome/browser/global_features.cc
+++ b/chrome/browser/global_features.cc
@@ -20,8 +20,10 @@
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
 // This causes a gn error on Android builds, because gn does not understand
 // buildflags, so we include it only on platforms where it is used.
-#include "components/user_education/common/user_education_features.h"  // nogncheck
+#include "chrome/browser/glic/glic_enabling.h"         // nogncheck
+#include "chrome/browser/glic/glic_profile_manager.h"  // nogncheck
 #include "chrome/browser/ui/webui/whats_new/whats_new_registrar.h"
+#include "components/user_education/common/user_education_features.h"  // nogncheck
 #endif
 
 namespace {
@@ -60,6 +62,9 @@
   if (user_education::features::IsWhatsNewV2()) {
     whats_new_registry_ = CreateWhatsNewRegistry();
   }
+  if (GlicEnabling::IsEnabledByFlags()) {
+    glic_profile_manager_ = std::make_unique<glic::GlicProfileManager>();
+  }
 #endif
 
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
diff --git a/chrome/browser/global_features.h b/chrome/browser/global_features.h
index dcccfb2..481f563 100644
--- a/chrome/browser/global_features.h
+++ b/chrome/browser/global_features.h
@@ -13,14 +13,15 @@
 namespace system_permission_settings {
 class PlatformHandle;
 }  // namespace system_permission_settings
-namespace whats_new {
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
+namespace whats_new {
 class WhatsNewRegistry;
-#endif
 }  // namespace whats_new
 namespace glic {
 class GlicBackgroundModeManager;
-}
+class GlicProfileManager;
+}  // namespace glic
+#endif
 
 // This class owns the core controllers for features that are globally
 // scoped on desktop. It can be subclassed by tests to perform
@@ -52,6 +53,10 @@
   whats_new::WhatsNewRegistry* whats_new_registry() {
     return whats_new_registry_.get();
   }
+
+  glic::GlicProfileManager* glic_profile_manager() {
+    return glic_profile_manager_.get();
+  }
 #endif
 
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
@@ -81,6 +86,7 @@
       system_permissions_platform_handle_;
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
   std::unique_ptr<whats_new::WhatsNewRegistry> whats_new_registry_;
+  std::unique_ptr<glic::GlicProfileManager> glic_profile_manager_;
 #endif
 
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
diff --git a/chrome/browser/history_embeddings/history_embeddings_service_factory.cc b/chrome/browser/history_embeddings/history_embeddings_service_factory.cc
index 8df39e5..c837545 100644
--- a/chrome/browser/history_embeddings/history_embeddings_service_factory.cc
+++ b/chrome/browser/history_embeddings/history_embeddings_service_factory.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/history_embeddings/chrome_history_embeddings_service.h"
+#include "chrome/browser/history_embeddings/history_embeddings_utils.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
 #include "chrome/browser/page_content_annotations/page_content_annotations_service_factory.h"
@@ -49,7 +50,7 @@
 
 bool ShouldBuildServiceInstance(Profile* profile) {
   // Do NOT construct the service if the feature flag is disabled.
-  if (!history_embeddings::IsHistoryEmbeddingsEnabled()) {
+  if (!history_embeddings::IsHistoryEmbeddingsFeatureEnabled()) {
     return false;
   }
 
@@ -127,7 +128,7 @@
       OptimizationGuideKeyedServiceFactory::GetForProfile(profile);
 
   std::unique_ptr<history_embeddings::Answerer> answerer;
-  if (history_embeddings::IsHistoryEmbeddingsAnswersEnabled()) {
+  if (history_embeddings::IsHistoryEmbeddingsAnswersFeatureEnabled()) {
     if (history_embeddings::GetFeatureParameters().use_ml_answerer) {
       answerer = std::make_unique<history_embeddings::MlAnswerer>(
           optimization_guide_keyed_service);
diff --git a/chrome/browser/history_embeddings/history_embeddings_utils.cc b/chrome/browser/history_embeddings/history_embeddings_utils.cc
index 515b04d..8b018df 100644
--- a/chrome/browser/history_embeddings/history_embeddings_utils.cc
+++ b/chrome/browser/history_embeddings/history_embeddings_utils.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/history_embeddings/history_embeddings_utils.h"
 
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/history_embeddings/history_embeddings_service_factory.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
@@ -13,12 +14,29 @@
 #include "components/history_embeddings/history_embeddings_service.h"
 #include "components/optimization_guide/core/optimization_guide_features.h"
 #include "components/strings/grit/components_strings.h"
+#include "components/variations/service/variations_service.h"
 #include "content/public/browser/web_ui_data_source.h"
 
+#if BUILDFLAG(IS_CHROMEOS)
+#include "chromeos/constants/chromeos_features.h"
+#endif
+
 namespace history_embeddings {
 
+namespace {
+bool IsEnabledForCountryAndLocale(const base::Feature& launch_feature) {
+  // Launch in the US via client-side code, leaving a Finch hook available just
+  // in case. Note, the variations service may be nullptr in unit tests.
+  return g_browser_process && g_browser_process->variations_service() &&
+         g_browser_process->variations_service()->GetStoredPermanentCountry() ==
+             "US" &&
+         g_browser_process->GetApplicationLocale() == "en-US" &&
+         base::FeatureList::IsEnabled(launch_feature);
+}
+}  // namespace
+
 bool IsHistoryEmbeddingsEnabledForProfile(Profile* profile) {
-  if (!IsHistoryEmbeddingsEnabled()) {
+  if (!IsHistoryEmbeddingsFeatureEnabled()) {
     return false;
   }
 
@@ -31,7 +49,7 @@
 }
 
 bool IsHistoryEmbeddingsSettingVisible(Profile* profile) {
-  if (!IsHistoryEmbeddingsEnabled()) {
+  if (!IsHistoryEmbeddingsFeatureEnabled()) {
     return false;
   }
 
@@ -46,10 +64,11 @@
                             Profile* profile) {
   auto* history_embeddings_service =
       HistoryEmbeddingsServiceFactory::GetForProfile(profile);
-  source->AddBoolean("enableHistoryEmbeddingsAnswers",
-                     history_embeddings::IsHistoryEmbeddingsAnswersEnabled() &&
-                         history_embeddings_service &&
-                         history_embeddings_service->IsAnswererUseAllowed());
+  source->AddBoolean(
+      "enableHistoryEmbeddingsAnswers",
+      history_embeddings::IsHistoryEmbeddingsAnswersFeatureEnabled() &&
+          history_embeddings_service &&
+          history_embeddings_service->IsAnswererUseAllowed());
   source->AddBoolean(
       "enableHistoryEmbeddingsImages",
       history_embeddings::GetFeatureParameters().enable_images_for_results);
@@ -88,4 +107,32 @@
           : chrome::kHistorySearchSettingURL);
 }
 
+bool IsHistoryEmbeddingsFeatureEnabled() {
+#if BUILDFLAG(IS_CHROMEOS)
+  if (!chromeos::features::IsFeatureManagementHistoryEmbeddingEnabled()) {
+    return false;
+  }
+#endif
+
+  if (IsEnabledForCountryAndLocale(kLaunchedHistoryEmbeddings)) {
+    return true;
+  }
+
+  // Gate on server-side Finch config for all other countries/locales.
+  return base::FeatureList::IsEnabled(kHistoryEmbeddings);
+}
+
+bool IsHistoryEmbeddingsAnswersFeatureEnabled() {
+  if (!IsHistoryEmbeddingsFeatureEnabled()) {
+    return false;
+  }
+
+  if (IsEnabledForCountryAndLocale(kLaunchedHistoryEmbeddingsAnswers)) {
+    return true;
+  }
+
+  // Gate on server-side Finch config for all other countries/locales.
+  return base::FeatureList::IsEnabled(kHistoryEmbeddingsAnswers);
+}
+
 }  // namespace history_embeddings
diff --git a/chrome/browser/history_embeddings/history_embeddings_utils.h b/chrome/browser/history_embeddings/history_embeddings_utils.h
index 276f393b..73fad9d4 100644
--- a/chrome/browser/history_embeddings/history_embeddings_utils.h
+++ b/chrome/browser/history_embeddings/history_embeddings_utils.h
@@ -13,6 +13,7 @@
 
 namespace history_embeddings {
 
+// Checks whether the feature behavior is enabled for given profile.
 bool IsHistoryEmbeddingsEnabledForProfile(Profile* profile);
 
 // Return if the feature is enabled and the setting is visible; i.e. if users
@@ -21,6 +22,14 @@
 
 void PopulateSourceForWebUI(content::WebUIDataSource* source, Profile* profile);
 
+// Whether the HistoryEmbeddings feature is enabled. This only checks if the
+// feature flags are enabled and does not check the user's opt-in preference
+// or eligibility based on the user profile.
+bool IsHistoryEmbeddingsFeatureEnabled();
+
+// Whether the HistoryEmbeddingsAnswers feature is enabled.
+bool IsHistoryEmbeddingsAnswersFeatureEnabled();
+
 }  // namespace history_embeddings
 
 #endif  // CHROME_BROWSER_HISTORY_EMBEDDINGS_HISTORY_EMBEDDINGS_UTILS_H_
diff --git a/chrome/browser/magic_stack/android/BUILD.gn b/chrome/browser/magic_stack/android/BUILD.gn
index 261517c4..83492e5 100644
--- a/chrome/browser/magic_stack/android/BUILD.gn
+++ b/chrome/browser/magic_stack/android/BUILD.gn
@@ -14,6 +14,7 @@
     "java/src/org/chromium/chrome/browser/magic_stack/HomeModulesMediator.java",
     "java/src/org/chromium/chrome/browser/magic_stack/HomeModulesMetricsUtils.java",
     "java/src/org/chromium/chrome/browser/magic_stack/HomeModulesRecyclerView.java",
+    "java/src/org/chromium/chrome/browser/magic_stack/HomeModulesUtils.java",
     "java/src/org/chromium/chrome/browser/magic_stack/ModuleConfigChecker.java",
     "java/src/org/chromium/chrome/browser/magic_stack/ModuleDelegate.java",
     "java/src/org/chromium/chrome/browser/magic_stack/ModuleDelegateHost.java",
@@ -75,6 +76,7 @@
     "junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesMediatorUnitTest.java",
     "junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesMetricsUtilsUnitTest.java",
     "junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesRecyclerViewUnitTest.java",
+    "junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesUtilsUnitTest.java",
     "junit/src/org/chromium/chrome/browser/magic_stack/ModuleRegistryUnitTest.java",
   ]
 
diff --git a/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesConfigManager.java b/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesConfigManager.java
index 1a36a8c..09d837e2 100644
--- a/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesConfigManager.java
+++ b/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesConfigManager.java
@@ -34,9 +34,6 @@
         void onModuleConfigChanged(@ModuleType int moduleType, boolean isEnabled);
     }
 
-    static final long INVALID_TIMESTAMP = -1;
-    static final int INVALID_FRESHNESS_SCORE = -1;
-
     private final SharedPreferencesManager mSharedPreferencesManager;
     private final ObserverList<HomeModulesStateListener> mHomepageStateListeners;
 
@@ -174,64 +171,6 @@
         return ChromePreferenceKeys.HOME_MODULES_MODULE_TYPE.createKey(String.valueOf(moduleType));
     }
 
-    /** Returns the preference key of the module type. */
-    String getFreshnessCountPreferenceKey(@ModuleType int moduleType) {
-        assert 0 <= moduleType && moduleType < ModuleType.NUM_ENTRIES;
-
-        return ChromePreferenceKeys.HOME_MODULES_FRESHNESS_COUNT.createKey(
-                String.valueOf(moduleType));
-    }
-
-    /** Gets the freshness count of a module. */
-    public int getFreshnessCount(@ModuleType int moduleType) {
-        SharedPreferencesManager sharedPreferencesManager = ChromeSharedPreferences.getInstance();
-        String freshnessScoreKey = getFreshnessCountPreferenceKey(moduleType);
-        return sharedPreferencesManager.readInt(freshnessScoreKey, INVALID_FRESHNESS_SCORE);
-    }
-
-    /** Called to reset the freshness count when there is new information to show. */
-    public void resetFreshnessCount(@ModuleType int moduleType) {
-        SharedPreferencesManager sharedPreferencesManager = ChromeSharedPreferences.getInstance();
-        String freshnessScoreKey = getFreshnessCountPreferenceKey(moduleType);
-        sharedPreferencesManager.writeInt(freshnessScoreKey, INVALID_FRESHNESS_SCORE);
-    }
-
-    /**
-     * Called to increase the freshness score for the module. The count is increased from 0, not -1.
-     */
-    public void increaseFreshnessCount(@ModuleType int moduleType, int count) {
-        SharedPreferencesManager sharedPreferencesManager = ChromeSharedPreferences.getInstance();
-        String freshnessScoreKey = getFreshnessCountPreferenceKey(moduleType);
-        int score =
-                Math.max(
-                        0,
-                        sharedPreferencesManager.readInt(
-                                freshnessScoreKey, INVALID_FRESHNESS_SCORE));
-        sharedPreferencesManager.writeInt(freshnessScoreKey, (score + count));
-    }
-
-    /** Returns the preference key of the module type. */
-    String getFreshnessTimeStampPreferenceKey(@ModuleType int moduleType) {
-        assert 0 <= moduleType && moduleType < ModuleType.NUM_ENTRIES;
-
-        return ChromePreferenceKeys.HOME_MODULES_FRESHNESS_TIMESTAMP_MS.createKey(
-                String.valueOf(moduleType));
-    }
-
-    /** Sets the timestamp of last time a freshness score is logged for a module. */
-    public void setFreshnessScoreTimeStamp(@ModuleType int moduleType, long timeStampMs) {
-        SharedPreferencesManager sharedPreferencesManager = ChromeSharedPreferences.getInstance();
-        String freshnessScoreTimeStampKey = getFreshnessTimeStampPreferenceKey(moduleType);
-        sharedPreferencesManager.writeLong(freshnessScoreTimeStampKey, timeStampMs);
-    }
-
-    /** Gets the timestamp of last time a freshness score is logged for a module. */
-    public long getFreshnessScoreTimeStamp(@ModuleType int moduleType) {
-        SharedPreferencesManager sharedPreferencesManager = ChromeSharedPreferences.getInstance();
-        String freshnessScoreTimeStampKey = getFreshnessTimeStampPreferenceKey(moduleType);
-        return sharedPreferencesManager.readLong(freshnessScoreTimeStampKey, INVALID_TIMESTAMP);
-    }
-
     /** Sets a mocked instance for testing. */
     public static void setInstanceForTesting(HomeModulesConfigManager instance) {
         var oldValue = LazyHolder.sInstance;
@@ -239,18 +178,6 @@
         ResettersForTesting.register(() -> LazyHolder.sInstance = oldValue);
     }
 
-    public void setFreshnessCountForTesting(@ModuleType int moduleType, int count) {
-        SharedPreferencesManager sharedPreferencesManager = ChromeSharedPreferences.getInstance();
-        String freshnessScoreKey = getFreshnessCountPreferenceKey(moduleType);
-        sharedPreferencesManager.writeInt(freshnessScoreKey, count);
-    }
-
-    public void resetFreshnessTimeStampForTesting(@ModuleType int moduleType) {
-        SharedPreferencesManager sharedPreferencesManager = ChromeSharedPreferences.getInstance();
-        String freshnessScoreKey = getFreshnessTimeStampPreferenceKey(moduleType);
-        sharedPreferencesManager.removeKey(freshnessScoreKey);
-    }
-
     public void cleanupForTesting() {
         mModuleConfigCheckerMap.clear();
     }
diff --git a/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesMediator.java b/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesMediator.java
index 89b1b8d..386aa31 100644
--- a/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesMediator.java
+++ b/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesMediator.java
@@ -698,14 +698,14 @@
     private int getFreshnessScore(boolean useFreshnessScore, @ModuleType int moduleType) {
         if (!useFreshnessScore) return INVALID_FRESHNESS_SCORE;
 
-        long timeStamp = mHomeModulesConfigManager.getFreshnessScoreTimeStamp(moduleType);
-        if (timeStamp == HomeModulesConfigManager.INVALID_TIMESTAMP
+        long timeStamp = HomeModulesUtils.getFreshnessScoreTimeStamp(moduleType);
+        if (timeStamp == HomeModulesUtils.INVALID_TIMESTAMP
                 || SystemClock.elapsedRealtime() - timeStamp
                         >= HomeModulesMediator.FRESHNESS_THRESHOLD_MS) {
             return INVALID_FRESHNESS_SCORE;
         }
 
-        return mHomeModulesConfigManager.getFreshnessCount(moduleType);
+        return HomeModulesUtils.getFreshnessCount(moduleType);
     }
 
     @VisibleForTesting
diff --git a/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesMetricsUtils.java b/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesMetricsUtils.java
index 0b424d4..339f4f39 100644
--- a/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesMetricsUtils.java
+++ b/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesMetricsUtils.java
@@ -19,7 +19,7 @@
 import org.chromium.chrome.browser.util.BrowserUiUtils;
 import org.chromium.chrome.browser.util.BrowserUiUtils.ModuleTypeOnStartAndNtp;
 
-/** The utility class for magic stack. */
+/** The utility class for logging the magic stack's metrics. */
 public class HomeModulesMetricsUtils {
     @VisibleForTesting static final String HISTOGRAM_PREFIX = "MagicStack.Clank.NewTabPage";
     @VisibleForTesting static final String HISTOGRAM_OS_PREFIX = "MagicStack.Clank.";
diff --git a/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesUtils.java b/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesUtils.java
new file mode 100644
index 0000000..a758c4e2
--- /dev/null
+++ b/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesUtils.java
@@ -0,0 +1,94 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.magic_stack;
+
+import androidx.annotation.VisibleForTesting;
+
+import org.chromium.base.shared_preferences.SharedPreferencesManager;
+import org.chromium.chrome.browser.magic_stack.ModuleDelegate.ModuleType;
+import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
+import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
+
+/** Utility class for the magic stack. */
+public class HomeModulesUtils {
+    static final long INVALID_TIMESTAMP = -1;
+    static final int INVALID_FRESHNESS_SCORE = -1;
+
+    /** Returns the preference key of the module type. */
+    private static String getFreshnessCountPreferenceKey(@ModuleType int moduleType) {
+        assert 0 <= moduleType && moduleType < ModuleType.NUM_ENTRIES;
+
+        return ChromePreferenceKeys.HOME_MODULES_FRESHNESS_COUNT.createKey(
+                String.valueOf(moduleType));
+    }
+
+    /** Gets the freshness count of a module. */
+    @VisibleForTesting
+    static int getFreshnessCount(@ModuleType int moduleType) {
+        SharedPreferencesManager sharedPreferencesManager = ChromeSharedPreferences.getInstance();
+        String freshnessScoreKey = getFreshnessCountPreferenceKey(moduleType);
+        return sharedPreferencesManager.readInt(freshnessScoreKey, INVALID_FRESHNESS_SCORE);
+    }
+
+    /** Called to reset the freshness count when there is new information to show. */
+    @VisibleForTesting
+    static void resetFreshnessCount(@ModuleType int moduleType) {
+        SharedPreferencesManager sharedPreferencesManager = ChromeSharedPreferences.getInstance();
+        String freshnessScoreKey = getFreshnessCountPreferenceKey(moduleType);
+        sharedPreferencesManager.writeInt(freshnessScoreKey, INVALID_FRESHNESS_SCORE);
+    }
+
+    /**
+     * Called to increase the freshness score for the module. The count is increased from 0, not -1.
+     */
+    @VisibleForTesting
+    static void increaseFreshnessCount(@ModuleType int moduleType, int count) {
+        SharedPreferencesManager sharedPreferencesManager = ChromeSharedPreferences.getInstance();
+        String freshnessScoreKey = getFreshnessCountPreferenceKey(moduleType);
+        int score =
+                Math.max(
+                        0,
+                        sharedPreferencesManager.readInt(
+                                freshnessScoreKey, INVALID_FRESHNESS_SCORE));
+        sharedPreferencesManager.writeInt(freshnessScoreKey, (score + count));
+    }
+
+    /** Returns the preference key of the module type. */
+    @VisibleForTesting
+    static String getFreshnessTimeStampPreferenceKey(@ModuleType int moduleType) {
+        assert 0 <= moduleType && moduleType < ModuleType.NUM_ENTRIES;
+
+        return ChromePreferenceKeys.HOME_MODULES_FRESHNESS_TIMESTAMP_MS.createKey(
+                String.valueOf(moduleType));
+    }
+
+    /** Sets the timestamp of last time a freshness score is logged for a module. */
+    @VisibleForTesting
+    static void setFreshnessScoreTimeStamp(@ModuleType int moduleType, long timeStampMs) {
+        SharedPreferencesManager sharedPreferencesManager = ChromeSharedPreferences.getInstance();
+        String freshnessScoreTimeStampKey = getFreshnessTimeStampPreferenceKey(moduleType);
+        sharedPreferencesManager.writeLong(freshnessScoreTimeStampKey, timeStampMs);
+    }
+
+    /** Gets the timestamp of last time a freshness score is logged for a module. */
+    @VisibleForTesting
+    static long getFreshnessScoreTimeStamp(@ModuleType int moduleType) {
+        SharedPreferencesManager sharedPreferencesManager = ChromeSharedPreferences.getInstance();
+        String freshnessScoreTimeStampKey = getFreshnessTimeStampPreferenceKey(moduleType);
+        return sharedPreferencesManager.readLong(freshnessScoreTimeStampKey, INVALID_TIMESTAMP);
+    }
+
+    public static void setFreshnessCountForTesting(@ModuleType int moduleType, int count) {
+        SharedPreferencesManager sharedPreferencesManager = ChromeSharedPreferences.getInstance();
+        String freshnessScoreKey = getFreshnessCountPreferenceKey(moduleType);
+        sharedPreferencesManager.writeInt(freshnessScoreKey, count);
+    }
+
+    public static void resetFreshnessTimeStampForTesting(@ModuleType int moduleType) {
+        SharedPreferencesManager sharedPreferencesManager = ChromeSharedPreferences.getInstance();
+        String freshnessScoreKey = getFreshnessTimeStampPreferenceKey(moduleType);
+        sharedPreferencesManager.removeKey(freshnessScoreKey);
+    }
+}
diff --git a/chrome/browser/magic_stack/android/junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesConfigManagerUnitTest.java b/chrome/browser/magic_stack/android/junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesConfigManagerUnitTest.java
index 3d31357..1bcb2ab 100644
--- a/chrome/browser/magic_stack/android/junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesConfigManagerUnitTest.java
+++ b/chrome/browser/magic_stack/android/junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesConfigManagerUnitTest.java
@@ -15,12 +15,13 @@
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
-import org.chromium.base.shared_preferences.SharedPreferencesManager;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.browser.magic_stack.HomeModulesConfigManager.HomeModulesStateListener;
 import org.chromium.chrome.browser.magic_stack.ModuleDelegate.ModuleType;
@@ -34,12 +35,13 @@
 /** Unit tests for {@link HomeModulesConfigManager}. */
 @RunWith(BaseRobolectricTestRunner.class)
 public class HomeModulesConfigManagerUnitTest {
+    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     private List<ModuleConfigChecker> mModuleConfigCheckerList = new ArrayList<>();
     private HomeModulesConfigManager mHomeModulesConfigManager;
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mHomeModulesConfigManager = HomeModulesConfigManager.getInstance();
     }
 
@@ -142,38 +144,6 @@
                 mHomeModulesConfigManager.getSettingsPreferenceKey(ModuleType.PRICE_CHANGE));
     }
 
-    @Test
-    public void testFreshnessCount() {
-        @ModuleType int moduleType = ModuleType.PRICE_CHANGE;
-        String moduleFreshnessCountPreferenceKey =
-                ChromePreferenceKeys.HOME_MODULES_FRESHNESS_COUNT.createKey(
-                        String.valueOf(moduleType));
-        SharedPreferencesManager sharedPreferencesManager = ChromeSharedPreferences.getInstance();
-
-        assertFalse(sharedPreferencesManager.contains(moduleFreshnessCountPreferenceKey));
-        assertEquals(
-                HomeModulesMediator.INVALID_FRESHNESS_SCORE,
-                sharedPreferencesManager.readInt(
-                        moduleFreshnessCountPreferenceKey,
-                        HomeModulesMediator.INVALID_FRESHNESS_SCORE));
-
-        int count = 5;
-        mHomeModulesConfigManager.increaseFreshnessCount(moduleType, count);
-        assertEquals(
-                count,
-                sharedPreferencesManager.readInt(
-                        moduleFreshnessCountPreferenceKey,
-                        HomeModulesMediator.INVALID_FRESHNESS_SCORE));
-
-        mHomeModulesConfigManager.resetFreshnessCount(moduleType);
-        assertTrue(sharedPreferencesManager.contains(moduleFreshnessCountPreferenceKey));
-        assertEquals(
-                HomeModulesMediator.INVALID_FRESHNESS_SCORE,
-                sharedPreferencesManager.readInt(
-                        moduleFreshnessCountPreferenceKey,
-                        HomeModulesMediator.INVALID_FRESHNESS_SCORE));
-    }
-
     private void registerModuleConfigChecker(int size) {
         size = Math.min(size, ModuleType.NUM_ENTRIES);
         for (int i = 0; i < size; i++) {
diff --git a/chrome/browser/magic_stack/android/junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesMediatorUnitTest.java b/chrome/browser/magic_stack/android/junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesMediatorUnitTest.java
index 378d1075..b14df2c67 100644
--- a/chrome/browser/magic_stack/android/junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesMediatorUnitTest.java
+++ b/chrome/browser/magic_stack/android/junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesMediatorUnitTest.java
@@ -102,8 +102,8 @@
     @After
     public void tearDown() {
         for (int i = 0; i < ModuleType.NUM_ENTRIES; i++) {
-            mHomeModulesConfigManager.resetFreshnessCount(i);
-            mHomeModulesConfigManager.resetFreshnessTimeStampForTesting(i);
+            HomeModulesUtils.resetFreshnessCount(i);
+            HomeModulesUtils.resetFreshnessTimeStampForTesting(i);
         }
         mHomeModulesConfigManager.cleanupForTesting();
     }
@@ -701,8 +701,8 @@
 
         // Verifies that createInputContext() returns an empty one with invalid score value if the
         // freshness score is invalid or not added.
-        mHomeModulesConfigManager.setFreshnessCountForTesting(
-                moduleType, HomeModulesConfigManager.INVALID_FRESHNESS_SCORE);
+        HomeModulesUtils.setFreshnessCountForTesting(
+                moduleType, HomeModulesUtils.INVALID_FRESHNESS_SCORE);
         InputContext inputContext = mMediator.createInputContext();
         verifyEmptyInputContext(inputContext);
     }
@@ -724,23 +724,23 @@
         int expectedScore = 100;
         long scoreLoggedTime =
                 SystemClock.elapsedRealtime() - HomeModulesMediator.FRESHNESS_THRESHOLD_MS - 10;
-        mHomeModulesConfigManager.setFreshnessScoreTimeStamp(moduleType, scoreLoggedTime);
-        mHomeModulesConfigManager.setFreshnessCountForTesting(moduleType, expectedScore);
+        HomeModulesUtils.setFreshnessScoreTimeStamp(moduleType, scoreLoggedTime);
+        HomeModulesUtils.setFreshnessCountForTesting(moduleType, expectedScore);
         InputContext inputContext = mMediator.createInputContext();
         verifyEmptyInputContext(inputContext);
 
         // Verifies that the freshness score will be used if the logging time is less than the
         // threshold.
         scoreLoggedTime = SystemClock.elapsedRealtime() - 10;
-        mHomeModulesConfigManager.setFreshnessScoreTimeStamp(moduleType, scoreLoggedTime);
-        mHomeModulesConfigManager.setFreshnessCountForTesting(moduleType, expectedScore);
+        HomeModulesUtils.setFreshnessScoreTimeStamp(moduleType, scoreLoggedTime);
+        HomeModulesUtils.setFreshnessCountForTesting(moduleType, expectedScore);
         int[] scores = new int[] {-1, expectedScore, -1, -1, -1};
         inputContext = mMediator.createInputContext();
         verifyInputContext(inputContext, scores);
 
         // Verifies that if the freshness score becomes invalid or removed, there isn't any entry
         // added to the InputContext.
-        mHomeModulesConfigManager.setFreshnessCountForTesting(moduleType, INVALID_FRESHNESS_SCORE);
+        HomeModulesUtils.setFreshnessCountForTesting(moduleType, INVALID_FRESHNESS_SCORE);
         inputContext = mMediator.createInputContext();
         verifyEmptyInputContext(inputContext);
     }
diff --git a/chrome/browser/magic_stack/android/junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesUtilsUnitTest.java b/chrome/browser/magic_stack/android/junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesUtilsUnitTest.java
new file mode 100644
index 0000000..df4de571
--- /dev/null
+++ b/chrome/browser/magic_stack/android/junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesUtilsUnitTest.java
@@ -0,0 +1,59 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.magic_stack;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.shared_preferences.SharedPreferencesManager;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.magic_stack.ModuleDelegate.ModuleType;
+import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
+import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
+
+/** Unit tests for {@link HomeModulesUtils}. */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class HomeModulesUtilsUnitTest {
+    @Test
+    @SmallTest
+    public void testFreshnessCount() {
+        @ModuleType int moduleType = ModuleType.PRICE_CHANGE;
+        String moduleFreshnessCountPreferenceKey =
+                ChromePreferenceKeys.HOME_MODULES_FRESHNESS_COUNT.createKey(
+                        String.valueOf(moduleType));
+        SharedPreferencesManager sharedPreferencesManager = ChromeSharedPreferences.getInstance();
+
+        assertFalse(sharedPreferencesManager.contains(moduleFreshnessCountPreferenceKey));
+        assertEquals(
+                HomeModulesMediator.INVALID_FRESHNESS_SCORE,
+                sharedPreferencesManager.readInt(
+                        moduleFreshnessCountPreferenceKey,
+                        HomeModulesMediator.INVALID_FRESHNESS_SCORE));
+
+        int count = 5;
+        HomeModulesUtils.increaseFreshnessCount(moduleType, count);
+        assertEquals(
+                count,
+                sharedPreferencesManager.readInt(
+                        moduleFreshnessCountPreferenceKey,
+                        HomeModulesMediator.INVALID_FRESHNESS_SCORE));
+
+        HomeModulesUtils.resetFreshnessCount(moduleType);
+        assertTrue(sharedPreferencesManager.contains(moduleFreshnessCountPreferenceKey));
+        assertEquals(
+                HomeModulesMediator.INVALID_FRESHNESS_SCORE,
+                sharedPreferencesManager.readInt(
+                        moduleFreshnessCountPreferenceKey,
+                        HomeModulesMediator.INVALID_FRESHNESS_SCORE));
+    }
+}
diff --git a/chrome/browser/media/router/test/provider_test_helpers.cc b/chrome/browser/media/router/test/provider_test_helpers.cc
index cb3d6d7..ab959da 100644
--- a/chrome/browser/media/router/test/provider_test_helpers.cc
+++ b/chrome/browser/media/router/test/provider_test_helpers.cc
@@ -170,7 +170,6 @@
   MediaSink sink{CreateCastSink(unique_id, friendly_name)};
   CastSinkExtraData extra_data;
   extra_data.ip_endpoint = ip_endpoint;
-  extra_data.port = ip_endpoint.port();
   extra_data.model_name = base::StringPrintf("model name %d", num);
   extra_data.cast_channel_id = num;
   extra_data.capabilities = {cast_channel::CastDeviceCapability::kAudioOut,
diff --git a/chrome/browser/password_manager/android/save_update_password_message_delegate.cc b/chrome/browser/password_manager/android/save_update_password_message_delegate.cc
index 271ed262..ffc426d 100644
--- a/chrome/browser/password_manager/android/save_update_password_message_delegate.cc
+++ b/chrome/browser/password_manager/android/save_update_password_message_delegate.cc
@@ -340,9 +340,6 @@
 unsigned int SaveUpdatePasswordMessageDelegate::GetDisplayUsernames(
     std::vector<std::u16string>* usernames) {
   unsigned int selected_username_index = 0;
-  // TODO(crbug.com/40675711): Fix the update logic to use all best matches,
-  // rather than current_forms which is best_matches without PSL-matched
-  // credentials.
   const std::vector<std::unique_ptr<password_manager::PasswordForm>>&
       password_forms = passwords_state_.GetCurrentForms();
   const std::u16string& default_username =
@@ -460,9 +457,6 @@
 }
 
 bool SaveUpdatePasswordMessageDelegate::HasMultipleCredentialsStored() {
-  // TODO(crbug.com/40675711): Fix the update logic to use all best matches,
-  // rather than current_forms which is best_matches without PSL-matched
-  // credentials.
   const std::vector<std::unique_ptr<password_manager::PasswordForm>>&
       password_forms = passwords_state_.GetCurrentForms();
   return password_forms.size() > 1;
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc
index 1a40464..01b67ca 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client.cc
+++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -769,9 +769,12 @@
     ResetSubmissionTrackingAfterTouchToFill();
   }
 #else
-  if (auto* delegate = PasswordChangeServiceFactory::GetForProfile(profile_)
-                           ->GetPasswordChangeDelegate(web_contents())) {
-    delegate->SuccessfulSubmissionDetected(web_contents());
+  ChromePasswordChangeService* password_change_service =
+      PasswordChangeServiceFactory::GetForProfile(profile_);
+  if (password_change_service &&
+      password_change_service->GetPasswordChangeDelegate(web_contents())) {
+    password_change_service->GetPasswordChangeDelegate(web_contents())
+        ->SuccessfulSubmissionDetected(web_contents());
   }
 #endif  // BUILDFLAG(IS_ANDROID)
 }
diff --git a/chrome/browser/password_manager/multi_profile_credentials_filter.cc b/chrome/browser/password_manager/multi_profile_credentials_filter.cc
index e6b9d385..54d41068 100644
--- a/chrome/browser/password_manager/multi_profile_credentials_filter.cc
+++ b/chrome/browser/password_manager/multi_profile_credentials_filter.cc
@@ -8,7 +8,7 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/signin/dice_web_signin_interceptor.h"
-#include "components/autofill/core/browser/validation.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/password_manager/core/browser/password_sync_util.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 
diff --git a/chrome/browser/payments/chrome_payment_request_delegate.cc b/chrome/browser/payments/chrome_payment_request_delegate.cc
index 6d1da4b..429c48d3 100644
--- a/chrome/browser/payments/chrome_payment_request_delegate.cc
+++ b/chrome/browser/payments/chrome_payment_request_delegate.cc
@@ -27,7 +27,7 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/views/payments/payment_request_dialog_view.h"
-#include "components/autofill/core/browser/address_normalizer_impl.h"
+#include "components/autofill/core/browser/data_quality/addresses/address_normalizer_impl.h"
 #include "components/autofill/core/browser/geo/region_data_loader_impl.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/ui/region_combobox_model.h"
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index 745d07bc..6539c2eb 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -117,6 +117,7 @@
 #include "ui/base/clipboard/test/test_clipboard.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/rect.h"
+#include "ui/native_theme/native_theme_features.h"
 #include "url/gurl.h"
 
 #if defined(TOOLKIT_VIEWS) && !BUILDFLAG(IS_MAC)
@@ -1406,7 +1407,7 @@
                                        /*command=*/false);
   ASSERT_NO_FATAL_FAILURE(scroll_waiter.Wait());
 #if BUILDFLAG(IS_WIN)
-  constexpr int kFirstPosition = 915;
+  const int kFirstPosition = ui::IsFluentScrollbarEnabled() ? 917 : 915;
 #elif BUILDFLAG(IS_CHROMEOS)
   constexpr int kFirstPosition = 937;
 #else
@@ -1425,7 +1426,7 @@
                                        /*command=*/false);
   ASSERT_NO_FATAL_FAILURE(scroll_waiter.Wait());
 #if BUILDFLAG(IS_WIN)
-  constexpr int kSecondPosition = 1831;
+  const int kSecondPosition = ui::IsFluentScrollbarEnabled() ? 1834 : 1831;
 #elif BUILDFLAG(IS_CHROMEOS)
   constexpr int kSecondPosition = 1875;
 #else
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index 419bf206..1f65b49 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -106,6 +106,7 @@
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/views/side_panel/read_anything/read_anything_side_panel_controller_utils.h"
 #include "chrome/browser/ui/web_applications/app_browser_controller.h"
+#include "chrome/browser/ui/webauthn/context_menu_helper.h"
 #include "chrome/browser/ui/webui/history/foreign_session_handler.h"
 #include "chrome/browser/user_education/user_education_service.h"
 #include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h"
@@ -530,13 +531,14 @@
        {IDC_CONTENT_CONTEXT_AUTOFILL_PREDICTION_IMPROVEMENTS, 151},
        {IDC_CONTENT_CONTEXT_AUTOFILL_FALLBACK_PASSWORDS_USE_PASSKEY_FROM_ANOTHER_DEVICE,
         152},
+       {IDC_CONTENT_CONTEXT_USE_PASSKEY_FROM_ANOTHER_DEVICE, 153},
        // To add new items:
        //   - Add one more line above this comment block, using the UMA value
        //     from the line below this comment block.
        //   - Increment the UMA value in that latter line.
        //   - Add the new item to the RenderViewContextMenuItem enum in
        //     tools/metrics/histograms/enums.xml.
-       {0, 153}});
+       {0, 154}});
 
   // These UMA values are for the ContextMenuOptionDesktop enum, used for
   // the ContextMenu.SelectedOptionDesktop histograms.
@@ -2670,12 +2672,10 @@
   password_manager::ContentPasswordManagerDriver* driver =
       password_manager::ContentPasswordManagerDriver::GetForRenderFrameHost(
           GetRenderFrameHost());
-
-  if (!driver || !driver->IsPasswordFieldForPasswordManager(
-                     autofill::FieldRendererId(params_.field_renderer_id),
-                     params_.form_control_type)) {
-    return;
-  }
+  const bool is_pwm_field =
+      driver && driver->IsPasswordFieldForPasswordManager(
+                    autofill::FieldRendererId(params_.field_renderer_id),
+                    params_.form_control_type);
 
   if (base::FeatureList::IsEnabled(
           password_manager::features::kPasswordManualFallbackAvailable)) {
@@ -2686,16 +2686,31 @@
 
   // Don't show the item for guest or incognito profiles and also when the
   // automatic generation feature is disabled.
-  if (password_manager_util::ManualPasswordGenerationEnabled(driver)) {
+  if (is_pwm_field &&
+      password_manager_util::ManualPasswordGenerationEnabled(driver)) {
     menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_GENERATEPASSWORD,
                                     IDS_CONTENT_CONTEXT_GENERATEPASSWORD);
     add_separator = true;
   }
-  if (password_manager_util::ShowAllSavedPasswordsContextMenuEnabled(driver)) {
+  if (is_pwm_field &&
+      password_manager_util::ShowAllSavedPasswordsContextMenuEnabled(driver)) {
     menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SHOWALLSAVEDPASSWORDS,
                                     IDS_AUTOFILL_SHOW_ALL_SAVED_FALLBACK);
     add_separator = true;
   }
+  const bool add_passkey_from_another_device_option =
+      webauthn::IsPasskeyFromAnotherDeviceContextMenuEnabled(
+          GetRenderFrameHost(), params_.form_renderer_id,
+          params_.field_renderer_id) &&
+      base::FeatureList::IsEnabled(
+          password_manager::features::
+              kWebAuthnUsePasskeyFromAnotherDeviceInContextMenu);
+  if (add_passkey_from_another_device_option) {
+    menu_model_.AddItemWithStringId(
+        IDC_CONTENT_CONTEXT_USE_PASSKEY_FROM_ANOTHER_DEVICE,
+        IDS_CONTENT_CONTEXT_AUTOFILL_FALLBACK_PASSWORDS_USE_PASSKEY_FROM_ANOTHER_DEVICE);
+    add_separator = true;
+  }
 
   if (add_separator) {
     menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
@@ -3083,6 +3098,7 @@
     case IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_SETTINGS:
     case IDC_CONTENT_CONTEXT_GENERATEPASSWORD:
     case IDC_CONTENT_CONTEXT_SHOWALLSAVEDPASSWORDS:
+    case IDC_CONTENT_CONTEXT_USE_PASSKEY_FROM_ANOTHER_DEVICE:
       return true;
 
     case IDC_ROUTE_MEDIA:
@@ -3568,6 +3584,10 @@
           GetBrowser(),
           password_manager::ManagePasswordsReferrer::kPasswordContextMenu);
       break;
+    case IDC_CONTENT_CONTEXT_USE_PASSKEY_FROM_ANOTHER_DEVICE:
+      webauthn::OnPasskeyFromAnotherDeviceContextMenuItemSelected(
+          GetRenderFrameHost());
+      break;
 
     case IDC_CONTENT_CONTEXT_PICTUREINPICTURE:
       ExecPictureInPicture();
diff --git a/chrome/browser/resource_coordinator/decision_details.cc b/chrome/browser/resource_coordinator/decision_details.cc
index e259b6b..624ebfa 100644
--- a/chrome/browser/resource_coordinator/decision_details.cc
+++ b/chrome/browser/resource_coordinator/decision_details.cc
@@ -9,7 +9,7 @@
 
 #include "chrome/browser/resource_coordinator/decision_details.h"
 
-#include "services/metrics/public/cpp/ukm_builders.h"
+#include "base/check.h"
 
 namespace resource_coordinator {
 
@@ -58,112 +58,6 @@
                   static_cast<size_t>(DecisionSuccessReason::MAX),
               "kDecisionSuccessReasonStrings not up to date with enum");
 
-void PopulateSuccessReason(
-    DecisionSuccessReason success_reason,
-    ukm::builders::TabManager_LifecycleStateChange* ukm) {
-  switch (success_reason) {
-    case DecisionSuccessReason::INVALID:
-      break;
-    case DecisionSuccessReason::ORIGIN_TRIAL_OPT_IN:
-      ukm->SetSuccessOriginTrialOptIn(1);
-      break;
-    case DecisionSuccessReason::GLOBAL_ALLOWLIST:
-      ukm->SetSuccessGlobalAllowlist(1);
-      break;
-    case DecisionSuccessReason::HEURISTIC_OBSERVED_TO_BE_SAFE:
-      ukm->SetSuccessHeuristic(1);
-      break;
-    case DecisionSuccessReason::MAX:
-      NOTREACHED();
-  }
-}
-
-void PopulateFailureReason(
-    DecisionFailureReason failure_reason,
-    ukm::builders::TabManager_LifecycleStateChange* ukm) {
-  switch (failure_reason) {
-    case DecisionFailureReason::INVALID:
-      break;
-    case DecisionFailureReason::LIFECYCLES_ENTERPRISE_POLICY_OPT_OUT:
-      ukm->SetFailureLifecyclesEnterprisePolicyOptOut(1);
-      break;
-    case DecisionFailureReason::ORIGIN_TRIAL_OPT_OUT:
-      ukm->SetFailureOriginTrialOptOut(1);
-      break;
-    case DecisionFailureReason::GLOBAL_DISALLOWLIST:
-      ukm->SetFailureGlobalDisallowlist(1);
-      break;
-    case DecisionFailureReason::HEURISTIC_AUDIO:
-      ukm->SetFailureHeuristicAudio(1);
-      break;
-    case DecisionFailureReason::HEURISTIC_FAVICON:
-      ukm->SetFailureHeuristicFavicon(1);
-      break;
-    case DecisionFailureReason::HEURISTIC_INSUFFICIENT_OBSERVATION:
-      ukm->SetFailureHeuristicInsufficientObservation(1);
-      break;
-    case DecisionFailureReason::HEURISTIC_TITLE:
-      ukm->SetFailureHeuristicTitle(1);
-      break;
-    case DecisionFailureReason::LIVE_STATE_CAPTURING:
-      ukm->SetFailureLiveStateCapturing(1);
-      break;
-    case DecisionFailureReason::LIVE_STATE_EXTENSION_DISALLOWED:
-      ukm->SetFailureLiveStateExtensionDisallowed(1);
-      break;
-    case DecisionFailureReason::LIVE_STATE_FORM_ENTRY:
-      ukm->SetFailureLiveStateFormEntry(1);
-      break;
-    case DecisionFailureReason::LIVE_STATE_IS_PDF:
-      ukm->SetFailureLiveStateIsPDF(1);
-      break;
-    case DecisionFailureReason::LIVE_STATE_MIRRORING:
-      ukm->SetFailureLiveStateMirroring(1);
-      break;
-    case DecisionFailureReason::LIVE_STATE_PLAYING_AUDIO:
-      ukm->SetFailureLiveStatePlayingAudio(1);
-      break;
-    case DecisionFailureReason::LIVE_STATE_USING_WEB_SOCKETS:
-      ukm->SetFailureLiveStateUsingWebSockets(1);
-      break;
-    case DecisionFailureReason::LIVE_STATE_USING_WEB_USB:
-      ukm->SetFailureLiveStateUsingWebUSB(1);
-      break;
-    case DecisionFailureReason::LIVE_STATE_VISIBLE:
-      ukm->SetFailureLiveStateVisible(1);
-      break;
-    case DecisionFailureReason::LIVE_STATE_DEVTOOLS_OPEN:
-      ukm->SetFailureLiveStateDevToolsOpen(1);
-      break;
-    case DecisionFailureReason::LIVE_STATE_DESKTOP_CAPTURE:
-      ukm->SetFailureLiveStateDesktopCapture(1);
-      break;
-    case DecisionFailureReason::LIVE_STATE_SHARING_BROWSING_INSTANCE:
-      ukm->SetFailureLiveStateSharingBrowsingInstance(1);
-      break;
-    case DecisionFailureReason::LIVE_STATE_USING_BLUETOOTH:
-      ukm->SetFailureLiveStateUsingBluetooth(1);
-      break;
-    case DecisionFailureReason::LIVE_STATE_USING_WEBLOCK:
-      ukm->SetFailureLiveStateUsingWebLock(1);
-      break;
-    case DecisionFailureReason::LIVE_STATE_USING_INDEXEDDB_LOCK:
-      ukm->SetFailureLiveStateUsingIndexedDBLock(1);
-      break;
-    case DecisionFailureReason::LIVE_STATE_HAS_NOTIFICATIONS_PERMISSION:
-      ukm->SetFailureLiveStateHasNotificationsPermission(1);
-      break;
-    case DecisionFailureReason::LIVE_WEB_APP:
-      ukm->SetFailureLiveWebApp(1);
-      break;
-    case DecisionFailureReason::LIVE_PICTURE_IN_PICTURE:
-      ukm->SetFailureLivePictureInPicture(1);
-      break;
-    case DecisionFailureReason::MAX:
-      NOTREACHED();
-  }
-}
-
 }  // namespace
 
 const char* ToString(DecisionFailureReason failure_reason) {
@@ -293,25 +187,6 @@
   return reasons_.front().failure_reason();
 }
 
-void DecisionDetails::Populate(
-    ukm::builders::TabManager_LifecycleStateChange* ukm) const {
-  DCHECK(!reasons_.empty());
-  bool positive = IsPositive();
-  ukm->SetOutcome(positive);
-  for (const auto& reason : reasons_) {
-    // Stop adding reasons once all of the initial reasons of the same type
-    // have been added.
-    bool success = reason.IsSuccess();
-    if (success != positive)
-      break;
-    if (success) {
-      PopulateSuccessReason(reason.success_reason(), ukm);
-    } else {
-      PopulateFailureReason(reason.failure_reason(), ukm);
-    }
-  }
-}
-
 std::vector<std::string> DecisionDetails::GetFailureReasonStrings() const {
   std::vector<std::string> reasons;
   for (const auto& reason : reasons_) {
diff --git a/chrome/browser/resource_coordinator/decision_details.h b/chrome/browser/resource_coordinator/decision_details.h
index 8a98dabf..7f5e4e7 100644
--- a/chrome/browser/resource_coordinator/decision_details.h
+++ b/chrome/browser/resource_coordinator/decision_details.h
@@ -8,19 +8,12 @@
 #include <string>
 #include <vector>
 
-namespace ukm {
-namespace builders {
-class TabManager_LifecycleStateChange;
-}
-}  // namespace ukm
-
 namespace resource_coordinator {
 
 // An enumeration of reasons why a particular intervention or lifecycle state
 // changes can be denied. This is a superset of all failure reasons that can
 // apply for any particular intervention. New reasons can freely be added to
-// this enum as necessary, but UKM plumbing and string conversion needs to be
-// maintained as well.
+// this enum as necessary, but string conversion needs to be maintained as well.
 enum class DecisionFailureReason : int32_t {
   // An invalid failure reason. This must remain first.
   INVALID = -1,
@@ -116,9 +109,8 @@
 // Describes the detailed reasons why a particular intervention decision was
 // made. This is populated by the various policy bits of policy logic that
 // decide whether a particular intervention or lifecycle state transition can be
-// performed. It can populate various related UKM builders and also be converted
-// to a collection of user readable strings for the purposes of displaying in
-// in web UI.
+// performed. It can be converted to a collection of user readable strings for
+// the purposes of displaying in in web UI.
 //
 // A decision can contain multiple reasons for success or failure, and policy
 // allows some success reasons to override some failure reasons and vice versa.
@@ -209,10 +201,6 @@
   // Returns whether or not the chain of reasons has toggled.
   bool toggled() const { return toggled_; }
 
-  // Populates the provided "TabManager.LifecycleStateChange" UKM builder with
-  // information from this object.
-  void Populate(ukm::builders::TabManager_LifecycleStateChange* ukm) const;
-
   // Returns a collection of failure reason strings, from most important failure
   // reason to least important. This is empty if the outcome is positive, and
   // will only be populated with failure reasons that are not overridden by any
diff --git a/chrome/browser/resource_coordinator/decision_details_unittest.cc b/chrome/browser/resource_coordinator/decision_details_unittest.cc
index 88c3ace..3d6a6ff 100644
--- a/chrome/browser/resource_coordinator/decision_details_unittest.cc
+++ b/chrome/browser/resource_coordinator/decision_details_unittest.cc
@@ -4,10 +4,6 @@
 
 #include "chrome/browser/resource_coordinator/decision_details.h"
 
-#include "components/ukm/test_ukm_recorder.h"
-#include "services/metrics/public/cpp/ukm_builders.h"
-#include "services/metrics/public/cpp/ukm_source_id.h"
-#include "services/metrics/public/mojom/ukm_interface.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace resource_coordinator {
@@ -177,94 +173,4 @@
   EXPECT_TRUE(details.toggled());
 }
 
-TEST(DecisionDetailsTest, TabManagerLifecycleStateChangeUkm) {
-  DecisionDetails details;
-
-  // Make details with every possible failure reason except one, followed by a
-  // single success reason.
-  EXPECT_FALSE(details.AddReason(
-      DecisionFailureReason::LIFECYCLES_ENTERPRISE_POLICY_OPT_OUT));
-  EXPECT_FALSE(details.AddReason(DecisionFailureReason::ORIGIN_TRIAL_OPT_OUT));
-  EXPECT_FALSE(details.AddReason(DecisionFailureReason::GLOBAL_DISALLOWLIST));
-  EXPECT_FALSE(details.AddReason(DecisionFailureReason::HEURISTIC_AUDIO));
-  EXPECT_FALSE(details.AddReason(DecisionFailureReason::HEURISTIC_FAVICON));
-  EXPECT_FALSE(details.AddReason(
-      DecisionFailureReason::HEURISTIC_INSUFFICIENT_OBSERVATION));
-  EXPECT_FALSE(details.AddReason(DecisionFailureReason::HEURISTIC_TITLE));
-  EXPECT_FALSE(details.AddReason(DecisionFailureReason::LIVE_STATE_CAPTURING));
-  // Skipping LIVE_STATE_EXTENSION_DISALLOWED here.
-  EXPECT_FALSE(details.AddReason(DecisionFailureReason::LIVE_STATE_FORM_ENTRY));
-  EXPECT_FALSE(details.AddReason(DecisionFailureReason::LIVE_STATE_IS_PDF));
-  EXPECT_FALSE(details.AddReason(DecisionFailureReason::LIVE_STATE_MIRRORING));
-  EXPECT_FALSE(
-      details.AddReason(DecisionFailureReason::LIVE_STATE_PLAYING_AUDIO));
-  EXPECT_FALSE(
-      details.AddReason(DecisionFailureReason::LIVE_STATE_USING_WEB_SOCKETS));
-  EXPECT_FALSE(
-      details.AddReason(DecisionFailureReason::LIVE_STATE_USING_WEB_USB));
-  EXPECT_FALSE(details.AddReason(DecisionFailureReason::LIVE_STATE_VISIBLE));
-  EXPECT_FALSE(
-      details.AddReason(DecisionFailureReason::LIVE_STATE_DEVTOOLS_OPEN));
-  EXPECT_FALSE(
-      details.AddReason(DecisionFailureReason::LIVE_STATE_DESKTOP_CAPTURE));
-  EXPECT_FALSE(
-      details.AddReason(DecisionFailureReason::LIVE_STATE_USING_BLUETOOTH));
-  EXPECT_TRUE(details.AddReason(DecisionSuccessReason::ORIGIN_TRIAL_OPT_IN));
-
-  // Dump the data to a UKM builder.
-  ukm::TestUkmRecorder ukm_recorder;
-  ukm::SourceId ukm_source_id = ukm::UkmRecorder::GetNewSourceID();
-  ukm::builders::TabManager_LifecycleStateChange ukm_builder(ukm_source_id);
-  details.Populate(&ukm_builder);
-  ukm_builder.Record(&ukm_recorder);
-
-  // Validate the output.
-  EXPECT_EQ(1u, ukm_recorder.entries_count());
-  auto entries = ukm_recorder.GetEntriesByName(ukm_builder.kEntryName);
-  EXPECT_EQ(1u, entries.size());
-  auto* entry = entries[0].get();
-  ukm_recorder.ExpectEntryMetric(
-      entry, ukm_builder.kFailureLifecyclesEnterprisePolicyOptOutName, 1);
-  ukm_recorder.ExpectEntryMetric(entry,
-                                 ukm_builder.kFailureOriginTrialOptOutName, 1);
-  ukm_recorder.ExpectEntryMetric(entry,
-                                 ukm_builder.kFailureGlobalDisallowlistName, 1);
-  ukm_recorder.ExpectEntryMetric(entry, ukm_builder.kFailureHeuristicAudioName,
-                                 1);
-  ukm_recorder.ExpectEntryMetric(entry,
-                                 ukm_builder.kFailureHeuristicFaviconName, 1);
-  ukm_recorder.ExpectEntryMetric(
-      entry, ukm_builder.kFailureHeuristicInsufficientObservationName, 1);
-  ukm_recorder.ExpectEntryMetric(entry, ukm_builder.kFailureHeuristicTitleName,
-                                 1);
-  ukm_recorder.ExpectEntryMetric(entry,
-                                 ukm_builder.kFailureLiveStateCapturingName, 1);
-  EXPECT_FALSE(ukm_recorder.EntryHasMetric(
-      entry, ukm_builder.kFailureLiveStateExtensionDisallowedName));
-  ukm_recorder.ExpectEntryMetric(entry,
-                                 ukm_builder.kFailureLiveStateFormEntryName, 1);
-  ukm_recorder.ExpectEntryMetric(entry, ukm_builder.kFailureLiveStateIsPDFName,
-                                 1);
-  ukm_recorder.ExpectEntryMetric(entry,
-                                 ukm_builder.kFailureLiveStateMirroringName, 1);
-  ukm_recorder.ExpectEntryMetric(
-      entry, ukm_builder.kFailureLiveStatePlayingAudioName, 1);
-  ukm_recorder.ExpectEntryMetric(
-      entry, ukm_builder.kFailureLiveStateUsingWebSocketsName, 1);
-  ukm_recorder.ExpectEntryMetric(
-      entry, ukm_builder.kFailureLiveStateUsingWebUSBName, 1);
-  ukm_recorder.ExpectEntryMetric(entry,
-                                 ukm_builder.kFailureLiveStateVisibleName, 1);
-  ukm_recorder.ExpectEntryMetric(
-      entry, ukm_builder.kFailureLiveStateDevToolsOpenName, 1);
-  ukm_recorder.ExpectEntryMetric(
-      entry, ukm_builder.kFailureLiveStateDesktopCaptureName, 1);
-  ukm_recorder.ExpectEntryMetric(
-      entry, ukm_builder.kFailureLiveStateUsingBluetoothName, 1);
-  EXPECT_FALSE(ukm_recorder.EntryHasMetric(
-      entry, ukm_builder.kSuccessOriginTrialOptInName));
-  EXPECT_FALSE(ukm_recorder.EntryHasMetric(
-      entry, ukm_builder.kSuccessGlobalAllowlistName));
-}
-
 }  // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/lifecycle_unit.h b/chrome/browser/resource_coordinator/lifecycle_unit.h
index 6337953d..9ff2d9a 100644
--- a/chrome/browser/resource_coordinator/lifecycle_unit.h
+++ b/chrome/browser/resource_coordinator/lifecycle_unit.h
@@ -16,7 +16,6 @@
 #include "chrome/browser/resource_coordinator/decision_details.h"
 #include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom-forward.h"
 #include "content/public/browser/visibility.h"
-#include "services/metrics/public/cpp/ukm_source_id.h"
 
 namespace resource_coordinator {
 
@@ -158,10 +157,6 @@
   // Adds/removes an observer to this LifecycleUnit.
   virtual void AddObserver(LifecycleUnitObserver* observer) = 0;
   virtual void RemoveObserver(LifecycleUnitObserver* observer) = 0;
-
-  // Returns the UKM source ID associated with this LifecycleUnit, if it has
-  // one.
-  virtual ukm::SourceId GetUkmSourceId() const = 0;
 };
 
 using LifecycleUnitSet =
diff --git a/chrome/browser/resource_coordinator/lifecycle_unit_base.cc b/chrome/browser/resource_coordinator/lifecycle_unit_base.cc
index 5b47598..23f5d74 100644
--- a/chrome/browser/resource_coordinator/lifecycle_unit_base.cc
+++ b/chrome/browser/resource_coordinator/lifecycle_unit_base.cc
@@ -68,10 +68,6 @@
   observers_.RemoveObserver(observer);
 }
 
-ukm::SourceId LifecycleUnitBase::GetUkmSourceId() const {
-  return ukm::kInvalidSourceId;
-}
-
 void LifecycleUnitBase::SetDiscardCountForTesting(size_t discard_count) {
   discard_count_ = discard_count;
 }
diff --git a/chrome/browser/resource_coordinator/lifecycle_unit_base.h b/chrome/browser/resource_coordinator/lifecycle_unit_base.h
index 637146d6..41cf62c 100644
--- a/chrome/browser/resource_coordinator/lifecycle_unit_base.h
+++ b/chrome/browser/resource_coordinator/lifecycle_unit_base.h
@@ -44,7 +44,6 @@
   size_t GetDiscardCount() const override;
   void AddObserver(LifecycleUnitObserver* observer) override;
   void RemoveObserver(LifecycleUnitObserver* observer) override;
-  ukm::SourceId GetUkmSourceId() const override;
 
   void SetDiscardCountForTesting(size_t discard_count);
 
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
index f733183..699df7f 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
@@ -432,15 +432,6 @@
   return decision_details->IsPositive();
 }
 
-ukm::SourceId TabLifecycleUnitSource::TabLifecycleUnit::GetUkmSourceId() const {
-  resource_coordinator::ResourceCoordinatorTabHelper* observer =
-      resource_coordinator::ResourceCoordinatorTabHelper::FromWebContents(
-          web_contents());
-  if (!observer)
-    return ukm::kInvalidSourceId;
-  return observer->ukm_source_id();
-}
-
 bool TabLifecycleUnitSource::TabLifecycleUnit::IsAutoDiscardable() const {
   return auto_discardable_;
 }
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.h b/chrome/browser/resource_coordinator/tab_lifecycle_unit.h
index e9f34e7a..f253e99 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.h
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit.h
@@ -100,7 +100,6 @@
   LifecycleUnitDiscardReason GetDiscardReason() const override;
   bool Discard(LifecycleUnitDiscardReason discard_reason,
                uint64_t memory_footprint_estimate) override;
-  ukm::SourceId GetUkmSourceId() const override;
 
   // TabLifecycleUnitExternal:
   content::WebContents* GetWebContents() const override;
diff --git a/chrome/browser/resources/ash/settings/os_people_page/lock_screen_subpage.ts b/chrome/browser/resources/ash/settings/os_people_page/lock_screen_subpage.ts
index 02c7936..d29115e9 100644
--- a/chrome/browser/resources/ash/settings/os_people_page/lock_screen_subpage.ts
+++ b/chrome/browser/resources/ash/settings/os_people_page/lock_screen_subpage.ts
@@ -166,18 +166,6 @@
       },
 
       /**
-       * Whether switch from Gaia password factor to local password factor are
-       * allowed by the feature flag.
-       */
-      changePasswordFactorSetupEnabled_: {
-        type: Boolean,
-        value() {
-          return loadTimeData.getBoolean('changePasswordFactorSetupEnabled');
-        },
-        readOnly: true,
-      },
-
-      /**
        * Whether the device account is managed.
        */
       deviceAccountManaged_: {
@@ -203,7 +191,6 @@
   private showPasswordSettings_: boolean;
   private showDisableRecoveryDialog_: boolean;
   private fingerprintBrowserProxy_: FingerprintBrowserProxy;
-  private changePasswordFactorSetupEnabled_: boolean;
   private deviceAccountManaged_: boolean;
 
   static get observers() {
@@ -477,7 +464,7 @@
       this.showPasswordSettings_ = true;
     } else if (!this.deviceAccountManaged_) {
       // Onto scenarios for non managed accounts now.
-      if (this.changePasswordFactorSetupEnabled_ && hasGaiaPassword) {
+      if (hasGaiaPassword) {
         // If the gaia password is setup, for non managed users, we will allow
         // them to switch to local password.
         this.showPasswordSettings_ = true;
diff --git a/chrome/browser/resources/ash/settings/os_people_page/password_settings.html b/chrome/browser/resources/ash/settings/os_people_page/password_settings.html
index bc165d4..a5be3e6 100644
--- a/chrome/browser/resources/ash/settings/os_people_page/password_settings.html
+++ b/chrome/browser/resources/ash/settings/os_people_page/password_settings.html
@@ -28,8 +28,7 @@
       </template>
       <template
         is="dom-if"
-        if="[[canSwitchLocalPassword_(hasGaiaPassword_,
-              changePasswordFactorSetupEnabled_)]]"
+        if="[[hasGaiaPassword_]]"
       >
         <div class="secondary" id="switchLocalPasswordSecondaryLabel">
           $i18n{lockScreenSwitchLocalPasswordDescription}
@@ -38,7 +37,7 @@
     </div>
     <div class="settings-row">
       <div>
-        <template is="dom-if" if="[[hasNoPassword_(hasGaiaPassword_, hasLocalPassword_)]]">
+        <template is="dom-if" if="[[!hasLocalPassword_]]">
           <cr-button
             id="switchLocalPasswordButton"
             aria-describedby="switchLocalPasswordSecondaryLabel"
diff --git a/chrome/browser/resources/ash/settings/os_people_page/password_settings.ts b/chrome/browser/resources/ash/settings/os_people_page/password_settings.ts
index 7c408278..7d618419 100644
--- a/chrome/browser/resources/ash/settings/os_people_page/password_settings.ts
+++ b/chrome/browser/resources/ash/settings/os_people_page/password_settings.ts
@@ -6,7 +6,6 @@
 import {CrIconButtonElement} from 'chrome://resources/ash/common/cr_elements/cr_icon_button/cr_icon_button.js';
 import {fireAuthTokenInvalidEvent} from 'chrome://resources/ash/common/quick_unlock/utils.js';
 import {assert} from 'chrome://resources/js/assert.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {AuthFactor, AuthFactorConfig, ConfigureResult, FactorObserverReceiver, PasswordFactorEditor} from 'chrome://resources/mojo/chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom-webui.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
@@ -44,14 +43,6 @@
         type: Boolean,
         value: false,
       },
-
-      changePasswordFactorSetupEnabled_: {
-        type: Boolean,
-        value() {
-          return loadTimeData.getBoolean('changePasswordFactorSetupEnabled');
-        },
-        readOnly: true,
-      },
     };
   }
 
@@ -59,7 +50,6 @@
   private hasCryptohomePinV2_: boolean;
   private hasGaiaPassword_: boolean;
   private hasLocalPassword_: boolean;
-  private changePasswordFactorSetupEnabled_: boolean;
 
   override ready(): void {
     super.ready();
@@ -128,10 +118,6 @@
     this.setLocalPasswordDialog().showModal();
   }
 
-  private canSwitchLocalPassword_(): boolean {
-    return this.hasGaiaPassword_ && this.changePasswordFactorSetupEnabled_;
-  }
-
   private moreButton_(): CrIconButtonElement {
     const moreButton = this.shadowRoot!.querySelector('#moreButton');
     assert(moreButton instanceof CrIconButtonElement);
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/facegaze_test.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/facegaze_test.js
index 8e798e8..f09c5e9f 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/facegaze_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/facegaze_test.js
@@ -162,8 +162,7 @@
 
   // Cursor position does change after interval fired.
   this.triggerMouseControllerInterval();
-  const cursorPosition =
-      this.mockAccessibilityPrivate.getLatestCursorPosition();
+  const cursorPosition = this.getLatestCursorPosition();
   assertNotEquals(600, cursorPosition.x);
   assertNotEquals(400, cursorPosition.y);
 });
@@ -224,15 +223,13 @@
           0.11, 0.21);
       this.processFaceLandmarkerResult(result);
 
-      assertEquals(
-          null, this.mockAccessibilityPrivate.getLatestCursorPosition());
+      assertEquals(null, this.getLatestCursorPosition());
 
       // Try moving back. Still nothing.
       result = new MockFaceLandmarkerResult().setNormalizedForeheadLocation(
           0.1, 0.2);
       this.processFaceLandmarkerResult(result);
-      assertEquals(
-          null, this.mockAccessibilityPrivate.getLatestCursorPosition());
+      assertEquals(null, this.getLatestCursorPosition());
 
       // Turn on cursor control.
       await this.setPref(PrefNames.CURSOR_CONTROL_ENABLED, true);
@@ -326,7 +323,7 @@
   let result =
       new MockFaceLandmarkerResult().setNormalizedForeheadLocation(0.11, 0.21);
   this.processFaceLandmarkerResult(result);
-  let cursorPosition = this.mockAccessibilityPrivate.getLatestCursorPosition();
+  let cursorPosition = this.getLatestCursorPosition();
   assertTrue(cursorPosition.x < 600);
   assertTrue(cursorPosition.y > 400);
 
@@ -335,8 +332,7 @@
   result =
       new MockFaceLandmarkerResult().setNormalizedForeheadLocation(0.1, 0.2);
   this.processFaceLandmarkerResult(result);
-  let newCursorPosition =
-      this.mockAccessibilityPrivate.getLatestCursorPosition();
+  let newCursorPosition = this.getLatestCursorPosition();
   assertTrue(newCursorPosition.x > cursorPosition.x);
   assertTrue(newCursorPosition.y < cursorPosition.y);
   assertTrue(newCursorPosition.x < 600);
@@ -345,7 +341,7 @@
   cursorPosition = newCursorPosition;
   // Process the same result again. We move even closer to (600, 400).
   this.processFaceLandmarkerResult(result);
-  newCursorPosition = this.mockAccessibilityPrivate.getLatestCursorPosition();
+  newCursorPosition = this.getLatestCursorPosition();
   assertTrue(newCursorPosition.x > cursorPosition.x);
   assertTrue(newCursorPosition.y < cursorPosition.y);
   assertTrue(newCursorPosition.x < 600);
@@ -493,14 +489,12 @@
       for (let i = 1; i < 5; i++) {
         xLocation += px * 10;
         yLocation += py * 10;
-        const initialCursorPosition =
-            this.mockAccessibilityPrivate.getLatestCursorPosition();
+        const initialCursorPosition = this.getLatestCursorPosition();
         const result =
             new MockFaceLandmarkerResult().setNormalizedForeheadLocation(
                 xLocation, yLocation);
         this.processFaceLandmarkerResult(result);
-        const cursorPosition =
-            this.mockAccessibilityPrivate.getLatestCursorPosition();
+        const cursorPosition = this.getLatestCursorPosition();
         assertEquals(-10, cursorPosition.x - initialCursorPosition.x);
         assertEquals(10, cursorPosition.y - initialCursorPosition.y);
       }
@@ -524,14 +518,12 @@
       for (let i = 1; i < 5; i++) {
         xLocation += px * 20;
         yLocation += py * 20;
-        const initialCursorPosition =
-            this.mockAccessibilityPrivate.getLatestCursorPosition();
+        const initialCursorPosition = this.getLatestCursorPosition();
         const result =
             new MockFaceLandmarkerResult().setNormalizedForeheadLocation(
                 xLocation, yLocation);
         this.processFaceLandmarkerResult(result);
-        const cursorPosition =
-            this.mockAccessibilityPrivate.getLatestCursorPosition();
+        const cursorPosition = this.getLatestCursorPosition();
         assertEquals(-24, cursorPosition.x - initialCursorPosition.x);
         assertEquals(24, cursorPosition.y - initialCursorPosition.y);
       }
@@ -786,13 +778,13 @@
       const result = new MockFaceLandmarkerResult().addGestureWithConfidence(
           MediapipeFacialGesture.JAW_OPEN, 0.9);
       this.processFaceLandmarkerResult(result);
-      assertTrue(this.getFaceGaze().mouseController_.isLongClickActive());
+      assertTrue(this.getMouseController().isLongClickActive());
 
       // Remove long click action.
       await this.setPref(PrefNames.ACTIONS_ENABLED, false);
 
       // Ensure long click automatically toggled off.
-      assertFalse(this.getFaceGaze().mouseController_.isLongClickActive());
+      assertFalse(this.getMouseController().isLongClickActive());
     });
 
 AX_TEST_F(
@@ -811,13 +803,13 @@
       const result = new MockFaceLandmarkerResult().addGestureWithConfidence(
           MediapipeFacialGesture.JAW_OPEN, 0.9);
       this.processFaceLandmarkerResult(result);
-      assertTrue(this.getFaceGaze().mouseController_.isLongClickActive());
+      assertTrue(this.getMouseController().isLongClickActive());
 
       // Remove long click action.
       await this.setPref(PrefNames.GESTURE_TO_MACRO, {});
 
       // Ensure long click automatically toggled off.
-      assertFalse(this.getFaceGaze().mouseController_.isLongClickActive());
+      assertFalse(this.getMouseController().isLongClickActive());
     });
 
 // The BrowDown gesture is special because it is the combination of two
@@ -839,7 +831,7 @@
           .addGestureWithConfidence(
               MediapipeFacialGesture.BROW_DOWN_RIGHT, 0.3);
   this.processFaceLandmarkerResult(result);
-  assertEquals(null, this.mockAccessibilityPrivate.getLatestCursorPosition());
+  assertEquals(null, this.getLatestCursorPosition());
 
   result =
       new MockFaceLandmarkerResult()
@@ -1348,7 +1340,7 @@
       MediapipeFacialGesture.JAW_OPEN, 0.9);
   this.processFaceLandmarkerResult(
       result, /*triggerMouseControllerInterval=*/ false);
-  assertTrue(this.getFaceGaze().gestureHandler_.paused_);
+  assertTrue(this.getGestureHandler().paused_);
 
   // Try to perform left click.
   result =
@@ -1368,7 +1360,7 @@
           .addGestureWithConfidence(MediapipeFacialGesture.BROW_INNER_UP, 0);
   this.processFaceLandmarkerResult(
       result, /*triggerMouseControllerInterval=*/ false);
-  assertFalse(this.getFaceGaze().gestureHandler_.paused_);
+  assertFalse(this.getGestureHandler().paused_);
   // No click should be performed.
   this.assertNumMouseEvents(0);
 
@@ -1421,8 +1413,8 @@
   this.assertMousePress(this.getMouseEvents()[0]);
 
   // Stop FaceGaze in the middle of long actions.
-  this.getFaceGaze().mouseController_.stop();
-  this.getFaceGaze().gestureHandler_.stop();
+  this.getMouseController().stop();
+  this.getGestureHandler().stop();
 
   // Stopping in the middle of long actions should cause them to be completed.
   // The purpose of this is to clear state.
@@ -1443,8 +1435,8 @@
   this.assertNumKeyEvents(2);
 
   // Resume FaceGaze.
-  this.getFaceGaze().mouseController_.start();
-  this.getFaceGaze().gestureHandler_.start();
+  this.getMouseController().start();
+  this.getGestureHandler().start();
 
   // No extra mouse or key events should come through.
   this.assertNumMouseEvents(2);
@@ -1514,7 +1506,7 @@
   result = new MockFaceLandmarkerResult().addGestureWithConfidence(
       MediapipeFacialGesture.JAW_OPEN, 0.9);
   this.processFaceLandmarkerResult(result);
-  assertTrue(this.getFaceGaze().mouseController_.paused_);
+  assertTrue(this.getMouseController().paused_);
 
   // Try to move the mouse.
   result = new MockFaceLandmarkerResult()
@@ -1531,7 +1523,7 @@
   // is an asynchronous operation and will cause flakes otherwise.
   this.processFaceLandmarkerResult(
       result, /*triggerMouseControllerInterval=*/ false);
-  assertFalse(this.getFaceGaze().mouseController_.paused_);
+  assertFalse(this.getMouseController().paused_);
   // Wait for the MouseController to fully start.
   await this.waitForValidMouseInterval();
 
@@ -1573,7 +1565,7 @@
       {[FacialGesture.JAW_OPEN]: JSON.stringify(keyCombination)});
 
   // Verify that the preference propagated to FaceGaze.
-  assertEquals(this.getFaceGaze().gestureHandler_.gesturesToKeyCombos_.size, 1);
+  assertEquals(this.getGestureHandler().gesturesToKeyCombos_.size, 1);
 
   // Jaw open for custom key press.
   let result = new MockFaceLandmarkerResult().addGestureWithConfidence(
@@ -1622,7 +1614,7 @@
       {[FacialGesture.JAW_OPEN]: JSON.stringify(keyCombination)});
 
   // Verify that the preference propagated to FaceGaze.
-  assertEquals(this.getFaceGaze().gestureHandler_.gesturesToKeyCombos_.size, 1);
+  assertEquals(this.getGestureHandler().gesturesToKeyCombos_.size, 1);
 
   // Jaw open for custom key press.
   let result = new MockFaceLandmarkerResult().addGestureWithConfidence(
@@ -1679,20 +1671,18 @@
                      .withVelocityThreshold()
                      .withSpeeds(1, 1, 1, 1);
   await this.startFacegazeWithConfigAndForeheadLocation_(config, 0.1, 0.2);
-  assertNullOrUndefined(
-      this.mockAccessibilityPrivate.getLatestCursorPosition());
+  assertNullOrUndefined(this.getLatestCursorPosition());
 
   // Manually set the velocity threshold to 1. This means that the mouse needs
   // to move by more than one pixel before it will actually be moved.
-  this.getFaceGaze().mouseController_.velocityThreshold_ = 1;
+  this.getMouseController().velocityThreshold_ = 1;
 
   // Small movement in head location (e.g. one pixel) doesn't trigger any
   // mouse movement.
   result = new MockFaceLandmarkerResult().setNormalizedForeheadLocation(
       0.101, 0.201);
   this.processFaceLandmarkerResult(result);
-  assertNullOrUndefined(
-      this.mockAccessibilityPrivate.getLatestCursorPosition());
+  assertNullOrUndefined(this.getLatestCursorPosition());
 
   // Large movement triggers mouse movement.
   result =
@@ -1718,7 +1708,7 @@
 
   assertEquals(
       'Left-click the mouse (Open your mouth wide)', this.getBubbleText());
-  assertFalse(this.mockAccessibilityPrivate.getFaceGazeBubbleIsWarning());
+  assertFalse(this.getBubbleIsWarning());
 
   this.triggerBubbleControllerTimeout();
   assertEquals('', this.getBubbleText());
@@ -1749,7 +1739,7 @@
       'Right-click the mouse (Raise eyebrows), ' +
           'Left-click the mouse (Open your mouth wide)',
       this.getBubbleText());
-  assertFalse(this.mockAccessibilityPrivate.getFaceGazeBubbleIsWarning());
+  assertFalse(this.getBubbleIsWarning());
 
   this.triggerBubbleControllerTimeout();
   assertEquals('', this.getBubbleText());
@@ -1777,7 +1767,7 @@
       {[FacialGesture.JAW_OPEN]: JSON.stringify(keyCombination)});
 
   // Verify that the preference propagated to FaceGaze.
-  assertEquals(this.getFaceGaze().gestureHandler_.gesturesToKeyCombos_.size, 1);
+  assertEquals(this.getGestureHandler().gesturesToKeyCombos_.size, 1);
 
   // Jaw open for custom key press.
   let result = new MockFaceLandmarkerResult().addGestureWithConfidence(
@@ -1787,7 +1777,7 @@
   assertEquals(
       'Custom key combination: ctrl + c (Open your mouth wide)',
       this.getBubbleText());
-  assertFalse(this.mockAccessibilityPrivate.getFaceGazeBubbleIsWarning());
+  assertFalse(this.getBubbleIsWarning());
 
   // Message should persist while the gesture and key press is still being held.
   this.triggerBubbleControllerTimeout();
@@ -1832,8 +1822,7 @@
           {[FacialGesture.JAW_OPEN]: JSON.stringify(keyCombination)});
 
       // Verify that the preference propagated to FaceGaze.
-      assertEquals(
-          this.getFaceGaze().gestureHandler_.gesturesToKeyCombos_.size, 1);
+      assertEquals(this.getGestureHandler().gesturesToKeyCombos_.size, 1);
 
       // Jaw open for custom key press.
       let result = new MockFaceLandmarkerResult().addGestureWithConfidence(
@@ -1900,8 +1889,7 @@
           {[FacialGesture.JAW_OPEN]: JSON.stringify(keyCombination)});
 
       // Verify that the preference propagated to FaceGaze.
-      assertEquals(
-          this.getFaceGaze().gestureHandler_.gesturesToKeyCombos_.size, 1);
+      assertEquals(this.getGestureHandler().gesturesToKeyCombos_.size, 1);
 
       // Jaw open for custom key press.
       let result = new MockFaceLandmarkerResult().addGestureWithConfidence(
@@ -1959,7 +1947,7 @@
   const jawOpenTime =
       this.getGestureLastRecognized(MediapipeFacialGesture.JAW_OPEN);
   assertTrue(!!jawOpenTime);
-  assertTrue(this.getFaceGaze().gestureHandler_.paused_);
+  assertTrue(this.getGestureHandler().paused_);
 
   for (let i = 0; i < 5; i++) {
     const result = new MockFaceLandmarkerResult().addGestureWithConfidence(
@@ -1970,7 +1958,7 @@
     assertEquals(
         jawOpenTime,
         this.getGestureLastRecognized(MediapipeFacialGesture.JAW_OPEN));
-    assertTrue(this.getFaceGaze().gestureHandler_.paused_);
+    assertTrue(this.getGestureHandler().paused_);
   }
 
   // Check that we can resume after pausing.
@@ -1982,7 +1970,7 @@
   assertNotEquals(
       jawOpenTime,
       this.getGestureLastRecognized(MediapipeFacialGesture.JAW_OPEN));
-  assertFalse(this.getFaceGaze().gestureHandler_.paused_);
+  assertFalse(this.getGestureHandler().paused_);
 });
 
 AX_TEST_F('FaceGazeTest', 'BubbleTextStateMessages', async function() {
@@ -2002,7 +1990,7 @@
 
   assertEquals(
       'Pause face control (Open your mouth wide)', this.getBubbleText());
-  assertFalse(this.mockAccessibilityPrivate.getFaceGazeBubbleIsWarning());
+  assertFalse(this.getBubbleIsWarning());
 
   // FaceGaze should display important messages about the state after the
   // timeout has elapsed.
@@ -2010,7 +1998,7 @@
   assertEquals(
       'Face control paused. Open your mouth wide to resume. Other gestures temporarily unavailable.',
       this.getBubbleText());
-  assertTrue(this.mockAccessibilityPrivate.getFaceGazeBubbleIsWarning());
+  assertTrue(this.getBubbleIsWarning());
 });
 
 AX_TEST_F('FaceGazeTest', 'BubbleTextLongClickStateMessage', async function() {
@@ -2032,26 +2020,26 @@
 
   assertEquals(
       'Start drag and drop (Open your mouth wide)', this.getBubbleText());
-  assertFalse(this.mockAccessibilityPrivate.getFaceGazeBubbleIsWarning());
+  assertFalse(this.getBubbleIsWarning());
 
   // FaceGaze should display important messages about the state after the
   // timeout has elapsed.
   this.triggerBubbleControllerTimeout();
-  assertTrue(this.getFaceGaze().mouseController_.isLongClickActive());
+  assertTrue(this.getMouseController().isLongClickActive());
   assertEquals(
       'Drag and drop in progress. Open your mouth wide to end. Other gestures temporarily unavailable.',
       this.getBubbleText());
-  assertTrue(this.mockAccessibilityPrivate.getFaceGazeBubbleIsWarning());
+  assertTrue(this.getBubbleIsWarning());
 
   // Finish drag and drop action.
   this.processFaceLandmarkerResult(result);
   assertEquals(
       'End drag and drop (Open your mouth wide)', this.getBubbleText());
-  assertFalse(this.mockAccessibilityPrivate.getFaceGazeBubbleIsWarning());
+  assertFalse(this.getBubbleIsWarning());
 
   this.triggerBubbleControllerTimeout();
   assertEquals('', this.getBubbleText());
-  assertFalse(this.mockAccessibilityPrivate.getFaceGazeBubbleIsWarning());
+  assertFalse(this.getBubbleIsWarning());
 });
 
 AX_TEST_F('FaceGazeTest', 'BubbleTextDictationStateMessage', async function() {
@@ -2072,10 +2060,10 @@
   this.processFaceLandmarkerResult(result, false);
 
   // Make FaceGaze think dictation is active.
-  this.getFaceGaze().gestureHandler_.isDictationActive_ = () => true;
+  this.getGestureHandler().isDictationActive_ = () => true;
 
   assertEquals('Start dictation (Open your mouth wide)', this.getBubbleText());
-  assertFalse(this.mockAccessibilityPrivate.getFaceGazeBubbleIsWarning());
+  assertFalse(this.getBubbleIsWarning());
 
   // Make bubble controller think that Dictation is active.
   this.getFaceGaze().bubbleController_.getState_ = () => {
@@ -2088,7 +2076,7 @@
   assertEquals(
       'Dictation active. Open your mouth wide to stop. Other gestures temporarily unavailable.',
       this.getBubbleText());
-  assertTrue(this.mockAccessibilityPrivate.getFaceGazeBubbleIsWarning());
+  assertTrue(this.getBubbleIsWarning());
 
   // Toggle dictation off.
   this.processFaceLandmarkerResult(result);
@@ -2097,12 +2085,12 @@
   };
 
   // Make FaceGaze think dictation is off.
-  this.getFaceGaze().gestureHandler_.isDictationActive_ = () => false;
+  this.getGestureHandler().isDictationActive_ = () => false;
   assertEquals('Stop dictation (Open your mouth wide)', this.getBubbleText());
-  assertFalse(this.mockAccessibilityPrivate.getFaceGazeBubbleIsWarning());
+  assertFalse(this.getBubbleIsWarning());
   this.triggerBubbleControllerTimeout();
   assertEquals('', this.getBubbleText());
-  assertFalse(this.mockAccessibilityPrivate.getFaceGazeBubbleIsWarning());
+  assertFalse(this.getBubbleIsWarning());
 });
 
 AX_TEST_F('FaceGazeTest', 'BubbleTextStateAndActionMessages', async function() {
@@ -2131,7 +2119,7 @@
       'Pause face control (Raise eyebrows), ' +
           'Left-click the mouse (Open your mouth wide)',
       this.getBubbleText());
-  assertFalse(this.mockAccessibilityPrivate.getFaceGazeBubbleIsWarning());
+  assertFalse(this.getBubbleIsWarning());
 
   // FaceGaze should display important messages about the state after the
   // timeout has elapsed.
@@ -2139,7 +2127,7 @@
   assertEquals(
       'Face control paused. Raise eyebrows to resume. Other gestures temporarily unavailable.',
       this.getBubbleText());
-  assertTrue(this.mockAccessibilityPrivate.getFaceGazeBubbleIsWarning());
+  assertTrue(this.getBubbleIsWarning());
 
   // Send another result. Note that since FaceGaze is paused, no action
   // will be taken.
@@ -2150,14 +2138,14 @@
   assertEquals(
       'Face control paused. Raise eyebrows to resume. Other gestures temporarily unavailable.',
       this.getBubbleText());
-  assertTrue(this.mockAccessibilityPrivate.getFaceGazeBubbleIsWarning());
+  assertTrue(this.getBubbleIsWarning());
 
   result = new MockFaceLandmarkerResult().addGestureWithConfidence(
       MediapipeFacialGesture.BROW_INNER_UP, 0.9);
   this.processFaceLandmarkerResult(
       result, /*triggerMouseControllerInterval=*/ false);
   assertEquals('Resume face control (Raise eyebrows)', this.getBubbleText());
-  assertFalse(this.mockAccessibilityPrivate.getFaceGazeBubbleIsWarning());
+  assertFalse(this.getBubbleIsWarning());
 });
 
 AX_TEST_F('FaceGazeTest', 'TurnOffActionsWhileInScrollMode', async function() {
@@ -2335,7 +2323,7 @@
       PrefNames.GESTURE_TO_KEY_COMBO,
       {[FacialGesture.BROW_INNER_UP]: JSON.stringify(keyCombination)});
 
-  const gestureHandler = this.getFaceGaze().gestureHandler_;
+  const gestureHandler = this.getGestureHandler();
 
   let lastText = '';
   for (const macroName of macroNames) {
@@ -2372,7 +2360,7 @@
                      .withRepeatDelayMs(0);
   await this.startFacegazeWithConfigAndForeheadLocation_(config, 0.1, 0.2);
 
-  const gestureHandler = this.getFaceGaze().gestureHandler_;
+  const gestureHandler = this.getGestureHandler();
 
   // Make FaceGaze think that Dictation is active.
   gestureHandler.isDictationActive_ = () => true;
@@ -2412,7 +2400,7 @@
                      .withRepeatDelayMs(0);
   await this.configureFaceGaze(config);
 
-  const gestureHandler = this.getFaceGaze().gestureHandler_;
+  const gestureHandler = this.getGestureHandler();
 
   // If eye squint on one side occurs at same time as a blink or squint on the
   // wrong side, then the gesture should not register as an eye squint on the
@@ -2498,7 +2486,7 @@
                          .withMinDurationMs(30 * 1000);
       await this.configureFaceGaze(config);
 
-      const gestureHandler = this.getFaceGaze().gestureHandler_;
+      const gestureHandler = this.getGestureHandler();
 
       let result = new MockFaceLandmarkerResult()
                        .addGestureWithConfidence(
@@ -2537,7 +2525,7 @@
                      .withMinDurationMs(-1);
   await this.configureFaceGaze(config);
 
-  const gestureHandler = this.getFaceGaze().gestureHandler_;
+  const gestureHandler = this.getGestureHandler();
   assertEquals(-1, gestureHandler.gestureTimer_.minDurationMs_);
 
   let result =
@@ -2586,7 +2574,7 @@
                          .withRepeatDelayMs(0)
                          .withMinDurationMs(-1);
       await this.configureFaceGaze(config);
-      const gestureHandler = this.getFaceGaze().gestureHandler_;
+      const gestureHandler = this.getGestureHandler();
       assertEquals(-1, gestureHandler.gestureTimer_.minDurationMs_);
 
       let result = new MockFaceLandmarkerResult()
@@ -2648,7 +2636,7 @@
                          .withRepeatDelayMs(0)
                          .withMinDurationMs(-1);
       await this.configureFaceGaze(config);
-      const gestureHandler = this.getFaceGaze().gestureHandler_;
+      const gestureHandler = this.getGestureHandler();
       assertEquals(-1, gestureHandler.gestureTimer_.minDurationMs_);
 
       let result = new MockFaceLandmarkerResult()
@@ -2717,7 +2705,7 @@
   let result = new MockFaceLandmarkerResult().addGestureWithConfidence(
       MediapipeFacialGesture.JAW_OPEN, 0.9);
   this.processFaceLandmarkerResult(result, false);
-  assertTrue(this.getFaceGaze().mouseController_.isPrecisionActive());
+  assertTrue(this.getMouseController().isPrecisionActive());
   // Ensure no mouse events were sent.
   assertEquals(this.getMouseEvents().length, 0);
 
@@ -2725,7 +2713,7 @@
   result = new MockFaceLandmarkerResult().addGestureWithConfidence(
       MediapipeFacialGesture.JAW_OPEN, 0.9);
   this.processFaceLandmarkerResult(result, false);
-  assertFalse(this.getFaceGaze().mouseController_.isPrecisionActive());
+  assertFalse(this.getMouseController().isPrecisionActive());
 
   const mouseEvents = this.getMouseEvents();
   assertEquals(mouseEvents.length, 2);
@@ -2749,35 +2737,33 @@
                      .withPrecisionEnabled(/*speedFactor=*/ 50);
   await this.configureFaceGaze(config);
 
-  assertNullOrUndefined(this.mockAccessibilityPrivate.getFaceGazeBubbleText());
+  assertNullOrUndefined(this.getBubbleText());
 
   // Start precision click by performing gesture assigned to left click.
   let result = new MockFaceLandmarkerResult().addGestureWithConfidence(
       MediapipeFacialGesture.JAW_OPEN, 0.9);
   this.processFaceLandmarkerResult(result, false);
-  assertTrue(this.getFaceGaze().mouseController_.isPrecisionActive());
+  assertTrue(this.getMouseController().isPrecisionActive());
   assertEquals(
-      'Start precision click (Open your mouth wide)',
-      this.mockAccessibilityPrivate.getFaceGazeBubbleText());
+      'Start precision click (Open your mouth wide)', this.getBubbleText());
 
   // FaceGaze should display important messages about the state after the
   // timeout has elapsed.
   this.triggerBubbleControllerTimeout();
   assertEquals(
       'Mouse speed reduced, Open your mouth wide again to click',
-      this.mockAccessibilityPrivate.getFaceGazeBubbleText());
+      this.getBubbleText());
 
   // Perform the gesture again to left-click.
   result = new MockFaceLandmarkerResult().addGestureWithConfidence(
       MediapipeFacialGesture.JAW_OPEN, 0.9);
   this.processFaceLandmarkerResult(result, false);
-  assertFalse(this.getFaceGaze().mouseController_.isPrecisionActive());
+  assertFalse(this.getMouseController().isPrecisionActive());
   assertEquals(
-      'Left-click the mouse (Open your mouth wide)',
-      this.mockAccessibilityPrivate.getFaceGazeBubbleText());
+      'Left-click the mouse (Open your mouth wide)', this.getBubbleText());
 
   this.triggerBubbleControllerTimeout();
-  assertEquals('', this.mockAccessibilityPrivate.getFaceGazeBubbleText());
+  assertEquals('', this.getBubbleText());
 });
 
 AX_TEST_F('FaceGazeTest', 'PrecisionClickMouseMovement', async function() {
@@ -2804,7 +2790,7 @@
   result = new MockFaceLandmarkerResult().addGestureWithConfidence(
       MediapipeFacialGesture.JAW_OPEN, 0.9);
   this.processFaceLandmarkerResult(result);
-  assertTrue(this.getFaceGaze().mouseController_.isPrecisionActive());
+  assertTrue(this.getMouseController().isPrecisionActive());
 
   // Update the head position by the same delta. Notice that the cursor delta in
   // each direction is cut in half (due to the precision speed factor).
@@ -2828,19 +2814,19 @@
       const result = new MockFaceLandmarkerResult().addGestureWithConfidence(
           MediapipeFacialGesture.JAW_OPEN, 0.9);
       this.processFaceLandmarkerResult(result, false);
-      assertTrue(this.getFaceGaze().mouseController_.isPrecisionActive());
+      assertTrue(this.getMouseController().isPrecisionActive());
 
       this.triggerBubbleControllerTimeout();
       assertEquals(
           'Mouse speed reduced, Open your mouth wide again to click',
-          this.mockAccessibilityPrivate.getFaceGazeBubbleText());
+          this.getBubbleText());
 
       // Turn off actions via pref.
       await this.setPref(PrefNames.ACTIONS_ENABLED, false);
 
       // Ensure precision click is automatically toggled off.
-      assertFalse(this.getFaceGaze().mouseController_.isPrecisionActive());
-      assertEquals('', this.mockAccessibilityPrivate.getFaceGazeBubbleText());
+      assertFalse(this.getMouseController().isPrecisionActive());
+      assertEquals('', this.getBubbleText());
     });
 
 AX_TEST_F(
@@ -2858,19 +2844,19 @@
       const result = new MockFaceLandmarkerResult().addGestureWithConfidence(
           MediapipeFacialGesture.JAW_OPEN, 0.9);
       this.processFaceLandmarkerResult(result, false);
-      assertTrue(this.getFaceGaze().mouseController_.isPrecisionActive());
+      assertTrue(this.getMouseController().isPrecisionActive());
 
       this.triggerBubbleControllerTimeout();
       assertEquals(
           'Mouse speed reduced, Open your mouth wide again to click',
-          this.mockAccessibilityPrivate.getFaceGazeBubbleText());
+          this.getBubbleText());
 
       // Turn off cursor control via pref.
       await this.setPref(PrefNames.CURSOR_CONTROL_ENABLED, false);
 
       // Ensure precision click is automatically toggled off.
-      assertFalse(this.getFaceGaze().mouseController_.isPrecisionActive());
-      assertEquals('', this.mockAccessibilityPrivate.getFaceGazeBubbleText());
+      assertFalse(this.getMouseController().isPrecisionActive());
+      assertEquals('', this.getBubbleText());
     });
 
 AX_TEST_F('FaceGazeTest', 'PrecisionClickAndScrollMode', async function() {
@@ -2893,33 +2879,30 @@
   let result = new MockFaceLandmarkerResult().addGestureWithConfidence(
       MediapipeFacialGesture.JAW_OPEN, 0.9);
   this.processFaceLandmarkerResult(result);
-  assertTrue(this.getFaceGaze().mouseController_.isPrecisionActive());
+  assertTrue(this.getMouseController().isPrecisionActive());
 
   assertEquals(
-      'Start precision click (Open your mouth wide)',
-      this.mockAccessibilityPrivate.getFaceGazeBubbleText());
+      'Start precision click (Open your mouth wide)', this.getBubbleText());
 
   this.triggerBubbleControllerTimeout();
   assertEquals(
       'Mouse speed reduced, Open your mouth wide again to click',
-      this.mockAccessibilityPrivate.getFaceGazeBubbleText());
+      this.getBubbleText());
 
   // Toggle scroll mode on. This should automatically stop precision click.
   result = new MockFaceLandmarkerResult().addGestureWithConfidence(
       MediapipeFacialGesture.BROW_INNER_UP, 0.9);
   this.processFaceLandmarkerResult(result);
-  assertFalse(this.getFaceGaze().mouseController_.isPrecisionActive());
+  assertFalse(this.getMouseController().isPrecisionActive());
   assertTrue(this.getScrollModeController().active());
-  assertEquals(
-      'Enter scroll mode (Raise eyebrows)',
-      this.mockAccessibilityPrivate.getFaceGazeBubbleText());
+  assertEquals('Enter scroll mode (Raise eyebrows)', this.getBubbleText());
 
   // Only the scroll mode state message should be present.
   this.triggerBubbleControllerTimeout();
   assertEquals(
       'Scroll mode active. Raise eyebrows to exit. Other gestures ' +
           'temporarily unavailable.',
-      this.mockAccessibilityPrivate.getFaceGazeBubbleText());
+      this.getBubbleText());
 });
 
 AX_TEST_F(
@@ -2940,12 +2923,12 @@
       let result = new MockFaceLandmarkerResult().addGestureWithConfidence(
           MediapipeFacialGesture.JAW_OPEN, 0.9);
       this.processFaceLandmarkerResult(result, false);
-      assertFalse(this.getFaceGaze().mouseController_.isPrecisionActive());
+      assertFalse(this.getMouseController().isPrecisionActive());
 
       result = new MockFaceLandmarkerResult().addGestureWithConfidence(
           MediapipeFacialGesture.BROW_INNER_UP, 0.9);
       this.processFaceLandmarkerResult(result, false);
-      assertFalse(this.getFaceGaze().mouseController_.isPrecisionActive());
+      assertFalse(this.getMouseController().isPrecisionActive());
     });
 
 AX_TEST_F('FaceGazeTest', 'PrecisionRightClickBubbleText', async function() {
@@ -2958,35 +2941,33 @@
                      .withPrecisionEnabled(/*speedFactor=*/ 50);
   await this.configureFaceGaze(config);
 
-  assertNullOrUndefined(this.mockAccessibilityPrivate.getFaceGazeBubbleText());
+  assertNullOrUndefined(this.getBubbleText());
 
   // Start precision click by performing gesture assigned to right click.
   let result = new MockFaceLandmarkerResult().addGestureWithConfidence(
       MediapipeFacialGesture.JAW_OPEN, 0.9);
   this.processFaceLandmarkerResult(result, false);
-  assertTrue(this.getFaceGaze().mouseController_.isPrecisionActive());
+  assertTrue(this.getMouseController().isPrecisionActive());
   assertEquals(
-      'Start precision click (Open your mouth wide)',
-      this.mockAccessibilityPrivate.getFaceGazeBubbleText());
+      'Start precision click (Open your mouth wide)', this.getBubbleText());
 
   // FaceGaze should display important messages about the state after the
   // timeout has elapsed.
   this.triggerBubbleControllerTimeout();
   assertEquals(
       'Mouse speed reduced, Open your mouth wide again to click',
-      this.mockAccessibilityPrivate.getFaceGazeBubbleText());
+      this.getBubbleText());
 
   // Perform the gesture again to right-click.
   result = new MockFaceLandmarkerResult().addGestureWithConfidence(
       MediapipeFacialGesture.JAW_OPEN, 0.9);
   this.processFaceLandmarkerResult(result, false);
-  assertFalse(this.getFaceGaze().mouseController_.isPrecisionActive());
+  assertFalse(this.getMouseController().isPrecisionActive());
   assertEquals(
-      'Right-click the mouse (Open your mouth wide)',
-      this.mockAccessibilityPrivate.getFaceGazeBubbleText());
+      'Right-click the mouse (Open your mouth wide)', this.getBubbleText());
 
   this.triggerBubbleControllerTimeout();
-  assertEquals('', this.mockAccessibilityPrivate.getFaceGazeBubbleText());
+  assertEquals('', this.getBubbleText());
 });
 
 AX_TEST_F('FaceGazeTest', 'PrecisionRightClickMouseEvents', async function() {
@@ -3003,7 +2984,7 @@
   let result = new MockFaceLandmarkerResult().addGestureWithConfidence(
       MediapipeFacialGesture.JAW_OPEN, 0.9);
   this.processFaceLandmarkerResult(result, false);
-  assertTrue(this.getFaceGaze().mouseController_.isPrecisionActive());
+  assertTrue(this.getMouseController().isPrecisionActive());
   // Ensure no mouse events were sent.
   assertEquals(this.getMouseEvents().length, 0);
 
@@ -3011,7 +2992,7 @@
   result = new MockFaceLandmarkerResult().addGestureWithConfidence(
       MediapipeFacialGesture.JAW_OPEN, 0.9);
   this.processFaceLandmarkerResult(result, false);
-  assertFalse(this.getFaceGaze().mouseController_.isPrecisionActive());
+  assertFalse(this.getMouseController().isPrecisionActive());
 
   const mouseEvents = this.getMouseEvents();
   assertEquals(mouseEvents.length, 2);
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/facegaze_test_base.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/facegaze_test_base.js
index 4ca90f7..8246ffd 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/facegaze_test_base.js
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/facegaze_test_base.js
@@ -282,9 +282,19 @@
     return accessibilityCommon.getFaceGazeForTest();
   }
 
+  /** @return {!MouseController} */
+  getMouseController() {
+    return this.getFaceGaze().mouseController_;
+  }
+
   /** @return {!ScrollModeController} */
   getScrollModeController() {
-    return this.getFaceGaze().mouseController_.scrollModeController_;
+    return this.getMouseController().scrollModeController_;
+  }
+
+  /** @return {!GestureHandler} */
+  getGestureHandler() {
+    return this.getFaceGaze().gestureHandler_;
   }
 
   async startFacegazeWithConfigAndForeheadLocation_(
@@ -551,4 +561,13 @@
   getBubbleText() {
     return this.mockAccessibilityPrivate.getFaceGazeBubbleText();
   }
+
+  /** @return {boolean} */
+  getBubbleIsWarning() {
+    return this.mockAccessibilityPrivate.getFaceGazeBubbleIsWarning();
+  }
+
+  getLatestCursorPosition() {
+    return this.mockAccessibilityPrivate.getLatestCursorPosition();
+  }
 };
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_am.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_am.xtb
index aea47ff..7757db5 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_am.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_am.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">ዓምድ</translation>
 <translation id="6387719785439924554">aside</translation>
 <translation id="6393014464788431702">ሁሉንም የክስተት ማጣሪያዎች አሰናክል</translation>
+<translation id="6406989068857078334">የመዳፊት ፍጥነት ተቀንሷል፣ ጠቅ ለማድረግ እንደገና <ph name="GESTURE" /></translation>
 <translation id="6411569524720229058">መኸር</translation>
 <translation id="6417265370957905582">Google ረዳት</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{ሁለት ነጥብ}one{# ሁለት ነጥቦች}other{# ሁለት ነጥቦች}}</translation>
@@ -1099,6 +1100,7 @@
 <translation id="8205922869661890178">የገንቢ ምዝግብ ገፅ ይክፈቱ</translation>
 <translation id="8212109599554677485">የማሳያ ቅጥ ወደ ጎን ለጎን ቀይር</translation>
 <translation id="8215202828671303819">ብዙ ምርጫ</translation>
+<translation id="822316432305106615">የትክክለኝነት ጠቅታን ጀምር</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />, <ph name="OPACITY_PERCENTAGE" />% ብርሃን-ከልነት።</translation>
 <translation id="8261506727792406068">ሰርዝ</translation>
 <translation id="826825447994856889">መግቢያ</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_as.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_as.xtb
index 7f651d4c..cbc5035a 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_as.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_as.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">স্তম্ভ</translation>
 <translation id="6387719785439924554">পৃথক</translation>
 <translation id="6393014464788431702">অনুষ্ঠানৰ সকলো ফিল্টাৰ অক্ষম কৰক</translation>
+<translation id="6406989068857078334">মাউছৰ গতিবেগ হ্ৰাস কৰা হৈছে, ক্লিক কৰিবলৈ পুনৰ <ph name="GESTURE" /></translation>
 <translation id="6411569524720229058">শৰৎ কাল</translation>
 <translation id="6417265370957905582">Google Assistant</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{ক'লন}one{#টা ক’লন}other{#টা ক’লন}}</translation>
@@ -1099,6 +1100,7 @@
 <translation id="8205922869661890178">বিকাশকৰ্তাৰ লগ পৃষ্ঠা খোলক</translation>
 <translation id="8212109599554677485">ডিছপ্লে’ৰ শৈলী কাষে-কাষে থকা অৱস্থালৈ সলনি কৰক</translation>
 <translation id="8215202828671303819">একাধিক বাছনি</translation>
+<translation id="822316432305106615">সঠিকতাৰ ক্লিক আৰম্ভ কৰক</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />, <ph name="OPACITY_PERCENTAGE" />% অস্পষ্টতা।</translation>
 <translation id="8261506727792406068">মচক</translation>
 <translation id="826825447994856889">পাতনি</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_az.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_az.xtb
index 95efffc..f755a1a1 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_az.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_az.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">süt</translation>
 <translation id="6387719785439924554">kənar</translation>
 <translation id="6393014464788431702">Bütün tədbir filtrlərini deaktiv edin</translation>
+<translation id="6406989068857078334">Mausun sürəti azaldıldı, klikləmək üçün yenidən <ph name="GESTURE" /></translation>
 <translation id="6411569524720229058">Payız</translation>
 <translation id="6417265370957905582">Google Assistent</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{iki nöqtə}other{# iki nöqtə}}</translation>
@@ -1099,6 +1100,7 @@
 <translation id="8205922869661890178">Developer giriş səhifəsini açın</translation>
 <translation id="8212109599554677485">Ekran üslubunu yan-yana olaraq dəyişin</translation>
 <translation id="8215202828671303819">Multi seçin</translation>
+<translation id="822316432305106615">Dəqiq kliklə başlayın</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />, <ph name="OPACITY_PERCENTAGE" />% qeyri-şəffaflıq.</translation>
 <translation id="8261506727792406068">Silin</translation>
 <translation id="826825447994856889">Giriş</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ca.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ca.xtb
index c28731c..42cbadf 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ca.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ca.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">columna</translation>
 <translation id="6387719785439924554">complement</translation>
 <translation id="6393014464788431702">Desactiva tots els filtres de l'esdeveniment</translation>
+<translation id="6406989068857078334">La velocitat del ratolí s'ha reduït. <ph name="GESTURE" /> de nou per fer clic.</translation>
 <translation id="6411569524720229058">Tardor</translation>
 <translation id="6417265370957905582">Assistent de Google</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{dos punts}other{# dos punts}}</translation>
@@ -1099,6 +1100,7 @@
 <translation id="8205922869661890178">Obre la pàgina de registres per a desenvolupadors</translation>
 <translation id="8212109599554677485">Canvia l'estil de pantalla a paral·lel</translation>
 <translation id="8215202828671303819">Selecció múltiple</translation>
+<translation id="822316432305106615">Inicia el clic de precisió</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />, <ph name="OPACITY_PERCENTAGE" />% d'opacitat.</translation>
 <translation id="8261506727792406068">Suprimeix</translation>
 <translation id="826825447994856889">Introducció</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_da.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_da.xtb
index 64636bf..aeee3b5 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_da.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_da.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">kol</translation>
 <translation id="6387719785439924554">tilsi</translation>
 <translation id="6393014464788431702">Deaktiver alle hændelsesfiltre</translation>
+<translation id="6406989068857078334">Musehastigheden er reduceret. <ph name="GESTURE" /> igen for at klikke</translation>
 <translation id="6411569524720229058">Efterår</translation>
 <translation id="6417265370957905582">Google Assistent</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{kolon}one{# koloner}other{# koloner}}</translation>
@@ -1099,6 +1100,7 @@
 <translation id="8205922869661890178">Åbn side med udviklerlogfiler</translation>
 <translation id="8212109599554677485">Skift visningsformat til side om side</translation>
 <translation id="8215202828671303819">Valg af flere</translation>
+<translation id="822316432305106615">Start præcisionsklik</translation>
 <translation id="8249864170673238087"><ph name="COLOR" /> – <ph name="OPACITY_PERCENTAGE" /> % gennemsigtighed.</translation>
 <translation id="8261506727792406068">Slet</translation>
 <translation id="826825447994856889">Indledning</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_en-GB.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_en-GB.xtb
index 655b53ece..961e9e56 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_en-GB.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_en-GB.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">col</translation>
 <translation id="6387719785439924554">aside</translation>
 <translation id="6393014464788431702">Disable all event filters</translation>
+<translation id="6406989068857078334">Mouse speed reduced, <ph name="GESTURE" /> again to click</translation>
 <translation id="6411569524720229058">Autumn</translation>
 <translation id="6417265370957905582">Google Assistant</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{colon}other{# colons}}</translation>
@@ -1099,6 +1100,7 @@
 <translation id="8205922869661890178">Open developer log page</translation>
 <translation id="8212109599554677485">Change display style to side by side</translation>
 <translation id="8215202828671303819">Multi select</translation>
+<translation id="822316432305106615">Start precision click</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />, <ph name="OPACITY_PERCENTAGE" />% opacity.</translation>
 <translation id="8261506727792406068">Delete</translation>
 <translation id="826825447994856889">Introduction</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_gu.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_gu.xtb
index a915986e..8e34131 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_gu.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_gu.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">કૉલમ</translation>
 <translation id="6387719785439924554">aside</translation>
 <translation id="6393014464788431702">ઇવેન્ટના બધા ફિલ્ટર બંધ કરો</translation>
+<translation id="6406989068857078334">માઉસની સ્પીડ ઘટાડવામાં આવી, ક્લિક કરવા માટે ફરીથી <ph name="GESTURE" /></translation>
 <translation id="6411569524720229058">પાનખર</translation>
 <translation id="6417265370957905582">Google Assistant</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{મહાવિરામ}one{# મહાવિરામ}other{# મહાવિરામ}}</translation>
@@ -1099,6 +1100,7 @@
 <translation id="8205922869661890178">ડેવલપર લૉગ પેજ ખોલો</translation>
 <translation id="8212109599554677485">ડિસ્પ્લે શૈલીને 'સાથેસાથે' પર બદલો</translation>
 <translation id="8215202828671303819">બહુ પસંદ</translation>
+<translation id="822316432305106615">ચોકસાઈવાળી ક્લિક શરૂ કરો</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />, પારદર્શકતા <ph name="OPACITY_PERCENTAGE" />%.</translation>
 <translation id="8261506727792406068">ડિલીટ કરો</translation>
 <translation id="826825447994856889">પ્રસ્તાવના</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_hy.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_hy.xtb
index 8d3560a..816a4fd 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_hy.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_hy.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">սյունակ</translation>
 <translation id="6387719785439924554">aside</translation>
 <translation id="6393014464788431702">Անջատել իրադարձությունների բոլոր զտիչները</translation>
+<translation id="6406989068857078334">Մկնիկի արագությունը նվազեցվել է, սեղմելու համար նորից <ph name="GESTURE" /></translation>
 <translation id="6411569524720229058">Աշուն</translation>
 <translation id="6417265370957905582">Google Օգնական</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{միջակետ}one{# միջակետ}other{# միջակետ}}</translation>
@@ -1099,6 +1100,7 @@
 <translation id="8205922869661890178">Բացել մշակողի մատյանի էջը</translation>
 <translation id="8212109599554677485">Դարձնել էկրանի ոճը կողք կողքի</translation>
 <translation id="8215202828671303819">Բազմակի ընտրարկում</translation>
+<translation id="822316432305106615">Սկսեք ճշգրտիչ սեղմումը</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />, <ph name="OPACITY_PERCENTAGE" />% թափանցիկություն</translation>
 <translation id="8261506727792406068">Ջնջել</translation>
 <translation id="826825447994856889">Ներածություն</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_id.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_id.xtb
index 4934131..f592c110 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_id.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_id.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">kolom</translation>
 <translation id="6387719785439924554">aside</translation>
 <translation id="6393014464788431702">Nonaktifkan semua filter peristiwa</translation>
+<translation id="6406989068857078334">Kecepatan mouse dikurangi, <ph name="GESTURE" /> lagi untuk mengklik</translation>
 <translation id="6411569524720229058">Musim Gugur</translation>
 <translation id="6417265370957905582">Asisten Google</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{titik dua}other{# titik dua}}</translation>
@@ -1098,6 +1099,7 @@
 <translation id="8205922869661890178">Buka halaman log developer</translation>
 <translation id="8212109599554677485">Ubah gaya tampilan menjadi berdampingan</translation>
 <translation id="8215202828671303819">Multi-pilihan</translation>
+<translation id="822316432305106615">Mulai klik presisi</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />, <ph name="OPACITY_PERCENTAGE" />% opasitas.</translation>
 <translation id="8261506727792406068">Hapus</translation>
 <translation id="826825447994856889">Pendahuluan</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ko.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ko.xtb
index 2bc7786..19680af 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ko.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ko.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">열</translation>
 <translation id="6387719785439924554">aside</translation>
 <translation id="6393014464788431702">모든 이벤트 필터 사용 중지</translation>
+<translation id="6406989068857078334">마우스 속도가 감소했습니다. 다시 <ph name="GESTURE" /> 동작을 수행하여 클릭하세요.</translation>
 <translation id="6411569524720229058">가을</translation>
 <translation id="6417265370957905582">Google 어시스턴트</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{콜론}other{콜론 #개}}</translation>
@@ -1098,6 +1099,7 @@
 <translation id="8205922869661890178">개발자 로그 페이지 열기</translation>
 <translation id="8212109599554677485">디스플레이 스타일을 나란히로 변경</translation>
 <translation id="8215202828671303819">다중 선택</translation>
+<translation id="822316432305106615">정밀 클릭 시작</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />, 불투명도 <ph name="OPACITY_PERCENTAGE" />%.</translation>
 <translation id="8261506727792406068">삭제</translation>
 <translation id="826825447994856889">소개</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_lt.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_lt.xtb
index 845694ca..bbc8be7 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_lt.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_lt.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">stulp.</translation>
 <translation id="6387719785439924554">šalia</translation>
 <translation id="6393014464788431702">Išjungti visus įvykių filtrus</translation>
+<translation id="6406989068857078334">Pelės greitis sumažintas, <ph name="GESTURE" /> dar kartą, kad spustelėtumėte</translation>
 <translation id="6411569524720229058">Ruduo</translation>
 <translation id="6417265370957905582">„Google“ padėjėjas</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{dvitaškis}one{# dvitaškis}few{# dvitaškiai}many{# colons}other{# dvitaškių}}</translation>
@@ -1099,6 +1100,7 @@
 <translation id="8205922869661890178">Atidaryti kūrėjo žurnalo puslapį</translation>
 <translation id="8212109599554677485">Keisti vaizdo stilių į gretutinį</translation>
 <translation id="8215202828671303819">Kelių elementų pasirinkimas</translation>
+<translation id="822316432305106615">Pradėti tikslų paspaudimą</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />, <ph name="OPACITY_PERCENTAGE" /> % nepermatomumas.</translation>
 <translation id="8261506727792406068">Ištrinti</translation>
 <translation id="826825447994856889">Įžanga</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_lv.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_lv.xtb
index 10c4c2d..55d90ba9 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_lv.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_lv.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">sleja</translation>
 <translation id="6387719785439924554">malā novietots saturs</translation>
 <translation id="6393014464788431702">Atspējot visus notikumu filtrus</translation>
+<translation id="6406989068857078334">Samazināts peles ātrums. Vēlreiz <ph name="GESTURE" />, lai noklikšķinātu</translation>
 <translation id="6411569524720229058">Rudens</translation>
 <translation id="6417265370957905582">Google asistents</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{kols}zero{# kolu}one{# kols}other{# koli}}</translation>
@@ -1099,6 +1100,7 @@
 <translation id="8205922869661890178">Atvērt izstrādātāja žurnāla lapu</translation>
 <translation id="8212109599554677485">Mainīt displeja veidu uz attēlojumu līdzās</translation>
 <translation id="8215202828671303819">Vairāku elementu atlase</translation>
+<translation id="822316432305106615">Sākt precīzu klikšķi</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />, <ph name="OPACITY_PERCENTAGE" />% necaurredzamība.</translation>
 <translation id="8261506727792406068">Dzēst</translation>
 <translation id="826825447994856889">Ievads</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_mn.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_mn.xtb
index 1f09879..82f626b 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_mn.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_mn.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">багана</translation>
 <translation id="6387719785439924554">гадна</translation>
 <translation id="6393014464788431702">Үйл явдлын бүх шүүлтийг идэвхгүй болгох</translation>
+<translation id="6406989068857078334">Хулганын хурдыг багасгасан, товшихын тулд дахин <ph name="GESTURE" /></translation>
 <translation id="6411569524720229058">Намар</translation>
 <translation id="6417265370957905582">Google туслах</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{ тодорхойлох цэг}other{ # тодорхойлох цэг}}</translation>
@@ -1099,6 +1100,7 @@
 <translation id="8205922869661890178">Хөгжүүлэгчийн логийн хуудсыг нээх</translation>
 <translation id="8212109599554677485">Дэлгэцийн загварыг зэрэгцсэн болгож өөрчлөх</translation>
 <translation id="8215202828671303819">Олныг сонгох</translation>
+<translation id="822316432305106615">Нарийвчлалтай товшилтыг эхлүүлэх</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />, үл нэвтрүүлдэг чанар <ph name="OPACITY_PERCENTAGE" />%.</translation>
 <translation id="8261506727792406068">Устгах</translation>
 <translation id="826825447994856889">Оршил</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_mr.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_mr.xtb
index 1ff2a8a..df900a1 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_mr.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_mr.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">स्तंभ</translation>
 <translation id="6387719785439924554">बाजूस</translation>
 <translation id="6393014464788431702">सर्व इव्‍हेंट फिल्टर बंद करा</translation>
+<translation id="6406989068857078334">माउसचा स्पीड कमी केला आहे, क्लिक करण्यासाठी पुन्हा <ph name="GESTURE" /> करा</translation>
 <translation id="6411569524720229058">शरद ऋतू</translation>
 <translation id="6417265370957905582">Google Assistant</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{अपूर्ण विराम}other{# अपूर्ण विराम}}</translation>
@@ -1099,6 +1100,7 @@
 <translation id="8205922869661890178">डेव्हलपर लॉग पेज उघडा</translation>
 <translation id="8212109599554677485">डिस्प्ले शैली शेजारी-शेजारी वर बदला</translation>
 <translation id="8215202828671303819">एकाधिक निवड</translation>
+<translation id="822316432305106615">अचूक क्लिक सुरू करा</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />, <ph name="OPACITY_PERCENTAGE" />% अपारदर्शकता.</translation>
 <translation id="8261506727792406068">हटवा</translation>
 <translation id="826825447994856889">परिचय</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ne.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ne.xtb
index 46fb5997..2ed162c2 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ne.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ne.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">स्तम्भ</translation>
 <translation id="6387719785439924554">अलग</translation>
 <translation id="6393014464788431702">कार्यक्रमसम्बन्धी सबै फिल्टरहरू असक्षम पार्नुहोस्</translation>
+<translation id="6406989068857078334">माउसको गति कम भएको छ, क्लिक गर्न फेरि <ph name="GESTURE" /></translation>
 <translation id="6411569524720229058">शरद्</translation>
 <translation id="6417265370957905582">Google सहायक</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{ कोलोन}other{# कोलोनहरू}}</translation>
@@ -1099,6 +1100,7 @@
 <translation id="8205922869661890178">विकासकर्ताको लग पृष्ठ खोल्नुहोस्</translation>
 <translation id="8212109599554677485">प्रदर्शनको प्रकार परिवर्तन गरी "सँगसँगै" बनाउनुहोस्</translation>
 <translation id="8215202828671303819">बहु चयन</translation>
+<translation id="822316432305106615">"प्रिसिजन क्लिक" सुविधा सुरु गर्नुहोस्</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />, <ph name="OPACITY_PERCENTAGE" />% अस्पष्टता।</translation>
 <translation id="8261506727792406068">मेट्नुहोस्</translation>
 <translation id="826825447994856889">परिचय</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_pl.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_pl.xtb
index e0932a8..8ade203 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_pl.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_pl.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">kol.</translation>
 <translation id="6387719785439924554">aside</translation>
 <translation id="6393014464788431702">Wyłącz wszystkie filtry zdarzeń</translation>
+<translation id="6406989068857078334">Zmniejszono prędkość myszy. Aby kliknąć, wykonaj ponownie gest <ph name="GESTURE" /></translation>
 <translation id="6411569524720229058">Jesień</translation>
 <translation id="6417265370957905582">Asystent Google</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{dwukropek}few{# dwukropki}many{# dwukropków}other{# colons}}</translation>
@@ -1098,6 +1099,7 @@
 <translation id="8205922869661890178">Otwórz stronę dziennika dla dewelopera</translation>
 <translation id="8212109599554677485">Zmień styl wyświetlania na Obok siebie</translation>
 <translation id="8215202828671303819">Wybór wielokrotny</translation>
+<translation id="822316432305106615">Rozpocznij precyzyjne klikanie</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />, przezroczystość <ph name="OPACITY_PERCENTAGE" />%.</translation>
 <translation id="8261506727792406068">Usuń</translation>
 <translation id="826825447994856889">Wprowadzenie</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ro.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ro.xtb
index 056eddf7..5e1c720 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ro.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ro.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">coloană</translation>
 <translation id="6387719785439924554">separat</translation>
 <translation id="6393014464788431702">Dezactivează toate filtrele pentru evenimente</translation>
+<translation id="6406989068857078334">Viteza mouse-ului a fost redusă, <ph name="GESTURE" /> din nou pentru a da clic</translation>
 <translation id="6411569524720229058">Toamnă</translation>
 <translation id="6417265370957905582">Asistent Google</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{semn două puncte}few{# semne două puncte}other{# de semne două puncte}}</translation>
@@ -1099,6 +1100,7 @@
 <translation id="8205922869661890178">Deschide pagina de jurnal a dezvoltatorului</translation>
 <translation id="8212109599554677485">Schimbă stilul de afișare la alăturat</translation>
 <translation id="8215202828671303819">Selectare multiplă</translation>
+<translation id="822316432305106615">Inițiază clicul precis</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />, <ph name="OPACITY_PERCENTAGE" />% opacitate.</translation>
 <translation id="8261506727792406068">Șterge</translation>
 <translation id="826825447994856889">Introducere</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ru.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ru.xtb
index 2b33598c..c3c4fe0 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ru.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_ru.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">стлбц</translation>
 <translation id="6387719785439924554">aside</translation>
 <translation id="6393014464788431702">Отключить все фильтры событий</translation>
+<translation id="6406989068857078334">Скорость указателя для мыши снижена. Чтобы выполнить клик, сделайте жест "<ph name="GESTURE" />".</translation>
 <translation id="6411569524720229058">Осень</translation>
 <translation id="6417265370957905582">Google Ассистент</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{двоеточие}one{# двоеточие}few{# двоеточия}many{# двоеточий}other{# colons}}</translation>
@@ -1098,6 +1099,7 @@
 <translation id="8205922869661890178">Открыть страницу с журналом разработчика.</translation>
 <translation id="8212109599554677485">Изменить стиль дисплея на параллельный</translation>
 <translation id="8215202828671303819">Множественный выбор</translation>
+<translation id="822316432305106615">Выполнить точный клик</translation>
 <translation id="8249864170673238087">Цвет <ph name="COLOR" />, прозрачность <ph name="OPACITY_PERCENTAGE" /> %.</translation>
 <translation id="8261506727792406068">Удалить</translation>
 <translation id="826825447994856889">Введение</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sl.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sl.xtb
index d8d3588..3e6987b5 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sl.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sl.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">stol.</translation>
 <translation id="6387719785439924554">poleg</translation>
 <translation id="6393014464788431702">Onemogoči vse filtre dogodkov</translation>
+<translation id="6406989068857078334">Hitrost miške je zmanjšana, <ph name="GESTURE" /> znova za klik</translation>
 <translation id="6411569524720229058">Jesen</translation>
 <translation id="6417265370957905582">Pomočnik Google</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{dvopičje}one{# dvopičje}two{# dvopičji}few{# dvopičja}other{# dvopičij}}</translation>
@@ -1099,6 +1100,7 @@
 <translation id="8205922869661890178">Odpiranje strani z dnevniki razvijalca</translation>
 <translation id="8212109599554677485">Preklop na vzporedni slog prikaza</translation>
 <translation id="8215202828671303819">Sočasna izbira več elementov</translation>
+<translation id="822316432305106615">Začni natančen klik</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />, <ph name="OPACITY_PERCENTAGE" />-odstotna neprosojnost.</translation>
 <translation id="8261506727792406068">Izbriši</translation>
 <translation id="826825447994856889">Uvod</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sw.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sw.xtb
index f349d20..2966db1 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sw.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_sw.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">safu wima</translation>
 <translation id="6387719785439924554">kando</translation>
 <translation id="6393014464788431702">Zima vichujio vyote vya matukio</translation>
+<translation id="6406989068857078334">Kasi ya kipanya imepungua, <ph name="GESTURE" /> tena ili ubofye</translation>
 <translation id="6411569524720229058">Majira ya kupukutika</translation>
 <translation id="6417265370957905582">Mratibu wa Google</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{nuktambili}other{nuktambili #}}</translation>
@@ -1099,6 +1100,7 @@
 <translation id="8205922869661890178">Fungua ukurasa wa kumbukumbu za msanidi programu</translation>
 <translation id="8212109599554677485">Badilisha mtindo wa onyesho uwe upande kwa upande</translation>
 <translation id="8215202828671303819">Chaguo nyingi</translation>
+<translation id="822316432305106615">Anza kubofya kwa usahihi</translation>
 <translation id="8249864170673238087">Kutopitisha nuru kwa <ph name="COLOR" />, <ph name="OPACITY_PERCENTAGE" />%.</translation>
 <translation id="8261506727792406068">Futa</translation>
 <translation id="826825447994856889">Utangulizi</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_zh-HK.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_zh-HK.xtb
index 3ed9f81..e08377b7 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_zh-HK.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_zh-HK.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">欄</translation>
 <translation id="6387719785439924554">獨立元素</translation>
 <translation id="6393014464788431702">停用所有活動篩選器</translation>
+<translation id="6406989068857078334">滑鼠速度已減慢,再次<ph name="GESTURE" />即可執行點擊的動作</translation>
 <translation id="6411569524720229058">秋季</translation>
 <translation id="6417265370957905582">Google 助理</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{1 個冒號}other{# 個冒號}}</translation>
@@ -1098,6 +1099,7 @@
 <translation id="8205922869661890178">開啟開發人員記錄頁面</translation>
 <translation id="8212109599554677485">將顯示樣式變更為並排。</translation>
 <translation id="8215202828671303819">多重選取</translation>
+<translation id="822316432305106615">開始精準點擊</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />,<ph name="OPACITY_PERCENTAGE" />% 透明度。</translation>
 <translation id="8261506727792406068">刪除</translation>
 <translation id="826825447994856889">簡介</translation>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_zh-TW.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_zh-TW.xtb
index 7540258..7d0b7a9 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_zh-TW.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_zh-TW.xtb
@@ -845,6 +845,7 @@
 <translation id="6385591741672306837">欄</translation>
 <translation id="6387719785439924554">獨立元素</translation>
 <translation id="6393014464788431702">停用所有事件篩選器</translation>
+<translation id="6406989068857078334">滑鼠速度已降低,請再<ph name="GESTURE" />即可執行點選的動作</translation>
 <translation id="6411569524720229058">秋季</translation>
 <translation id="6417265370957905582">Google 助理</translation>
 <translation id="641759969622533235">{COUNT,plural, =1{冒號}other{# 個冒號}}</translation>
@@ -1099,6 +1100,7 @@
 <translation id="8205922869661890178">開啟開發人員記錄頁面</translation>
 <translation id="8212109599554677485">將顯示樣式變更為並排</translation>
 <translation id="8215202828671303819">多重選取</translation>
+<translation id="822316432305106615">開始精確點選</translation>
 <translation id="8249864170673238087"><ph name="COLOR" />,不透明度 <ph name="OPACITY_PERCENTAGE" />%。</translation>
 <translation id="8261506727792406068">刪除</translation>
 <translation id="826825447994856889">簡介</translation>
diff --git a/chrome/browser/resources/commerce/product_specifications/product_selection_menu.html b/chrome/browser/resources/commerce/product_specifications/product_selection_menu.html
index cf80a92..b92d255 100644
--- a/chrome/browser/resources/commerce/product_specifications/product_selection_menu.html
+++ b/chrome/browser/resources/commerce/product_specifications/product_selection_menu.html
@@ -71,7 +71,8 @@
       <div id="selectionContainer">
         <template is="dom-if"
             if="[[!showTableFullMessage_(forNewColumn, isTableFull)]]">
-          <template is="dom-repeat" items="[[sections]]" as="section">
+          <template is="dom-repeat" items="[[sections]]" as="section"
+              index-as="sectionIndex">
             <cr-expand-button expanded="{{section.expanded}}" no-hover
                 expand-icon="cr:arrow-drop-down"
                 collapse-icon="cr:arrow-drop-up">
@@ -87,8 +88,12 @@
                 </cr-url-list-item>
               </template>
               <!-- Add spacer instead of adding margin or padding to the -->
-              <!-- parent for smooth expand/collapse transitions. -->
-              <div class="dropdown-spacer"></div>
+              <!-- parent for smooth expand/collapse transitions for the -->
+              <!-- last section. -->
+              <template is="dom-if"
+                  if="[[isLastSection_(sections, sectionIndex)]]">
+                <div class="dropdown-spacer"></div>
+              </template>
             </cr-collapse>
           </template>
         </template>
diff --git a/chrome/browser/resources/commerce/product_specifications/product_selection_menu.ts b/chrome/browser/resources/commerce/product_specifications/product_selection_menu.ts
index 2f32313..509b2c0 100644
--- a/chrome/browser/resources/commerce/product_specifications/product_selection_menu.ts
+++ b/chrome/browser/resources/commerce/product_specifications/product_selection_menu.ts
@@ -193,6 +193,10 @@
       boolean {
     return forNewColumn && isTableFull;
   }
+
+  private isLastSection_(sections: MenuSection[], sectionIndex: number) {
+    return sections && sectionIndex === sections.length - 1;
+  }
 }
 
 declare global {
diff --git a/chrome/browser/resources/commerce/product_specifications/table.html b/chrome/browser/resources/commerce/product_specifications/table.html
index 44ebd169..730861a 100644
--- a/chrome/browser/resources/commerce/product_specifications/table.html
+++ b/chrome/browser/resources/commerce/product_specifications/table.html
@@ -56,7 +56,7 @@
 
   .main-image {
     background-color: white;
-    border: 1px solid var(--color-sys-base-container);
+    border: 1px solid var(--color-sys-divider);
     border-radius: 8px;
     box-sizing: border-box;
     cursor: pointer;
diff --git a/chrome/browser/resources/tab_search/declutter/declutter_page.css b/chrome/browser/resources/tab_search/declutter/declutter_page.css
index 57af1f82..548510ea 100644
--- a/chrome/browser/resources/tab_search/declutter/declutter_page.css
+++ b/chrome/browser/resources/tab_search/declutter/declutter_page.css
@@ -112,6 +112,10 @@
   background-color: transparent;
 }
 
+:host([dedupe-enabled]) .mwb-list-item {
+  --mwb-item-height: 32px;
+}
+
 .subheading {
   color: var(--cr-secondary-text-color);
   font-size: 12px;
diff --git a/chrome/browser/resources/tab_search/declutter/declutter_page.html.ts b/chrome/browser/resources/tab_search/declutter/declutter_page.html.ts
index 0468d49..a4d16794 100644
--- a/chrome/browser/resources/tab_search/declutter/declutter_page.html.ts
+++ b/chrome/browser/resources/tab_search/declutter/declutter_page.html.ts
@@ -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 {html} from '//resources/lit/v3_0/lit.rollup.js';
+import {html, nothing} from '//resources/lit/v3_0/lit.rollup.js';
 
 import type {TabData} from '../tab_data.js';
 
@@ -110,6 +110,7 @@
                                                    this.onDuplicateTabExclude_}"
         @focus="${this.onTabFocus_}"
         @blur="${this.onTabBlur_}"
+        compact=${this.dedupeEnabled || nothing}
         hide-url>
     </tab-search-item>
   `;
diff --git a/chrome/browser/resources/tab_search/declutter/declutter_page.ts b/chrome/browser/resources/tab_search/declutter/declutter_page.ts
index 9f07cf6..6faeee7 100644
--- a/chrome/browser/resources/tab_search/declutter/declutter_page.ts
+++ b/chrome/browser/resources/tab_search/declutter/declutter_page.ts
@@ -274,8 +274,14 @@
       const urlTabs = tabs[url]!;
       if (urlTabs.length > 0) {
         const tabData: TabData = this.tabDataFromTab_(urlTabs[0]!);
-        tabData.tab.title = url;
-        tabData.tab.lastActiveElapsedText = urlTabs.length.toString();
+        const duplicateCount = urlTabs.length - 1;
+        if (duplicateCount === 1) {
+          tabData.tab.title =
+              loadTimeData.getStringF('duplicateItemTitleSingle', url);
+        } else {
+          tabData.tab.title = loadTimeData.getStringF(
+              'duplicateItemTitleMulti', url, duplicateCount);
+        }
         this.duplicateTabDatas_.push(tabData);
       }
     }
diff --git a/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubFetchService.java b/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubFetchService.java
index d321dd9..231c7e4 100644
--- a/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubFetchService.java
+++ b/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubFetchService.java
@@ -223,6 +223,12 @@
      * signed-in profile.
      */
     private void fetchWeakCredentialsCount(Callback<Boolean> onFinishedCallback) {
+        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.SAFETY_HUB_WEAK_AND_REUSED_PASSWORDS)) {
+            mWeakCredentialsCountFetched = true;
+            onFetchCredentialsFinished(onFinishedCallback);
+            return;
+        }
+
         PasswordManagerHelper passwordManagerHelper = PasswordManagerHelper.getForProfile(mProfile);
         PrefService prefService = UserPrefs.get(mProfile);
 
@@ -246,6 +252,12 @@
      * signed-in profile.
      */
     private void fetchReusedCredentialsCount(Callback<Boolean> onFinishedCallback) {
+        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.SAFETY_HUB_WEAK_AND_REUSED_PASSWORDS)) {
+            mReusedCredentialsCountFetched = true;
+            onFetchCredentialsFinished(onFinishedCallback);
+            return;
+        }
+
         PasswordManagerHelper passwordManagerHelper = PasswordManagerHelper.getForProfile(mProfile);
         PrefService prefService = UserPrefs.get(mProfile);
 
diff --git a/chrome/browser/safety_hub/android/junit/src/org/chromium/chrome/browser/safety_hub/SafetyHubFetchServiceTest.java b/chrome/browser/safety_hub/android/junit/src/org/chromium/chrome/browser/safety_hub/SafetyHubFetchServiceTest.java
index dcc3f4e..58c5dccd 100644
--- a/chrome/browser/safety_hub/android/junit/src/org/chromium/chrome/browser/safety_hub/SafetyHubFetchServiceTest.java
+++ b/chrome/browser/safety_hub/android/junit/src/org/chromium/chrome/browser/safety_hub/SafetyHubFetchServiceTest.java
@@ -93,7 +93,10 @@
     }
 
     @Test
-    @Features.DisableFeatures(ChromeFeatureList.SAFETY_HUB)
+    @Features.DisableFeatures({
+        ChromeFeatureList.SAFETY_HUB,
+        ChromeFeatureList.SAFETY_HUB_WEAK_AND_REUSED_PASSWORDS
+    })
     public void testTaskCancelled_WhenConditionsNotMet() {
         new SafetyHubFetchService(mProfile).onForegroundSessionStart();
 
@@ -149,7 +152,10 @@
     }
 
     @Test
-    @Features.EnableFeatures(ChromeFeatureList.SAFETY_HUB)
+    @Features.EnableFeatures({
+        ChromeFeatureList.SAFETY_HUB,
+        ChromeFeatureList.SAFETY_HUB_WEAK_AND_REUSED_PASSWORDS
+    })
     public void testTaskRescheduled_whenFetchFails() {
         mPasswordCheckupClientHelper.setError(new Exception());
 
@@ -162,7 +168,10 @@
     }
 
     @Test
-    @Features.EnableFeatures(ChromeFeatureList.SAFETY_HUB)
+    @Features.EnableFeatures({
+        ChromeFeatureList.SAFETY_HUB,
+        ChromeFeatureList.SAFETY_HUB_WEAK_AND_REUSED_PASSWORDS
+    })
     public void testTaskRescheduled_whenFetchFailsForOneCredentialType() {
         mPasswordCheckupClientHelper.setWeakCredentialsError(new Exception());
         int breachedCredentialsCount = 5;
@@ -181,7 +190,10 @@
     }
 
     @Test
-    @Features.EnableFeatures(ChromeFeatureList.SAFETY_HUB)
+    @Features.EnableFeatures({
+        ChromeFeatureList.SAFETY_HUB,
+        ChromeFeatureList.SAFETY_HUB_WEAK_AND_REUSED_PASSWORDS
+    })
     public void testNextTaskScheduled_WhenFetchSucceeds() {
         int breachedCredentialsCount = 5;
         int weakCredentialsCount = 4;
diff --git a/chrome/browser/segmentation_platform/BUILD.gn b/chrome/browser/segmentation_platform/BUILD.gn
index 791786e..7f2253bb 100644
--- a/chrome/browser/segmentation_platform/BUILD.gn
+++ b/chrome/browser/segmentation_platform/BUILD.gn
@@ -46,6 +46,26 @@
   generate_jni("jni_headers") {
     sources = [ "android/java/src/org/chromium/chrome/browser/segmentation_platform/SegmentationPlatformServiceFactory.java" ]
   }
+
+  android_library("client_util_java") {
+    srcjar_deps = [ ":client_util_jni_headers" ]
+    sources = [ "android/java/src/org/chromium/chrome/browser/segmentation_platform/client_util/HomeModulesRankingHelper.java" ]
+
+    deps = [
+      ":factory_java",
+      "//base:base_java",
+      "//build/android:build_java",
+      "//chrome/browser/flags:java",
+      "//chrome/browser/profiles/android:java",
+      "//components/segmentation_platform/public:public_java",
+      "//third_party/androidx:androidx_annotation_annotation_java",
+      "//third_party/androidx:androidx_annotation_annotation_java",
+      "//third_party/jni_zero:jni_zero_java",
+    ]
+  }
+  generate_jni("client_util_jni_headers") {
+    sources = [ "android/java/src/org/chromium/chrome/browser/segmentation_platform/client_util/HomeModulesRankingHelper.java" ]
+  }
 }
 
 static_library("test_utils") {
diff --git a/chrome/browser/segmentation_platform/android/home_modules_ranking_helper.cc b/chrome/browser/segmentation_platform/android/home_modules_ranking_helper.cc
new file mode 100644
index 0000000..e97b7ae
--- /dev/null
+++ b/chrome/browser/segmentation_platform/android/home_modules_ranking_helper.cc
@@ -0,0 +1,90 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <jni.h>
+
+#include "base/android/callback_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/android/jni_weak_ref.h"
+#include "base/memory/raw_ptr.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/segmentation_platform/segmentation_platform_service_factory.h"
+#include "components/segmentation_platform/embedder/home_modules/constants.h"
+#include "components/segmentation_platform/embedder/home_modules/home_modules_card_registry.h"
+#include "components/segmentation_platform/public/android/input_context_android.h"
+#include "components/segmentation_platform/public/android/prediction_options_android.h"
+#include "components/segmentation_platform/public/android/segmentation_platform_conversion_bridge.h"
+#include "components/segmentation_platform/public/segmentation_platform_service.h"
+
+// Must come after all headers that specialize FromJniType() / ToJniType().
+#include "chrome/browser/segmentation_platform/client_util_jni_headers/HomeModulesRankingHelper_jni.h"
+
+using ::base::android::AttachCurrentThread;
+using ::base::android::ConvertJavaStringToUTF8;
+using ::base::android::JavaParamRef;
+using ::base::android::ScopedJavaGlobalRef;
+using ::jni_zero::JavaRef;
+
+namespace {
+
+void RunGetClassificationResultCallback(
+    const JavaRef<jobject>& j_callback,
+    const segmentation_platform::ClassificationResult& result) {
+  JNIEnv* env = AttachCurrentThread();
+  base::android::RunObjectCallbackAndroid(
+      j_callback, segmentation_platform::SegmentationPlatformConversionBridge::
+                      CreateJavaClassificationResult(env, result));
+}
+
+}  // namespace
+
+static void JNI_HomeModulesRankingHelper_GetClassificationResult(
+    JNIEnv* env,
+    Profile* profile,
+    const jni_zero::JavaParamRef<jobject>& prediction_options,
+    const jni_zero::JavaParamRef<jobject>& input_context,
+    const jni_zero::JavaParamRef<jobject>& callback) {
+  segmentation_platform::SegmentationPlatformService* service =
+      segmentation_platform::SegmentationPlatformServiceFactory::GetForProfile(
+          profile);
+  segmentation_platform::home_modules::HomeModulesCardRegistry* registry =
+      segmentation_platform::SegmentationPlatformServiceFactory::
+          GetHomeModulesCardRegistry(profile);
+  scoped_refptr<segmentation_platform::InputContext> native_input_context =
+      segmentation_platform::InputContextAndroid::ToNativeInputContext(
+          env, input_context);
+
+  segmentation_platform::PredictionOptions native_prediction_options =
+      segmentation_platform::PredictionOptionsAndroid::
+          ToNativePredictionOptions(env, prediction_options);
+  registry->get_rank_fecther_helper()->GetHomeModulesRank(
+      service, native_prediction_options, native_input_context,
+      base::BindOnce(&RunGetClassificationResultCallback,
+                     ScopedJavaGlobalRef<jobject>(callback)));
+}
+
+static void JNI_HomeModulesRankingHelper_NotifyCardShown(
+    JNIEnv* env,
+    Profile* profile,
+    const JavaParamRef<jstring>& card_label) {
+  DCHECK(profile);
+  segmentation_platform::home_modules::HomeModulesCardRegistry* registry =
+      segmentation_platform::SegmentationPlatformServiceFactory::
+          GetHomeModulesCardRegistry(profile);
+  std::string native_card_label = ConvertJavaStringToUTF8(env, card_label);
+  registry->NotifyCardShown(native_card_label.c_str());
+}
+
+static void JNI_HomeModulesRankingHelper_NotifyCardInteracted(
+    JNIEnv* env,
+    Profile* profile,
+    const JavaParamRef<jstring>& card_label) {
+  DCHECK(profile);
+  segmentation_platform::home_modules::HomeModulesCardRegistry* registry =
+      segmentation_platform::SegmentationPlatformServiceFactory::
+          GetHomeModulesCardRegistry(profile);
+  std::string native_card_label = ConvertJavaStringToUTF8(env, card_label);
+  registry->NotifyCardInteracted(native_card_label.c_str());
+}
diff --git a/chrome/browser/segmentation_platform/android/java/src/org/chromium/chrome/browser/segmentation_platform/client_util/HomeModulesRankingHelper.java b/chrome/browser/segmentation_platform/android/java/src/org/chromium/chrome/browser/segmentation_platform/client_util/HomeModulesRankingHelper.java
new file mode 100644
index 0000000..1aa6084
--- /dev/null
+++ b/chrome/browser/segmentation_platform/android/java/src/org/chromium/chrome/browser/segmentation_platform/client_util/HomeModulesRankingHelper.java
@@ -0,0 +1,96 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+package org.chromium.chrome.browser.segmentation_platform.client_util;
+
+import androidx.annotation.NonNull;
+
+import org.jni_zero.JniType;
+import org.jni_zero.NativeMethods;
+
+import org.chromium.base.Callback;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.components.segmentation_platform.ClassificationResult;
+import org.chromium.components.segmentation_platform.InputContext;
+import org.chromium.components.segmentation_platform.PredictionOptions;
+import org.chromium.components.segmentation_platform.prediction_status.PredictionStatus;
+
+import java.util.List;
+
+/** Helper class to fetch module order. */
+public final class HomeModulesRankingHelper {
+    /**
+     * Fetches the module rank including both stable and ephemeral modules.
+     *
+     * @param profile the profile to fetch the module
+     * @param freshnessAndEphemeralInputs the input context for the request with all signals for
+     *     modules
+     * @param callback the callback to be called when the module rank is fetched
+     */
+    public static void fetchModulesRank(
+            @NonNull Profile profile,
+            @NonNull InputContext freshnessAndEphemeralInputs,
+            @NonNull Callback<List<String>> callback) {
+        HomeModulesRankingHelperJni.get()
+                .getClassificationResult(
+                        profile,
+                        createPredictionOptions(),
+                        /* inputContext= */ freshnessAndEphemeralInputs,
+                        result -> {
+                            assert result.status == PredictionStatus.SUCCEEDED;
+                            callback.onResult(result.orderedLabels);
+                        });
+    }
+
+    /**
+     * Notifies the module ranker that the card has been interacted with.
+     *
+     * @param profile the profile to notify the module ranker
+     * @param moduleLabel the module label to notify the module ranker
+     */
+    public static void notifyCardInteracted(@NonNull Profile profile, @NonNull String moduleLabel) {
+        HomeModulesRankingHelperJni.get().notifyCardInteracted(profile, moduleLabel);
+    }
+
+    /**
+     * Notifies the module ranker that the card has been shown.
+     *
+     * @param profile the profile to notify the module ranker
+     * @param moduleLabel the module label to notify the module ranker
+     */
+    public static void notifyCardShown(@NonNull Profile profile, @NonNull String moduleLabel) {
+        HomeModulesRankingHelperJni.get().notifyCardShown(profile, moduleLabel);
+    }
+
+    /**
+     * Creates an instance of PredictionOptions. If feature flag is enabled generate ondemand
+     * prediction options else will generate cache prediction options.
+     */
+    private static PredictionOptions createPredictionOptions() {
+        boolean usePredictionOptions =
+                ChromeFeatureList.isEnabled(
+                        ChromeFeatureList.SEGMENTATION_PLATFORM_ANDROID_HOME_MODULE_RANKER_V2);
+        if (usePredictionOptions) {
+            return new PredictionOptions(
+                    /* onDemandExecution= */ true,
+                    /* canUpdateCacheForFutureRequests= */ true,
+                    /* fallbackAllowed= */ true);
+        } else {
+            return new PredictionOptions(/* on_demand= */ false);
+        }
+    }
+
+    @NativeMethods
+    public interface Natives {
+        void getClassificationResult(
+                @JniType("Profile*") Profile profile,
+                PredictionOptions predictionOptions,
+                InputContext inputContext,
+                Callback<ClassificationResult> callback);
+
+        void notifyCardShown(@JniType("Profile*") Profile profile, String cardLabel);
+
+        void notifyCardInteracted(@JniType("Profile*") Profile profile, String cardLabel);
+    }
+}
diff --git a/chrome/browser/signin/signin_promo_util.cc b/chrome/browser/signin/signin_promo_util.cc
index 273658a..79a81c2 100644
--- a/chrome/browser/signin/signin_promo_util.cc
+++ b/chrome/browser/signin/signin_promo_util.cc
@@ -27,8 +27,8 @@
 #include "chrome/browser/signin/chrome_signin_pref_names.h"
 #include "chrome/browser/signin/signin_ui_util.h"
 #include "chrome/browser/signin/signin_util.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/browser/profile_requirement_utils.h"
 
 namespace {
 
diff --git a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
index 6bc456a0..b13776e 100644
--- a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
@@ -20,10 +20,10 @@
 #include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h"
 #include "chrome/browser/sync/test/integration/wallet_helper.h"
 #include "chrome/browser/webdata_services/web_data_service_factory.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/autofill/core/browser/data_model/credit_card_cloud_token_data.h"
 #include "components/autofill/core/browser/data_model/payments_metadata.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics.h"
 #include "components/autofill/core/browser/payments/payments_customer_data.h"
diff --git a/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc b/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc
index d73c7210..dd95988 100644
--- a/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc
@@ -12,10 +12,10 @@
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality_test_api.h"
 #include "components/autofill/core/browser/payments_data_manager.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/browser/profile_token_quality.h"
-#include "components/autofill/core/browser/profile_token_quality_test_api.h"
 #include "components/autofill/core/browser/webdata/autofill_table_utils.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/sync/engine/cycle/entity_change_metric_recording.h"
diff --git a/chrome/browser/sync/test/integration/wallet_helper.cc b/chrome/browser/sync/test/integration/wallet_helper.cc
index 07fa2e8..d9eba74 100644
--- a/chrome/browser/sync/test/integration/wallet_helper.cc
+++ b/chrome/browser/sync/test/integration/wallet_helper.cc
@@ -14,8 +14,8 @@
 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/browser/webdata_services/web_data_service_factory.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/data_model/payments_metadata.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/payments/payments_customer_data.h"
 #include "components/autofill/core/browser/payments_data_manager.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 977b322..e19010fc 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1239,6 +1239,8 @@
       "tabs/organization/trigger_observer.h",
       "tabs/organization/trigger_policies.cc",
       "tabs/organization/trigger_policies.h",
+      "tabs/saved_tab_groups/collaboration_messaging_tab_data.cc",
+      "tabs/saved_tab_groups/collaboration_messaging_tab_data.h",
       "tabs/saved_tab_groups/local_tab_group_listener.cc",
       "tabs/saved_tab_groups/local_tab_group_listener.h",
       "tabs/saved_tab_groups/saved_tab_group_controller.h",
diff --git a/chrome/browser/ui/actions/chrome_action_id.h b/chrome/browser/ui/actions/chrome_action_id.h
index f22b994..18c17c11 100644
--- a/chrome/browser/ui/actions/chrome_action_id.h
+++ b/chrome/browser/ui/actions/chrome_action_id.h
@@ -335,6 +335,8 @@
   E(kActionContentContextExitFullscreen, IDC_CONTENT_CONTEXT_EXIT_FULLSCREEN) \
   E(kActionContentContextShowAllSavedPasswords, \
     IDC_CONTENT_CONTEXT_SHOWALLSAVEDPASSWORDS) \
+  E(kActionContentContextUsePasskeyFromAnotherDeviceTopLevel, \
+    IDC_CONTENT_CONTEXT_USE_PASSKEY_FROM_ANOTHER_DEVICE) \
   E(kActionContentContextPartialTranslate, \
     IDC_CONTENT_CONTEXT_PARTIAL_TRANSLATE) \
   /* Frame items. */ \
diff --git a/chrome/browser/ui/android/fast_checkout/ui_view_android_utils.cc b/chrome/browser/ui/android/fast_checkout/ui_view_android_utils.cc
index 9f78370a..99950ee 100644
--- a/chrome/browser/ui/android/fast_checkout/ui_view_android_utils.cc
+++ b/chrome/browser/ui/android/fast_checkout/ui_view_android_utils.cc
@@ -9,7 +9,7 @@
 #include "base/android/jni_string.h"
 #include "base/strings/utf_string_conversion_utils.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/geo/autofill_country.h"
 #include "url/android/gurl_android.h"
 
diff --git a/chrome/browser/ui/android/fast_checkout/ui_view_android_utils_unittest.cc b/chrome/browser/ui/android/fast_checkout/ui_view_android_utils_unittest.cc
index d6b144f..ff4a46c 100644
--- a/chrome/browser/ui/android/fast_checkout/ui_view_android_utils_unittest.cc
+++ b/chrome/browser/ui/android/fast_checkout/ui_view_android_utils_unittest.cc
@@ -5,9 +5,9 @@
 #include "chrome/browser/ui/android/fast_checkout/ui_view_android_utils.h"
 
 #include "base/android/jni_android.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ar.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ar.xtb
index c1d2adf..2cae9c4 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ar.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ar.xtb
@@ -218,7 +218,7 @@
 <translation id="1963056249988316027">‏ميزة Identity Check مفعَّلة ولكن يتعذّر تأكيد هويتك</translation>
 <translation id="1963976881984600709">الحماية العادية</translation>
 <translation id="1966710179511230534">يُرجى تحديث تفاصيل تسجيل الدخول.</translation>
-<translation id="1969037871259811890">‏لا يؤدي حذف بيانات التصفّح إلى تسجيل خروجك من حسابك على Google. لإجراء ذلك، <ph name="BEGIN_LINK1" />سجِّل الخروج من Chrome<ph name="END_LINK1" />.</translation>
+<translation id="1969037871259811890">‏لا يؤدي حذف بيانات التصفّح إلى تسجيل خروجك من حسابك على Google. لإجراء ذلك، يجب <ph name="BEGIN_LINK1" />تسجيل الخروج من Chrome<ph name="END_LINK1" />.</translation>
 <translation id="197288927597451399">مواصلة</translation>
 <translation id="1973912524893600642">الاحتفاظ بالبيانات</translation>
 <translation id="1974060860693918893">الإعدادات المتقدّمة</translation>
@@ -473,7 +473,7 @@
 <translation id="3067505415088964188">السعر منخفض</translation>
 <translation id="3070005020161560471">لغات أريد ترجمتها تلقائيًا</translation>
 <translation id="3072980200212375806">‏سيتم فتح تطبيق "<ph name="APP_NAME" />" في Chrome. تعني المتابعة موافقتك على <ph name="BEGIN_LINK1" />بنود خدمة Google<ph name="END_LINK1" /> و<ph name="BEGIN_LINK2" />بنود الخدمة الإضافية لكل من متصفّح Google Chrome ونظام التشغيل Chrome<ph name="END_LINK2" />، علمًا بأنّ <ph name="BEGIN_LINK3" />سياسة الخصوصية<ph name="END_LINK3" /> تسري أيضًا.</translation>
-<translation id="3080525922482950719">يمكنك حفظ صفحات لقرائتها لاحقًا أو بلا إنترنت.</translation>
+<translation id="3080525922482950719">يمكنك حفظ صفحات لقراءتها لاحقًا أو بلا إنترنت</translation>
 <translation id="3087734570205094154">أسفل</translation>
 <translation id="3091010850649238832">عرض محتوى الحافظة</translation>
 <translation id="3098745985164956033">‏يتم إرسال بعض الصور إلى Google لتحسين أوصاف الصور.</translation>
@@ -972,7 +972,7 @@
 <translation id="543338862236136125">تعديل كلمة المرور</translation>
 <translation id="5433691172869980887">تم نسخ اسم المستخدم</translation>
 <translation id="5438292632479953702">تنزيل الملف مرة أخرى</translation>
-<translation id="5439191312780166229">‏ستتلقّى تحذيرات بشأن المواقع الإلكترونية الخطيرة، بما فيها المواقع التي لم يتعرّف عليها محرك البحث Google من قَبل، من خلال تحليل بيانات من المواقع الإلكترونية أكثر من الحماية العادية. يمكنك اختيار تخطّي تحذيرات Chrome.</translation>
+<translation id="5439191312780166229">‏ستتلقّى تحذيرات بشأن المواقع الإلكترونية الخطيرة، بما فيها المواقع الإلكترونية التي لم يتعرّف عليها محرك بحث Google، من خلال تحليل قدر أكبر من البيانات الواردة من المواقع الإلكترونية، مقارنةً بالحماية العادية. يمكنك اختيار تخطّي تحذيرات Chrome.</translation>
 <translation id="5441137934526263133">هل تواجهك مشكلة في الموقع الإلكتروني؟ تم حظر ملفات تعريف الارتباط التابعة لجهات خارجية.</translation>
 <translation id="5441466871879044658">ترجمة لهذه اللغة</translation>
 <translation id="5441522332038954058">الانتقال السريع إلى شريط العناوين</translation>
@@ -1122,7 +1122,7 @@
 <translation id="6107864469867367783">تم تغيير اسم المجموعة من قِبل "<ph name="USER_DISPLAY_NAME" />"</translation>
 <translation id="6108923351542677676">الإعداد قيد التقدّم…</translation>
 <translation id="6112702117600201073">يتم الآن إعادة تحميل الصفحة</translation>
-<translation id="6122831415929794347">هل تريد إيقاف "التصفُّح الآمن"؟</translation>
+<translation id="6122831415929794347">هل المطلوب إيقاف "التصفُّح الآمن"؟</translation>
 <translation id="6125202119952209826">الانضمام إلى مجموعة علامات التبويب التي تضمّ "<ph name="OWNER_FIRST_NAME" />"</translation>
 <translation id="6125864963080902918"><ph name="BEGIN_LINK" />المزيد من التفاصيل<ph name="END_LINK" /></translation>
 <translation id="6127379762771434464">أُزيلَ عنصر</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_et.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_et.xtb
index be3c73db..f713719 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_et.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_et.xtb
@@ -336,7 +336,7 @@
 <translation id="2534155362429831547"><ph name="NUMBER_OF_ITEMS" /> üksust kustutati</translation>
 <translation id="253498598929009420">Sait näeb teie ekraanikuval olevat sisu</translation>
 <translation id="2536728043171574184">Kuvatakse on lehe võrguühenduseta koopia</translation>
-<translation id="2546283357679194313">Küpsised ja saidiandmed</translation>
+<translation id="2546283357679194313">Küpsised ja saidi andmed</translation>
 <translation id="2547843573592965873">Teie profiililukk kaitseb autos teie teavet, sh paroole, makseid ja muud, mis on salvestatud teie Google'i kontole.</translation>
 <translation id="254973855621628293">Sellesse seadmesse salvestatud paroolid</translation>
 <translation id="2560519950693256002">Hiljuti kontrollitud paroolid salvestati kasutajale <ph name="USERNAME" /></translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ja.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ja.xtb
index 7727e7a..828665f3 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ja.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ja.xtb
@@ -1321,7 +1321,7 @@
 <translation id="6896758677409633944">コピー</translation>
 <translation id="6898797562238201317">独自のパスフレーズを使用して Google アカウントの Chrome データをすべて暗号化する</translation>
 <translation id="6900532703269623216">保護強化機能</translation>
-<translation id="6903907808598579934">同期を ON にする</translation>
+<translation id="6903907808598579934">同期をオンにする</translation>
 <translation id="6906448540340261898">Google アカウントのパスワードを常に使用できるようにしてください</translation>
 <translation id="6908230663105268638"><ph name="SITE_NAME" /> の通知が許可されています</translation>
 <translation id="6908998565271542516">ウェブサイトを承認するかどうかを決定するオプション(最大の高さで表示)</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_nl.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_nl.xtb
index fbbe84c..e7de2f7 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_nl.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_nl.xtb
@@ -409,7 +409,7 @@
 <translation id="2841216154655874070">{NUM_DAYS,plural, =1{1 dag geleden gecheckt}other{# dagen geleden gecheckt}}</translation>
 <translation id="2842985007712546952">Bovenliggende map</translation>
 <translation id="2854916915045135148">Houd je vinger hierop om te wisselen naar de incognitomodus</translation>
-<translation id="2855243985454069333">Hiermee wordt de geschiedenis van al je gesynchroniseerde apparaten verwijderd</translation>
+<translation id="2855243985454069333">Hiermee wordt de geschiedenis van al je gesynchroniseerde apparaten verwijderd.</translation>
 <translation id="2860954141821109167">Zorg ervoor dat een telefoon-app aanstaat op dit apparaat</translation>
 <translation id="2861923151411510142">Sommige Chrome-functies zijn niet meer beschikbaar</translation>
 <translation id="2869430948265924908">Als je je gevoelige content in de auto wilt beschermen, stel je een profielvergrendeling voor je auto in.  Dit kun je doen met een pincode, code of wachtwoord.</translation>
@@ -702,7 +702,7 @@
 <translation id="4248098802131000011">Bescherm je wachtwoorden tegen gegevenslekken en andere beveiligingsproblemen</translation>
 <translation id="424864128008805179">Uitloggen bij Chrome?</translation>
 <translation id="4249955472157341256">Sorteren op nieuwste</translation>
-<translation id="4255841059940367080">Realtime, AI-gestuurde bescherming tegen gevaarlijke sites, downloads en extensies op basis van je browsegegevens die naar Google worden gestuurd</translation>
+<translation id="4255841059940367080">Realtime, AI-gestuurde bescherming tegen gevaarlijke sites, downloads en extensies op basis van je browsegegevens die naar Google worden gestuurd.</translation>
 <translation id="4256782883801055595">Opensource-licenties</translation>
 <translation id="4257230861809842349">Wachtwoorden verwijderen uit Google Wachtwoordmanager?</translation>
 <translation id="426652736638196239">Dit IBAN-nummer wordt alleen op dit apparaat opgeslagen</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sl.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sl.xtb
index 0e22e1cd..cba88ab7 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sl.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sl.xtb
@@ -526,7 +526,7 @@
 <translation id="3387650086002190359">Prenos datoteke <ph name="FILE_NAME" /> ni uspel zaradi napak v datotečnem sistemu.</translation>
 <translation id="3398320232533725830">Odpiranje upravitelja zaznamkov</translation>
 <translation id="3414952576877147120">Velikost:</translation>
-<translation id="3421726884497337397">Izberite, kdaj blokirate piškotke drugih mest</translation>
+<translation id="3421726884497337397">Izberite, kdaj blokirate piškotke tretjih oseb</translation>
 <translation id="342220687432920852">{HOURS,plural, =1{Pred # h}one{Pred # h}two{Pred # h}few{Pred # h}other{Pred # h}}</translation>
 <translation id="3430670036890315772">Če izklopite zaklepanje profila, se shranjeni podatki odstranijo</translation>
 <translation id="3435465986463792564">Imate odprtih veliko oken? Tukaj jih lahko upravljate.</translation>
@@ -971,7 +971,7 @@
 <translation id="5433691172869980887">Uporabniško ime kopirano</translation>
 <translation id="5438292632479953702">Znova prenesi</translation>
 <translation id="5439191312780166229">Opozori vas o nevarnih spletnih mestih, celo tistih, za katere Google prej ni vedel, in sicer tako, da analizira več podatkov s spletnih mest kot standardna zaščita. Izberete lahko, da preskočite opozorila za Chrome.</translation>
-<translation id="5441137934526263133">Ali spletno mesto ne deluje? Piškotki drugih spletnih mest so blokirani.</translation>
+<translation id="5441137934526263133">Ali spletno mesto ne deluje? Piškotki tretjih oseb so blokirani.</translation>
 <translation id="5441466871879044658">Prevedi v ta jezik</translation>
 <translation id="5441522332038954058">Premik na naslovno vrstico</translation>
 <translation id="5444999712122199445">Nazaj na spletno mesto</translation>
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 1224867..7cf0425 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
@@ -20,12 +20,10 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnClickListener;
-import android.view.ViewGroup;
 import android.view.ViewStub;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.ImageButton;
 import android.widget.ImageView;
-import android.widget.LinearLayout;
 
 import androidx.annotation.ColorInt;
 import androidx.annotation.ColorRes;
@@ -83,8 +81,6 @@
         void downloadPage(Context context, Tab tab);
     }
 
-    private static final int HOME_BUTTON_POSITION_FOR_TAB_STRIP_REDESIGN = 3;
-
     private ImageButton mHomeButton;
     private ImageButton mBackButton;
     private ImageButton mForwardButton;
@@ -132,10 +128,6 @@
                 getResources().getDimensionPixelOffset(R.dimen.toolbar_edge_padding);
     }
 
-    public boolean isToolbarButtonReorderingEnabled() {
-        return ChromeFeatureList.sTabletToolbarReordering.isEnabled();
-    }
-
     @Override
     public void onFinishInflate() {
         super.onFinishInflate();
@@ -144,16 +136,6 @@
         mForwardButton = findViewById(R.id.forward_button);
         mReloadButton = findViewById(R.id.refresh_button);
 
-        // Reposition home button to align with desktop ordering when TSR enabled and toolbar
-        // reordering not disabled
-        if (isToolbarButtonReorderingEnabled()) {
-            // Remove home button view added in XML and adding back with different ordering
-            // programmatically.
-            ((ViewGroup) mHomeButton.getParent()).removeView(mHomeButton);
-            LinearLayout linearlayout = (LinearLayout) findViewById(R.id.toolbar_tablet_layout);
-            linearlayout.addView(mHomeButton, HOME_BUTTON_POSITION_FOR_TAB_STRIP_REDESIGN);
-        }
-
         // 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
@@ -225,26 +207,18 @@
                 new KeyboardNavigationListener() {
                     @Override
                     public View getNextFocusForward() {
-                        if (isToolbarButtonReorderingEnabled()) {
-                            return findViewById(R.id.url_bar);
+                        if (mBackButton.isFocusable()) {
+                            return findViewById(R.id.back_button);
+                        } else if (mForwardButton.isFocusable()) {
+                            return findViewById(R.id.forward_button);
                         } else {
-                            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);
-                            }
+                            return findViewById(R.id.refresh_button);
                         }
                     }
 
                     @Override
                     public View getNextFocusBackward() {
-                        if (isToolbarButtonReorderingEnabled()) {
-                            return findViewById(R.id.refresh_button);
-                        } else {
-                            return findViewById(R.id.menu_button);
-                        }
+                        return findViewById(R.id.menu_button);
                     }
                 });
 
@@ -263,14 +237,10 @@
 
                     @Override
                     public View getNextFocusBackward() {
-                        if (isToolbarButtonReorderingEnabled()) {
-                            return findViewById(R.id.menu_button);
+                        if (mHomeButton.getVisibility() == VISIBLE) {
+                            return findViewById(R.id.home_button);
                         } else {
-                            if (mHomeButton.getVisibility() == VISIBLE) {
-                                return findViewById(R.id.home_button);
-                            } else {
-                                return findViewById(R.id.menu_button);
-                            }
+                            return findViewById(R.id.menu_button);
                         }
                     }
                 });
@@ -288,8 +258,7 @@
                     public View getNextFocusBackward() {
                         if (mBackButton.isFocusable()) {
                             return mBackButton;
-                        } else if (!isToolbarButtonReorderingEnabled()
-                                && mHomeButton.getVisibility() == VISIBLE) {
+                        } else if (mHomeButton.getVisibility() == VISIBLE) {
                             return findViewById(R.id.home_button);
                         } else {
                             return findViewById(R.id.menu_button);
@@ -303,12 +272,7 @@
                 new KeyboardNavigationListener() {
                     @Override
                     public View getNextFocusForward() {
-                        if (isToolbarButtonReorderingEnabled()
-                                && mHomeButton.getVisibility() == VISIBLE) {
-                            return findViewById(R.id.home_button);
-                        } else {
-                            return findViewById(R.id.url_bar);
-                        }
+                        return findViewById(R.id.url_bar);
                     }
 
                     @Override
@@ -317,8 +281,7 @@
                             return mForwardButton;
                         } else if (mBackButton.isFocusable()) {
                             return mBackButton;
-                        } else if (!isToolbarButtonReorderingEnabled()
-                                && mHomeButton.getVisibility() == VISIBLE) {
+                        } else if (mHomeButton.getVisibility() == VISIBLE) {
                             return findViewById(R.id.home_button);
                         } else {
                             return findViewById(R.id.menu_button);
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTabletUnitTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTabletUnitTest.java
index 8d30b44..515e577 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTabletUnitTest.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTabletUnitTest.java
@@ -255,29 +255,6 @@
     }
 
     @Test
-    @EnableFeatures({ChromeFeatureList.TABLET_TOOLBAR_REORDERING})
-    public void testButtonPosition_TSR() {
-        mToolbarTablet.onFinishInflate();
-        assertEquals(
-                "Back button position is not as expected for Tab Strip Redesign",
-                mBackButton,
-                mToolbarTabletLayout.getChildAt(0));
-        assertEquals(
-                "Forward button position is not as expected for Tab Strip Redesign",
-                mForwardButton,
-                mToolbarTabletLayout.getChildAt(1));
-        assertEquals(
-                "Reloading button position is not as expected for Tab Strip Redesign",
-                mReloadingButton,
-                mToolbarTabletLayout.getChildAt(2));
-        assertEquals(
-                "Home button position is not as expected for Tab Strip Redesign",
-                mHomeButton,
-                mToolbarTabletLayout.getChildAt(3));
-    }
-
-    @Test
-    @DisableFeatures(ChromeFeatureList.TABLET_TOOLBAR_REORDERING)
     public void testButtonPosition_ShutoffToolbarReordering() {
         mToolbarTablet.onFinishInflate();
 
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc
index ebbcca1..e5bde22 100644
--- a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc
+++ b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc
@@ -762,6 +762,10 @@
   }
 
   void TearDown() override {
+    // Drop user pref service reference before `profile_` is released. This is
+    // needed because `profile_` is owned by the test not `TestProfileManager`.
+    ash_test_helper()->prefs_provider()->ClearUnownedUserPrefs(
+        AccountId::FromUserEmail(profile_->GetProfileUserName()));
     profile_.reset();
     HoldingSpaceKeyedServiceWithExperimentalFeatureTest::TearDown();
   }
diff --git a/chrome/browser/ui/autofill/BUILD.gn b/chrome/browser/ui/autofill/BUILD.gn
index b96228498..a432204 100644
--- a/chrome/browser/ui/autofill/BUILD.gn
+++ b/chrome/browser/ui/autofill/BUILD.gn
@@ -262,6 +262,7 @@
     "//components/autofill/content/browser:test_support",
     "//components/autofill/core/browser:test_support",
     "//components/autofill/core/common:test_support",
+    "//components/feature_engagement/public:feature_constants",
     "//components/input",
     "//components/keyed_service/content",
     "//components/keyed_service/core",
diff --git a/chrome/browser/ui/autofill/autofill_field_promo_controller_impl_unittest.cc b/chrome/browser/ui/autofill/autofill_field_promo_controller_impl_unittest.cc
index 3145bd1..b1dd157 100644
--- a/chrome/browser/ui/autofill/autofill_field_promo_controller_impl_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_field_promo_controller_impl_unittest.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/ui/browser_element_identifiers.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/test_browser_window.h"
+#include "components/feature_engagement/public/feature_constants.h"
 #include "components/user_education/common/feature_promo/feature_promo_controller.h"
 #include "components/user_education/common/feature_promo/feature_promo_result.h"
 #include "components/user_education/test/mock_feature_promo_controller.h"
@@ -60,7 +61,8 @@
       : content::WebContentsUserData<AutofillFieldPromoControllerWrapper>(
             *web_contents) {
     promo_controller_ = std::make_unique<AutofillFieldPromoControllerImpl>(
-        web_contents, feature_engagement::kIPHAutofillManualFallbackFeature,
+        web_contents,
+        feature_engagement::kIPHAutofillPredictionImprovementsFeature,
         kAutofillStandaloneCvcSuggestionElementId);
   }
   WEB_CONTENTS_USER_DATA_KEY_DECL();
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc
index 4a23c987..3c89d9d 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client.cc
+++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -180,8 +180,6 @@
 #if !BUILDFLAG(IS_ANDROID)
 const base::Feature& GetFeature(AutofillClient::IphFeature iph_feature) {
   switch (iph_feature) {
-    case AutofillClient::IphFeature::kManualFallback:
-      return feature_engagement::kIPHAutofillManualFallbackFeature;
     case AutofillClient::IphFeature::kPredictionImprovements:
       return feature_engagement::kIPHAutofillPredictionImprovementsFeature;
   }
@@ -190,8 +188,6 @@
 
 ui::ElementIdentifier GetElementId(AutofillClient::IphFeature iph_feature) {
   switch (iph_feature) {
-    case AutofillClient::IphFeature::kManualFallback:
-      return kAutofillManualFallbackElementId;
     case AutofillClient::IphFeature::kPredictionImprovements:
       return kAutofillPredictionImprovementsIphElementId;
   }
@@ -329,8 +325,8 @@
 AutofillCrowdsourcingManager& ChromeAutofillClient::GetCrowdsourcingManager() {
   if (!crowdsourcing_manager_) {
     // Lazy initialization to avoid virtual function calls in the constructor.
-    crowdsourcing_manager_ = std::make_unique<AutofillCrowdsourcingManager>(
-        this, GetChannel(), GetLogManager());
+    crowdsourcing_manager_ =
+        std::make_unique<AutofillCrowdsourcingManager>(this, GetChannel());
   }
   return *crowdsourcing_manager_;
 }
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client_interactive_uitest.cc b/chrome/browser/ui/autofill/chrome_autofill_client_interactive_uitest.cc
index c891975..db83d7d 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client_interactive_uitest.cc
+++ b/chrome/browser/ui/autofill/chrome_autofill_client_interactive_uitest.cc
@@ -7,7 +7,6 @@
 #include "base/test/run_until.h"
 #include "chrome/browser/ui/autofill/chrome_autofill_client.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -77,7 +76,7 @@
     // `BrowserWindow::MaybeShowFeaturePromo()` doesn't work in tests unless the
     // IPH feature is explicitly enabled.
     iph_feature_list_.InitAndEnableFeatures(
-        {feature_engagement::kIPHAutofillManualFallbackFeature});
+        {feature_engagement::kIPHAutofillPredictionImprovementsFeature});
   }
 
   void SetUpOnMainThread() override {
@@ -144,7 +143,7 @@
   TestAutofillDriverInjector<ContentAutofillDriver> autofill_driver_injector_;
 };
 
-// This test displays a manual fallback IPH, and then tries to show the Autofill
+// This test displays an autofill field IPH, and then tries to show the Autofill
 // Popup on top of it (they would overlap). The expected behaviour is
 // that the IPH is hidden and the Autofill Popup is successfully shown.
 IN_PROC_BROWSER_TEST_F(ChromeAutofillClientBrowserTest,
@@ -152,17 +151,15 @@
   FormData form = test::CreateTestAddressFormData();
   test_api(form).field(0).set_bounds(gfx::RectF(10, 10));
   client()->ShowAutofillFieldIphForFeature(
-      form.fields()[0], AutofillClient::IphFeature::kManualFallback);
+      form.fields()[0], AutofillClient::IphFeature::kPredictionImprovements);
 
   // Set the bounds such that the Autofill Popup would overlap with the IPH (the
   // IPH is displayed right below `form.fields[0]`, whose bounds are set above).
   ShowSuggestions(/*bounds=*/gfx::RectF(100, 100));
   WaitUntilSuggestionsHaveBeenShown();
 
-  EXPECT_FALSE(chrome::FindBrowserWithTab(web_contents())
-                   ->window()
-                   ->IsFeaturePromoActive(
-                       feature_engagement::kIPHAutofillManualFallbackFeature));
+  EXPECT_FALSE(browser()->window()->IsFeaturePromoActive(
+      feature_engagement::kIPHAutofillPredictionImprovementsFeature));
 }
 
 IN_PROC_BROWSER_TEST_F(ChromeAutofillClientBrowserTest, SuggestionUiSessionId) {
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client_unittest.cc b/chrome/browser/ui/autofill/chrome_autofill_client_unittest.cc
index ea19838..3316563e 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client_unittest.cc
+++ b/chrome/browser/ui/autofill/chrome_autofill_client_unittest.cc
@@ -41,6 +41,7 @@
 #include "components/autofill/core/common/autofill_test_utils.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/autofill/core/common/form_interactions_flow.h"
+#include "components/feature_engagement/public/feature_constants.h"
 #include "components/plus_addresses/features.h"
 #include "components/prefs/pref_service.h"
 #include "components/strings/grit/components_strings.h"
@@ -435,19 +436,20 @@
       /*on_confirmation_closed_callback=*/std::nullopt);
 }
 
-TEST_F(ChromeAutofillClientTest,
-       AutofillManualFallbackIPH_NotShownByPromoController) {
-  SetUpIphForTesting(feature_engagement::kIPHAutofillManualFallbackFeature);
+TEST_F(ChromeAutofillClientTest, AutofillFieldIPH_NotShownByPromoController) {
+  SetUpIphForTesting(
+      feature_engagement::kIPHAutofillPredictionImprovementsFeature);
 
   EXPECT_CALL(*autofill_field_promo_controller(), IsMaybeShowing)
       .WillRepeatedly(Return(false));
 
   EXPECT_FALSE(client()->ShowAutofillFieldIphForFeature(
-      FormFieldData{}, AutofillClient::IphFeature::kManualFallback));
+      FormFieldData{}, AutofillClient::IphFeature::kPredictionImprovements));
 }
 
-TEST_F(ChromeAutofillClientTest, AutofillManualFallbackIPH_IsShown) {
-  SetUpIphForTesting(feature_engagement::kIPHAutofillManualFallbackFeature);
+TEST_F(ChromeAutofillClientTest, AutofillFieldIPH_IsShown) {
+  SetUpIphForTesting(
+      feature_engagement::kIPHAutofillPredictionImprovementsFeature);
 
   InSequence sequence;
   EXPECT_CALL(*autofill_field_promo_controller(), IsMaybeShowing)
@@ -457,7 +459,7 @@
       .WillOnce(Return(true));
 
   EXPECT_TRUE(client()->ShowAutofillFieldIphForFeature(
-      FormFieldData{}, AutofillClient::IphFeature::kManualFallback));
+      FormFieldData{}, AutofillClient::IphFeature::kPredictionImprovements));
 }
 
 TEST_F(ChromeAutofillClientTest, AutofillImprovedPredictionsIPH_IsShown) {
@@ -476,7 +478,7 @@
 }
 
 TEST_F(ChromeAutofillClientTest,
-       AutofillManualFallbackIPH_HideOnShowAutofillSuggestions) {
+       AutofillFieldIPH_HideOnShowAutofillSuggestions) {
   SetUpIphForTesting(
       feature_engagement::kIPHAutofillPredictionImprovementsFeature);
   auto delegate = std::make_unique<MockAutofillSuggestionDelegate>();
@@ -521,13 +523,14 @@
       test_autofill_client_injector_;
 };
 
-TEST_F(ChromeAutofillClientTestWithWindow,
-       AutofillManualFallbackIPH_NotifyFeatureUsed) {
+TEST_F(ChromeAutofillClientTestWithWindow, AutofillFieldIPH_NotifyFeatureUsed) {
   EXPECT_CALL(
       *feature_promo_controller(),
-      EndPromo(Ref(feature_engagement::kIPHAutofillManualFallbackFeature),
-               user_education::EndFeaturePromoReason::kFeatureEngaged));
-  client()->NotifyIphFeatureUsed(AutofillClient::IphFeature::kManualFallback);
+      EndPromo(
+          Ref(feature_engagement::kIPHAutofillPredictionImprovementsFeature),
+          user_education::EndFeaturePromoReason::kFeatureEngaged));
+  client()->NotifyIphFeatureUsed(
+      AutofillClient::IphFeature::kPredictionImprovements);
 }
 #endif
 }  // namespace
diff --git a/chrome/browser/ui/autofill/payments/local_card_migration_dialog_controller_impl.cc b/chrome/browser/ui/autofill/payments/local_card_migration_dialog_controller_impl.cc
index d152a7bf..d0a337f 100644
--- a/chrome/browser/ui/autofill/payments/local_card_migration_dialog_controller_impl.cc
+++ b/chrome/browser/ui/autofill/payments/local_card_migration_dialog_controller_impl.cc
@@ -29,13 +29,13 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics.h"
 #include "components/autofill/core/browser/metrics/payments/local_card_migration_metrics.h"
 #include "components/autofill/core/browser/payments/local_card_migration_manager.h"
 #include "components/autofill/core/browser/payments/payments_service_url.h"
 #include "components/autofill/core/browser/strike_databases/payments/local_card_migration_strike_database.h"
 #include "components/autofill/core/browser/strike_databases/strike_database.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_payments_features.h"
diff --git a/chrome/browser/ui/browser_element_identifiers.cc b/chrome/browser/ui/browser_element_identifiers.cc
index 11cba8de..9730bd5 100644
--- a/chrome/browser/ui/browser_element_identifiers.cc
+++ b/chrome/browser/ui/browser_element_identifiers.cc
@@ -14,7 +14,6 @@
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kAppUninstallDialogOkButtonId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kAutofillCreditCardBenefitElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kAutofillCreditCardSuggestionEntryElementId);
-DEFINE_ELEMENT_IDENTIFIER_VALUE(kAutofillManualFallbackElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kAutofillPredictionImprovementsErrorElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kAutofillPredictionImprovementsFillElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(
diff --git a/chrome/browser/ui/browser_element_identifiers.h b/chrome/browser/ui/browser_element_identifiers.h
index 4a7082e8..eb42b46 100644
--- a/chrome/browser/ui/browser_element_identifiers.h
+++ b/chrome/browser/ui/browser_element_identifiers.h
@@ -23,7 +23,6 @@
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kAppUninstallDialogOkButtonId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kAutofillCreditCardBenefitElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kAutofillCreditCardSuggestionEntryElementId);
-DECLARE_ELEMENT_IDENTIFIER_VALUE(kAutofillManualFallbackElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kAutofillPredictionImprovementsErrorElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kAutofillPredictionImprovementsFillElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(
diff --git a/chrome/browser/ui/fast_checkout/fast_checkout_controller_impl.cc b/chrome/browser/ui/fast_checkout/fast_checkout_controller_impl.cc
index a9fdef9..f1f58e66 100644
--- a/chrome/browser/ui/fast_checkout/fast_checkout_controller_impl.cc
+++ b/chrome/browser/ui/fast_checkout/fast_checkout_controller_impl.cc
@@ -5,9 +5,9 @@
 #include "chrome/browser/ui/fast_checkout/fast_checkout_controller_impl.h"
 
 #include "chrome/browser/android/preferences/autofill/settings_navigation_helper.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "content/public/browser/web_contents.h"
 
 FastCheckoutControllerImpl::FastCheckoutControllerImpl(
diff --git a/chrome/browser/ui/hats/survey_config.cc b/chrome/browser/ui/hats/survey_config.cc
index 54fd711..9b1642e 100644
--- a/chrome/browser/ui/hats/survey_config.cc
+++ b/chrome/browser/ui/hats/survey_config.cc
@@ -579,6 +579,37 @@
                               features::kSafetyHubAndroidOrganicTriggerId.Get(),
                               product_specific_bits_data_fields,
                               product_specific_string_data);
+
+  survey_configs.emplace_back(
+      &privacy_sandbox::kPrivacySandboxCctAdsNoticeSurvey,
+      "privacy-sandbox-cct-ads-notice-eea-control",
+      privacy_sandbox::kPrivacySandboxCctAdsNoticeSurveyControlEeaTriggerId
+          .Get());
+
+  survey_configs.emplace_back(
+      &privacy_sandbox::kPrivacySandboxCctAdsNoticeSurvey,
+      "privacy-sandbox-cct-ads-notice-eea-accepted",
+      privacy_sandbox::kPrivacySandboxCctAdsNoticeSurveyAcceptedEeaTriggerId
+          .Get());
+
+  survey_configs.emplace_back(
+      &privacy_sandbox::kPrivacySandboxCctAdsNoticeSurvey,
+      "privacy-sandbox-cct-ads-notice-eea-declined",
+      privacy_sandbox::kPrivacySandboxCctAdsNoticeSurveyDeclinedEeaTriggerId
+          .Get());
+
+  survey_configs.emplace_back(
+      &privacy_sandbox::kPrivacySandboxCctAdsNoticeSurvey,
+      "privacy-sandbox-cct-ads-notice-row-control",
+      privacy_sandbox::kPrivacySandboxCctAdsNoticeSurveyControlRowTriggerId
+          .Get());
+
+  survey_configs.emplace_back(
+      &privacy_sandbox::kPrivacySandboxCctAdsNoticeSurvey,
+      "privacy-sandbox-cct-ads-notice-row-acknowledged",
+      privacy_sandbox::kPrivacySandboxCctAdsNoticeSurveyAcknowledgedRowTriggerId
+          .Get());
+
 #endif  // #if !BUILDFLAG(IS_ANDROID)
 
   survey_configs.emplace_back(
diff --git a/chrome/browser/ui/passwords/manage_passwords_state.cc b/chrome/browser/ui/passwords/manage_passwords_state.cc
index 1b4eac9..d2dc1b8 100644
--- a/chrome/browser/ui/passwords/manage_passwords_state.cc
+++ b/chrome/browser/ui/passwords/manage_passwords_state.cc
@@ -25,14 +25,12 @@
 
 namespace {
 
-std::vector<std::unique_ptr<PasswordForm>> DeepCopyNonPSLVector(
+std::vector<std::unique_ptr<PasswordForm>> DeepCopyMatchingCredentials(
     base::span<const PasswordForm> password_forms) {
   std::vector<std::unique_ptr<PasswordForm>> result;
   result.reserve(password_forms.size());
   for (const PasswordForm& form : password_forms) {
-    if (GetMatchType(form) != password_manager_util::GetLoginMatchType::kPSL) {
-      result.push_back(std::make_unique<PasswordForm>(form));
-    }
+    result.push_back(std::make_unique<PasswordForm>(form));
   }
   return result;
 }
@@ -87,7 +85,7 @@
   ClearData();
   form_manager_ = std::move(form_manager);
   local_credentials_forms_ =
-      DeepCopyNonPSLVector(form_manager_->GetBestMatches());
+      DeepCopyMatchingCredentials(form_manager_->GetBestMatches());
   AppendDeepCopyVector(form_manager_->GetFederatedMatches(),
                        &local_credentials_forms_);
   origin_ = url::Origin::Create(form_manager_->GetURL());
@@ -107,7 +105,7 @@
   ClearData();
   form_manager_ = std::move(form_manager);
   local_credentials_forms_ =
-      DeepCopyNonPSLVector(form_manager_->GetBestMatches());
+      DeepCopyMatchingCredentials(form_manager_->GetBestMatches());
   AppendDeepCopyVector(form_manager_->GetFederatedMatches(),
                        &local_credentials_forms_);
   origin_ = url::Origin::Create(form_manager_->GetURL());
@@ -137,13 +135,8 @@
     std::unique_ptr<PasswordFormManagerForUI> form_manager) {
   ClearData();
   form_manager_ = std::move(form_manager);
-  for (const password_manager::PasswordForm& form :
-       form_manager_->GetBestMatches()) {
-    if (GetMatchType(form) == password_manager_util::GetLoginMatchType::kPSL) {
-      continue;
-    }
-    local_credentials_forms_.push_back(std::make_unique<PasswordForm>(form));
-  }
+  local_credentials_forms_ =
+      DeepCopyMatchingCredentials(form_manager_->GetBestMatches());
   AppendDeepCopyVector(form_manager_->GetFederatedMatches(),
                        &local_credentials_forms_);
   origin_ = url::Origin::Create(form_manager_->GetURL());
@@ -163,7 +156,7 @@
   }
 
   local_credentials_forms_ =
-      DeepCopyNonPSLVector(form_manager_->GetBestMatches());
+      DeepCopyMatchingCredentials(form_manager_->GetBestMatches());
   AppendDeepCopyVector(form_manager_->GetFederatedMatches(),
                        &local_credentials_forms_);
 
@@ -201,7 +194,7 @@
     url::Origin origin,
     base::span<const PasswordForm> federated_matches) {
   CHECK(!password_forms.empty() || !federated_matches.empty());
-  auto local_credentials_forms = DeepCopyNonPSLVector(password_forms);
+  auto local_credentials_forms = DeepCopyMatchingCredentials(password_forms);
   AppendDeepCopyVector(federated_matches, &local_credentials_forms);
 
   // Delete |form_manager_| only when the parameters are processed. They may be
@@ -209,8 +202,6 @@
   ClearData();
 
   if (local_credentials_forms.empty()) {
-    // Don't show the UI for PSL matched passwords. They are not stored for this
-    // page and cannot be deleted.
     OnInactive();
   } else {
     origin_ = std::move(origin);
@@ -230,7 +221,7 @@
   ClearData();
   form_manager_ = std::move(form_to_move);
   local_credentials_forms_ =
-      DeepCopyNonPSLVector(form_manager_->GetBestMatches());
+      DeepCopyMatchingCredentials(form_manager_->GetBestMatches());
   AppendDeepCopyVector(form_manager_->GetFederatedMatches(),
                        &local_credentials_forms_);
   origin_ = url::Origin::Create(form_manager_->GetURL());
diff --git a/chrome/browser/ui/passwords/manage_passwords_state_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_state_unittest.cc
index 0cfbd6f..7b50fe3 100644
--- a/chrome/browser/ui/passwords/manage_passwords_state_unittest.cc
+++ b/chrome/browser/ui/passwords/manage_passwords_state_unittest.cc
@@ -267,7 +267,7 @@
   passwords_data().OnPendingPassword(std::move(test_form_manager));
 
   EXPECT_THAT(passwords_data().GetCurrentForms(),
-              ElementsAre(Pointee(saved_match())));
+              ElementsAre(Pointee(saved_match()), Pointee(psl_match())));
   EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE,
             passwords_data().state());
   EXPECT_EQ(url::Origin::Create(GURL(kTestOrigin)), passwords_data().origin());
@@ -358,7 +358,7 @@
 
   passwords_data().TransitionToState(password_manager::ui::MANAGE_STATE);
   EXPECT_THAT(passwords_data().GetCurrentForms(),
-              ElementsAre(Pointee(saved_match())));
+              ElementsAre(Pointee(saved_match()), Pointee(psl_match())));
   EXPECT_EQ(password_manager::ui::MANAGE_STATE, passwords_data().state());
   EXPECT_EQ(url::Origin::Create(GURL(kTestOrigin)), passwords_data().origin());
   TestAllUpdates();
@@ -420,22 +420,24 @@
   passwords_data().OnPasswordAutofilled(password_forms, origin, {});
 
   EXPECT_THAT(passwords_data().GetCurrentForms(),
-              ElementsAre(Pointee(saved_match())));
+              ElementsAre(Pointee(saved_match()), Pointee(psl_match())));
   EXPECT_EQ(password_manager::ui::MANAGE_STATE, passwords_data().state());
   EXPECT_EQ(origin, passwords_data().origin());
 
   TestAllUpdates();
 }
 
-TEST_F(ManagePasswordsStateTest, InactiveOnPSLMatched) {
-  std::vector<PasswordForm> password_forms = {psl_match()};
-  passwords_data().OnPasswordAutofilled(
-      password_forms, url::Origin::Create(GURL(kTestOrigin)), {});
+TEST_F(ManagePasswordsStateTest, ActiveOnPSLMatched) {
+  std::vector<PasswordForm> password_form = {psl_match()};
+  const url::Origin origin = url::Origin::Create(GURL(kTestOrigin));
+  passwords_data().OnPasswordAutofilled(password_form, origin, {});
 
-  EXPECT_THAT(passwords_data().GetCurrentForms(), IsEmpty());
-  EXPECT_EQ(password_manager::ui::INACTIVE_STATE, passwords_data().state());
-  EXPECT_TRUE(passwords_data().origin().opaque());
-  EXPECT_FALSE(passwords_data().form_manager());
+  EXPECT_THAT(passwords_data().GetCurrentForms(),
+              ElementsAre(Pointee(psl_match())));
+  EXPECT_EQ(password_manager::ui::MANAGE_STATE, passwords_data().state());
+  EXPECT_EQ(passwords_data().origin(), origin);
+
+  TestAllUpdates();
 }
 
 TEST_F(ManagePasswordsStateTest, OnInactive) {
@@ -470,7 +472,7 @@
   passwords_data().OnDefaultStoreChanged(std::move(test_form_manager));
 
   EXPECT_THAT(passwords_data().GetCurrentForms(),
-              ElementsAre(Pointee(saved_match())));
+              ElementsAre(Pointee(saved_match()), Pointee(psl_match())));
   EXPECT_EQ(password_manager::ui::PASSWORD_STORE_CHANGED_BUBBLE_STATE,
             passwords_data().state());
   EXPECT_EQ(url::Origin::Create(GURL(kTestOrigin)), passwords_data().origin());
@@ -538,7 +540,7 @@
   passwords_data().OnUpdatePassword(std::move(test_form_manager));
 
   EXPECT_THAT(passwords_data().GetCurrentForms(),
-              ElementsAre(Pointee(saved_match())));
+              ElementsAre(Pointee(saved_match()), Pointee(psl_match())));
   EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_UPDATE_STATE,
             passwords_data().state());
   EXPECT_EQ(url::Origin::Create(GURL(kTestOrigin)), passwords_data().origin());
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc
index ef20d17..0c703d5 100644
--- a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc
+++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc
@@ -1160,7 +1160,7 @@
   ExpectIconAndControllerStateIs(password_manager::ui::AUTO_SIGNIN_STATE);
 }
 
-TEST_F(ManagePasswordsUIControllerTest, InactiveOnPSLMatched) {
+TEST_F(ManagePasswordsUIControllerTest, ActiveOnPSLMatched) {
   std::u16string kTestUsername = u"test_username";
   std::vector<PasswordForm> forms;
   PasswordForm psl_matched_test_form(test_local_form());
@@ -1170,7 +1170,7 @@
   controller()->OnPasswordAutofilled(
       forms, url::Origin::Create(forms.front().url), {});
 
-  EXPECT_EQ(password_manager::ui::INACTIVE_STATE, controller()->GetState());
+  ExpectIconAndControllerStateIs(password_manager::ui::MANAGE_STATE);
 }
 
 TEST_F(ManagePasswordsUIControllerTest, UpdatePasswordSubmitted) {
diff --git a/chrome/browser/ui/tabs/public/tab_features.h b/chrome/browser/ui/tabs/public/tab_features.h
index a84c7cf..ae4e096 100644
--- a/chrome/browser/ui/tabs/public/tab_features.h
+++ b/chrome/browser/ui/tabs/public/tab_features.h
@@ -63,6 +63,10 @@
 class PageActionController;
 }  // namespace page_actions
 
+namespace tab_groups {
+class CollaborationMessagingTabData;
+}  // namespace tab_groups
+
 namespace tabs {
 
 class TabInterface;
@@ -142,6 +146,11 @@
     return page_action_controller_.get();
   }
 
+  tab_groups::CollaborationMessagingTabData*
+  collaboration_messaging_tab_data() {
+    return collaboration_messaging_tab_data_.get();
+  }
+
   // Called exactly once to initialize features.
   // Can be overridden in tests to initialize nothing.
   virtual void Init(TabInterface& tab, Profile* profile);
@@ -225,6 +234,10 @@
   // Responsible for managing page actions of a tab.
   std::unique_ptr<page_actions::PageActionController> page_action_controller_;
 
+  // Contains the recent collaboration message for a shared tab.
+  std::unique_ptr<tab_groups::CollaborationMessagingTabData>
+      collaboration_messaging_tab_data_;
+
   // Must be the last member.
   base::WeakPtrFactory<TabFeatures> weak_factory_{this};
 };
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.cc b/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.cc
new file mode 100644
index 0000000..bbc5d9c
--- /dev/null
+++ b/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.cc
@@ -0,0 +1,36 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.h"
+
+#include "components/collaboration/public/messaging/message.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "ui/base/l10n/l10n_util.h"
+
+using collaboration::messaging::PersistentMessage;
+
+namespace tab_groups {
+
+CollaborationMessagingTabData::CollaborationMessagingTabData() = default;
+CollaborationMessagingTabData::~CollaborationMessagingTabData() = default;
+
+void CollaborationMessagingTabData::SetMessage(PersistentMessage message) {
+  using collaboration::messaging::CollaborationEvent;
+  using collaboration::messaging::PersistentNotificationType;
+
+  // Only Chip messages are allowed.
+  CHECK(message.type == PersistentNotificationType::CHIP);
+
+  // Chip messages are always TAB_ADDED or TAB_UPDATED.
+  CHECK(message.collaboration_event == CollaborationEvent::TAB_ADDED ||
+        message.collaboration_event == CollaborationEvent::TAB_UPDATED);
+
+  message_ = message;
+}
+
+void CollaborationMessagingTabData::ClearMessage(PersistentMessage message) {
+  message_ = std::nullopt;
+}
+
+}  // namespace tab_groups
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.h b/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.h
new file mode 100644
index 0000000..064e506
--- /dev/null
+++ b/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.h
@@ -0,0 +1,69 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_TABS_SAVED_TAB_GROUPS_COLLABORATION_MESSAGING_TAB_DATA_H_
+#define CHROME_BROWSER_UI_TABS_SAVED_TAB_GROUPS_COLLABORATION_MESSAGING_TAB_DATA_H_
+
+#include "base/strings/utf_string_conversions.h"
+#include "components/collaboration/public/messaging/message.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace tab_groups {
+
+using collaboration::messaging::CollaborationEvent;
+using collaboration::messaging::PersistentMessage;
+
+class CollaborationMessagingTabData {
+ public:
+  CollaborationMessagingTabData();
+  CollaborationMessagingTabData(CollaborationMessagingTabData& other) = delete;
+  CollaborationMessagingTabData& operator=(
+      CollaborationMessagingTabData& other) = delete;
+  CollaborationMessagingTabData(CollaborationMessagingTabData&& other) = delete;
+  CollaborationMessagingTabData& operator=(
+      CollaborationMessagingTabData&& other) = delete;
+  ~CollaborationMessagingTabData();
+
+  void SetMessage(PersistentMessage message);
+  void ClearMessage(PersistentMessage message);
+  bool HasMessage() { return message_.has_value(); }
+
+  std::u16string given_name() {
+    CHECK(HasMessage());
+
+    auto member = message_->attribution.triggering_user;
+    CHECK(member.has_value());
+
+    return base::UTF8ToUTF16(member->given_name);
+  }
+
+  GURL avatar_url() {
+    CHECK(HasMessage());
+
+    auto member = message_->attribution.triggering_user;
+    CHECK(member.has_value());
+
+    return member->avatar_url;
+  }
+
+  CollaborationEvent collaboration_event() {
+    CHECK(HasMessage());
+    return message_->collaboration_event;
+  }
+
+  base::WeakPtr<CollaborationMessagingTabData> GetWeakPtr() {
+    return weak_factory_.GetWeakPtr();
+  }
+
+ private:
+  std::optional<PersistentMessage> message_ = std::nullopt;
+
+  // Must be the last member.
+  base::WeakPtrFactory<CollaborationMessagingTabData> weak_factory_{this};
+};
+
+}  // namespace tab_groups
+
+#endif  // CHROME_BROWSER_UI_TABS_SAVED_TAB_GROUPS_COLLABORATION_MESSAGING_TAB_DATA_H_
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data_unittest.cc b/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data_unittest.cc
new file mode 100644
index 0000000..21a0ac4d
--- /dev/null
+++ b/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data_unittest.cc
@@ -0,0 +1,77 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.h"
+
+#include "components/collaboration/public/messaging/message.h"
+#include "components/data_sharing/public/group_data.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace tab_groups {
+
+using collaboration::messaging::CollaborationEvent;
+using collaboration::messaging::MessageAttribution;
+using collaboration::messaging::PersistentMessage;
+using collaboration::messaging::PersistentNotificationType;
+using data_sharing::GroupMember;
+
+class CollaborationMessagingTabDataTest : public testing::Test {
+ protected:
+  void SetUp() override {
+    tab_data_ = std::make_unique<CollaborationMessagingTabData>();
+  }
+
+  CollaborationMessagingTabData& tab_data() { return *tab_data_; }
+
+  PersistentMessage CreateMessage(std::string given_name,
+                                  std::string avatar_url,
+                                  CollaborationEvent event) {
+    GroupMember member;
+    member.given_name = given_name;
+    member.avatar_url = GURL(avatar_url);
+
+    MessageAttribution attribution;
+    attribution.triggering_user = member;
+
+    PersistentMessage message;
+    message.type = PersistentNotificationType::CHIP;
+    message.attribution = attribution;
+    message.collaboration_event = event;
+
+    return message;
+  }
+
+ private:
+  std::unique_ptr<CollaborationMessagingTabData> tab_data_;
+};
+
+TEST_F(CollaborationMessagingTabDataTest, CanSetAndClearData) {
+  EXPECT_FALSE(tab_data().HasMessage());
+
+  std::string given_name = "User";
+  std::string avatar_url = "URL";
+  auto message =
+      CreateMessage(given_name, avatar_url, CollaborationEvent::TAB_ADDED);
+  tab_data().SetMessage(message);
+  EXPECT_TRUE(tab_data().HasMessage());
+  EXPECT_EQ(tab_data().given_name(), base::UTF8ToUTF16(given_name));
+  EXPECT_EQ(tab_data().avatar_url(), GURL(avatar_url));
+  EXPECT_EQ(tab_data().collaboration_event(), CollaborationEvent::TAB_ADDED);
+
+  // Overwrite with a new message.
+  std::string given_name2 = "User2";
+  std::string avatar_url2 = "URL2";
+  auto message2 =
+      CreateMessage(given_name2, avatar_url2, CollaborationEvent::TAB_UPDATED);
+  tab_data().SetMessage(message2);
+  EXPECT_TRUE(tab_data().HasMessage());
+  EXPECT_EQ(tab_data().given_name(), base::UTF8ToUTF16(given_name2));
+  EXPECT_EQ(tab_data().avatar_url(), GURL(avatar_url2));
+  EXPECT_EQ(tab_data().collaboration_event(), CollaborationEvent::TAB_UPDATED);
+
+  tab_data().ClearMessage(message2);
+  EXPECT_FALSE(tab_data().HasMessage());
+}
+
+}  // namespace tab_groups
diff --git a/chrome/browser/ui/tabs/tab_features.cc b/chrome/browser/ui/tabs/tab_features.cc
index 07d1b337..c0fa39a 100644
--- a/chrome/browser/ui/tabs/tab_features.cc
+++ b/chrome/browser/ui/tabs/tab_features.cc
@@ -32,6 +32,7 @@
 #include "chrome/browser/ui/lens/lens_overlay_controller.h"
 #include "chrome/browser/ui/tabs/public/tab_dialog_manager.h"
 #include "chrome/browser/ui/tabs/public/tab_interface.h"
+#include "chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.h"
 #include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h"
 #include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_web_contents_listener.h"
 #include "chrome/browser/ui/tabs/tab_model.h"
@@ -151,6 +152,11 @@
     CHECK(tab.GetBrowserWindowInterface()->GetActions());
     page_action_controller_->Initialize(std::vector<actions::ActionId>(
         page_actions::kActionIds.begin(), page_actions::kActionIds.end()));
+
+    if (tab_groups::SavedTabGroupUtils::SupportsSharedTabGroups()) {
+      collaboration_messaging_tab_data_ =
+          std::make_unique<tab_groups::CollaborationMessagingTabData>();
+    }
   }
 
   customize_chrome_side_panel_controller_ =
diff --git a/chrome/browser/ui/tabs/tab_renderer_data.cc b/chrome/browser/ui/tabs/tab_renderer_data.cc
index 1a5add0..cf04a52 100644
--- a/chrome/browser/ui/tabs/tab_renderer_data.cc
+++ b/chrome/browser/ui/tabs/tab_renderer_data.cc
@@ -16,7 +16,9 @@
 #include "chrome/browser/ui/performance_controls/memory_saver_utils.h"
 #include "chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.h"
 #include "chrome/browser/ui/tab_ui_helper.h"
+#include "chrome/browser/ui/tabs/public/tab_features.h"
 #include "chrome/browser/ui/tabs/public/tab_interface.h"
+#include "chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.h"
 #include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h"
@@ -44,44 +46,27 @@
 using collaboration::messaging::MessagingBackendServiceFactory;
 using collaboration::messaging::PersistentMessage;
 
-std::optional<PersistentMessage> GetSavedTabGroupRecentActivity(
-    const tabs::TabInterface* tab,
-    Profile* profile) {
+base::WeakPtr<tab_groups::CollaborationMessagingTabData>
+GetCollaborationMessage(tabs::TabInterface* tab) {
+  if (!tab_groups::SavedTabGroupUtils::SupportsSharedTabGroups()) {
+    return nullptr;
+  }
+
   if (!tab) {
-    return std::nullopt;
+    return nullptr;
   }
 
-  const auto group = tab->GetGroup();
-  if (!group) {
-    return std::nullopt;
+  auto* tab_features = tab->GetTabFeatures();
+  if (!tab_features) {
+    return nullptr;
   }
 
-  const auto* tab_group_sync_service =
-      tab_groups::SavedTabGroupUtils::GetServiceForProfile(profile);
-  if (!tab_group_sync_service) {
-    return std::nullopt;
+  auto* data = tab_features->collaboration_messaging_tab_data();
+  if (!data) {
+    return nullptr;
   }
 
-  std::optional<tab_groups::SavedTabGroup> saved_group =
-      tab_group_sync_service->GetGroup(*group);
-  if (!saved_group || !saved_group->is_shared_tab_group()) {
-    return std::nullopt;
-  }
-
-  MessagingBackendService* service =
-      MessagingBackendServiceFactory::GetForProfile(profile);
-  if (!service || !service->IsInitialized()) {
-    return std::nullopt;
-  }
-
-  auto messages = service->GetMessagesForTab(
-      tab->GetHandle().raw_value(),
-      collaboration::messaging::PersistentNotificationType::CHIP);
-  if (messages.empty()) {
-    return std::nullopt;
-  }
-
-  return messages.front();
+  return data->GetWeakPtr();
 }
 
 }  // namespace
@@ -132,10 +117,8 @@
   }
   data.is_tab_discarded = contents->WasDiscarded();
 
-  if (tab_groups::SavedTabGroupUtils::SupportsSharedTabGroups()) {
-    data.recent_activity = GetSavedTabGroupRecentActivity(
-        model->GetTabAtIndex(index), model->profile());
-  }
+  data.collaboration_messaging =
+      GetCollaborationMessage(model->GetTabAtIndex(index));
   data.network_state = TabNetworkStateForWebContents(contents);
   data.title = tab_ui_helper->GetTitle();
   data.visible_url = contents->GetVisibleURL();
diff --git a/chrome/browser/ui/tabs/tab_renderer_data.h b/chrome/browser/ui/tabs/tab_renderer_data.h
index c7eab74..f134620 100644
--- a/chrome/browser/ui/tabs/tab_renderer_data.h
+++ b/chrome/browser/ui/tabs/tab_renderer_data.h
@@ -10,7 +10,6 @@
 #include "base/process/kill.h"
 #include "chrome/browser/ui/tabs/tab_enums.h"
 #include "chrome/browser/ui/tabs/tab_network_state.h"
-#include "components/collaboration/public/messaging/message.h"
 #include "ui/base/models/image_model.h"
 #include "ui/gfx/image/image_skia.h"
 #include "url/gurl.h"
@@ -19,6 +18,10 @@
 class TabResourceUsage;
 class ThumbnailImage;
 
+namespace tab_groups {
+class CollaborationMessagingTabData;
+}  // namespace tab_groups
+
 // Wraps the state needed by the renderers.
 struct TabRendererData {
   static TabRendererData FromTabInModel(const TabStripModel* model, int index);
@@ -60,8 +63,8 @@
   bool should_render_empty_title = false;
   bool should_themify_favicon = false;
   bool is_tab_discarded = false;
-  std::optional<collaboration::messaging::PersistentMessage> recent_activity =
-      std::nullopt;
+  base::WeakPtr<tab_groups::CollaborationMessagingTabData>
+      collaboration_messaging = nullptr;
   bool should_show_discard_status = false;
   // Amount of memory saved through discarding the tab
   int64_t discarded_memory_savings_in_bytes = 0;
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc
index bb4a0d6..6ae20dad 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc
@@ -236,6 +236,10 @@
   EXPECT_TRUE(widget_);
 }
 
+#if !BUILDFLAG(IS_CHROMEOS)
+// Exclude the test from ChromeOS because profile destruction does not happen
+// on ChromeOS in production.
+//
 // Tests that the dialog closes when the current profile is destroyed.
 TEST_F(AppInfoDialogViewsTest, DestroyedProfileClosesDialog) {
   ShowAppInfo(kTestExtensionId);
@@ -260,15 +264,6 @@
     // tearing down arc_test user_manager.
     base::RunLoop().RunUntilIdle();
 
-#if BUILDFLAG(IS_CHROMEOS)
-    // Avoid a race condition when tearing down arc_test_ and deleting the user
-    // manager.
-    chrome_shelf_controller_.reset();
-    shelf_model_.reset();
-    arc_test_->TearDown();
-    arc_test_.reset();
-#endif
-
     ASSERT_TRUE(widget_);
     EXPECT_FALSE(widget_->IsClosed());
   }
@@ -288,6 +283,7 @@
 
   EXPECT_FALSE(widget_);
 }
+#endif  // !BUILDFLAG(IS_CHROMEOS)
 
 // Tests that the dialog does not close when a different profile is destroyed.
 TEST_F(AppInfoDialogViewsTest, DestroyedOtherProfileDoesNotCloseDialog) {
diff --git a/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc b/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc
index b501459..46bc8c8 100644
--- a/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc
+++ b/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc
@@ -26,10 +26,10 @@
 #include "chrome/grit/theme_resources.h"
 #include "components/autofill/core/browser/autofill_experiments.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics.h"
 #include "components/autofill/core/browser/metrics/payments/credit_card_save_metrics.h"
 #include "components/autofill/core/browser/payments/legal_message_line.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_payments_features.h"
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index 7645a50..a08a536 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -28,6 +28,7 @@
 #include "chrome/browser/extensions/api/omnibox/omnibox_api.h"
 #include "chrome/browser/extensions/extension_ui_util.h"
 #include "chrome/browser/extensions/tab_helper.h"
+#include "chrome/browser/page_info/merchant_trust_service_factory.h"
 #include "chrome/browser/page_info/page_info_features.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
@@ -282,7 +283,8 @@
     merchant_trust_chip_ = AddChildView(std::make_unique<OmniboxChipButton>());
     merchant_trust_chip_controller_ =
         std::make_unique<MerchantTrustChipButtonController>(
-            merchant_trust_chip_, location_icon_view_);
+            merchant_trust_chip_, location_icon_view_,
+            MerchantTrustServiceFactory::GetForProfile(profile_));
   }
 
   // Initialize the Omnibox view.
@@ -814,16 +816,31 @@
     leading_decorations.AddDecoration(vertical_padding, location_height, false,
                                       0, /*intra_item_padding=*/0, icon_left,
                                       location_icon_view_);
-    if (merchant_trust_chip_controller_ && merchant_trust_chip_->GetVisible()) {
+  } else {
+    location_icon_view_->SetVisible(false);
+  }
+
+  if (merchant_trust_chip_controller_) {
+    // The merchant chip is shown when:
+    // 1. there is data to be shown
+    // 2. no permission chips are shown
+    // 3. the omnibox is not in editing mode
+    // 4. location bar icon doesn't have extra text
+    const bool should_show_merchant_chip =
+        merchant_trust_chip_controller_->ShouldBeVisible() &&
+        !show_overriding_permission_chip && !IsEditingOrEmpty() &&
+        !location_icon_view_->GetShowText();
+
+    if (should_show_merchant_chip) {
       // TODO(crbug.com/378854462): Use constant.
       const int padding_before_chip = 2;
       merchant_trust_chip_controller_->Show();
       leading_decorations.AddDecoration(vertical_padding, location_height,
                                         false, 0, padding_before_chip,
                                         icon_left, merchant_trust_chip_);
+    } else {
+      merchant_trust_chip_controller_->Hide();
     }
-  } else {
-    location_icon_view_->SetVisible(false);
   }
 
   auto add_trailing_decoration = [&](View* view, int intra_item_padding) {
@@ -996,11 +1013,8 @@
   else
     omnibox_view_->Update();
 
-  // TODO(crbug.com/378854462): Fetch the data from the service and show when
-  // there is data available.
-  if (merchant_trust_chip_controller_ && contents) {
+  if (merchant_trust_chip_controller_) {
     merchant_trust_chip_controller_->UpdateWebContents(contents);
-    merchant_trust_chip_controller_->Show();
   }
 
   OnChanged();  // NOTE: Triggers layout.
@@ -1713,10 +1727,6 @@
       permission_dashboard_view_->SetVisible(false);
     }
   }
-
-  if (merchant_trust_chip_controller_) {
-    merchant_trust_chip_controller_->Hide();
-  }
 }
 
 ui::MouseEvent LocationBarView::AdjustMouseEventLocationForOmniboxView(
diff --git a/chrome/browser/ui/views/location_bar/merchant_trust_chip_button_controller.cc b/chrome/browser/ui/views/location_bar/merchant_trust_chip_button_controller.cc
index e0c1a644..065901bb 100644
--- a/chrome/browser/ui/views/location_bar/merchant_trust_chip_button_controller.cc
+++ b/chrome/browser/ui/views/location_bar/merchant_trust_chip_button_controller.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/ui/views/location_bar/location_icon_view.h"
 #include "chrome/browser/ui/views/location_bar/omnibox_chip_button.h"
 #include "chrome/browser/ui/views/page_info/page_info_bubble_view.h"
+#include "components/page_info/core/merchant_trust_service.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/vector_icons/vector_icons.h"
 #include "content/public/browser/navigation_entry.h"
@@ -25,8 +26,11 @@
 
 MerchantTrustChipButtonController::MerchantTrustChipButtonController(
     OmniboxChipButton* chip_button,
-    LocationIconView* location_icon_view)
-    : chip_button_(chip_button), location_icon_view_(location_icon_view) {
+    LocationIconView* location_icon_view,
+    page_info::MerchantTrustService* service)
+    : chip_button_(chip_button),
+      location_icon_view_(location_icon_view),
+      service_(service) {
   // TODO(crbug.com/378854462): Revisit icons, strings and theme.
   chip_button_->SetIcon(vector_icons::kStorefrontIcon);
   chip_button_->SetText(
@@ -42,10 +46,38 @@
     default;
 
 void MerchantTrustChipButtonController::UpdateWebContents(
-    content::WebContents* web_contents) {
-  web_contents_ = web_contents->GetWeakPtr();
+    content::WebContents* contents) {
+  if (contents) {
+    Observe(contents);
+  }
 
-  // TODO(crbug.com/378854906): Fetch the data.
+  if (!service_ || !web_contents()) {
+    return;
+  }
+
+  service_->GetMerchantTrustInfo(
+      web_contents()->GetVisibleURL(),
+      base::BindOnce(
+          &MerchantTrustChipButtonController::OnMerchantTrustDataFetched,
+          base::Unretained(this)));
+}
+
+void MerchantTrustChipButtonController::OnMerchantTrustDataFetched(
+    const GURL& url,
+    std::optional<page_info::MerchantData> merchant_data) {
+  merchant_data_ = merchant_data;
+
+  if (ShouldBeVisible()) {
+    // TODO(crbug.com/378854906): Animate expand when needed.
+    Show();
+  } else {
+    // TODO(crbug.com/378854906): Animate collapse when needed.
+    Hide();
+  }
+}
+
+bool MerchantTrustChipButtonController::ShouldBeVisible() {
+  return merchant_data_.has_value();
 }
 
 void MerchantTrustChipButtonController::Show() {
@@ -54,25 +86,21 @@
       gfx::RoundedCornersF(radius, 0, 0, radius));
   chip_button_->SetCornerRadii(gfx::RoundedCornersF(0, radius, radius, 0));
   chip_button_->SetVisible(true);
-
-  // TODO(crbug.com/378854906): Animate expand.
 }
 
 void MerchantTrustChipButtonController::Hide() {
   location_icon_view_->SetCornerRadii(gfx::RoundedCornersF(
       location_icon_view_->GetPreferredSize().height() / 2));
   chip_button_->SetVisible(false);
-
-  // TODO(crbug.com/378854906): Animate collapse.
 }
 
 void MerchantTrustChipButtonController::OpenPageInfoSubpage() {
-  if (!web_contents_) {
+  if (!web_contents()) {
     return;
   }
 
   content::NavigationEntry* entry =
-      web_contents_->GetController().GetVisibleEntry();
+      web_contents()->GetController().GetVisibleEntry();
   if (entry->IsInitialEntry()) {
     return;
   }
@@ -88,7 +116,7 @@
   views::BubbleDialogDelegateView* bubble =
       PageInfoBubbleView::CreatePageInfoBubble(
           location_icon_view_, gfx::Rect(),
-          chip_button_->GetWidget()->GetNativeWindow(), web_contents_.get(),
+          chip_button_->GetWidget()->GetNativeWindow(), web_contents(),
           entry->GetVirtualURL(), std::move(initialized_callback),
           base::DoNothing(),
           /*allow_about_this_site=*/true, std::nullopt, true);
diff --git a/chrome/browser/ui/views/location_bar/merchant_trust_chip_button_controller.h b/chrome/browser/ui/views/location_bar/merchant_trust_chip_button_controller.h
index c0690fd..6082e56 100644
--- a/chrome/browser/ui/views/location_bar/merchant_trust_chip_button_controller.h
+++ b/chrome/browser/ui/views/location_bar/merchant_trust_chip_button_controller.h
@@ -6,26 +6,31 @@
 #define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_MERCHANT_TRUST_CHIP_BUTTON_CONTROLLER_H_
 
 #include "base/memory/raw_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "content/public/browser/web_contents.h"
+#include "components/page_info/core/page_info_types.h"
+#include "content/public/browser/web_contents_observer.h"
 #include "ui/base/interaction/element_identifier.h"
 
 class OmniboxChipButton;
 class LocationIconView;
 
+namespace page_info {
+class MerchantTrustService;
+}  // namespace page_info
+
 // A controller for a chip-style button which opens "Merchant trust" page info
 // subpage.
-class MerchantTrustChipButtonController {
+class MerchantTrustChipButtonController : public content::WebContentsObserver {
  public:
   DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kElementIdForTesting);
 
   MerchantTrustChipButtonController(OmniboxChipButton* chip_button,
-                                    LocationIconView* location_icon_view);
+                                    LocationIconView* location_icon_view,
+                                    page_info::MerchantTrustService* service);
   MerchantTrustChipButtonController(const MerchantTrustChipButtonController&) =
       delete;
   MerchantTrustChipButtonController& operator=(
       const MerchantTrustChipButtonController&) = delete;
-  virtual ~MerchantTrustChipButtonController();
+  ~MerchantTrustChipButtonController() override;
 
   void UpdateWebContents(content::WebContents* web_contents);
 
@@ -33,10 +38,20 @@
   void Hide();
   void OpenPageInfoSubpage();
 
+  // Whether the chip should be visible based on the service response. Note:
+  // it doesn't mean that it will be visible since other views can take
+  // precedence over it.
+  bool ShouldBeVisible();
+
  private:
+  void OnMerchantTrustDataFetched(
+      const GURL& url,
+      std::optional<page_info::MerchantData> merchant_data);
+
   raw_ptr<OmniboxChipButton> chip_button_;
   raw_ptr<LocationIconView> location_icon_view_;
-  base::WeakPtr<content::WebContents> web_contents_;
+  raw_ptr<page_info::MerchantTrustService> service_;
+  std::optional<page_info::MerchantData> merchant_data_;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_MERCHANT_TRUST_CHIP_BUTTON_CONTROLLER_H_
diff --git a/chrome/browser/ui/views/location_bar/merchant_trust_chip_button_interactive_uitest.cc b/chrome/browser/ui/views/location_bar/merchant_trust_chip_button_interactive_uitest.cc
index b694f42..6149793 100644
--- a/chrome/browser/ui/views/location_bar/merchant_trust_chip_button_interactive_uitest.cc
+++ b/chrome/browser/ui/views/location_bar/merchant_trust_chip_button_interactive_uitest.cc
@@ -3,20 +3,42 @@
 // found in the LICENSE file.
 
 #include "base/test/scoped_feature_list.h"
+#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+#include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
+#include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_element_identifiers.h"
 #include "chrome/browser/ui/views/location_bar/merchant_trust_chip_button_controller.h"
 #include "chrome/browser/ui/views/page_info/page_info_main_view.h"
 #include "chrome/browser/ui/views/page_info/page_info_merchant_trust_content_view.h"
+#include "chrome/browser/ui/views/permissions/chip/permission_chip_view.h"
+#include "chrome/test/base/interactive_test_utils.h"
 #include "chrome/test/interaction/interactive_browser_test.h"
+#include "components/commerce/core/proto/merchant_trust.pb.h"
+#include "components/optimization_guide/core/optimization_metadata.h"
+#include "components/optimization_guide/proto/hints.pb.h"
 #include "components/page_info/core/features.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/test/browser_test.h"
 #include "net/dns/mock_host_resolver.h"
+#include "ui/events/keycodes/keyboard_codes.h"
 
 namespace {
 DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kWebContentsElementId);
+
+optimization_guide::OptimizationMetadata GetMerchantTrustMetadata() {
+  optimization_guide::OptimizationMetadata optimization_metadata;
+  commerce::MerchantTrustSignalsV2 metadata;
+  metadata.set_merchant_star_rating(3.5);
+  metadata.set_merchant_count_rating(23);
+  metadata.set_merchant_details_page_url("https://reviews.test");
+  metadata.set_reviews_summary("Test summary");
+
+  optimization_metadata.SetAnyMetadataForTesting(metadata);
+  return optimization_metadata;
+}
+
 }  // namespace
 
 class MerchantTrustChipButtonInteractiveUITest : public InteractiveBrowserTest {
@@ -47,6 +69,13 @@
     InteractiveBrowserTest::SetUpOnMainThread();
     host_resolver()->AddRule("*", "127.0.0.1");
     https_server()->StartAcceptingConnections();
+
+    auto* optimization_guide_decider =
+        OptimizationGuideKeyedServiceFactory::GetForProfile(
+            browser()->profile());
+    optimization_guide_decider->AddHintForTesting(
+        GetURL(), optimization_guide::proto::MERCHANT_TRUST_SIGNALS_V2,
+        GetMerchantTrustMetadata());
   }
 
   void TearDownOnMainThread() override {
@@ -54,9 +83,30 @@
     InteractiveBrowserTest::TearDownOnMainThread();
   }
 
+  void SetUpCommandLine(base::CommandLine* cmd) override {
+    cmd->AppendSwitch(optimization_guide::switches::
+                          kDisableCheckingUserPermissionsForTesting);
+  }
+
+  void SetPermission(ContentSettingsType type, ContentSetting setting) {
+    HostContentSettingsMap* map =
+        HostContentSettingsMapFactory::GetForProfile(browser()->profile());
+
+    map->SetContentSettingDefaultScope(GetURL(), GetURL(), type, setting);
+  }
+
+  auto SendKeyPress(ui::KeyboardCode key, bool control, bool shift) {
+    return Check([this, key, control, shift]() {
+      return ui_test_utils::SendKeyPressSync(browser(), key, control, shift,
+                                             false, false);
+    });
+  }
+
   net::EmbeddedTestServer* https_server() { return https_server_.get(); }
 
-  GURL GetURL() { return https_server()->GetURL("a.test", "/title1.html"); }
+  GURL GetURL() {
+    return https_server()->GetURL("a.test", "/permissions/requests.html");
+  }
 
  private:
   std::unique_ptr<net::EmbeddedTestServer> https_server_;
@@ -74,6 +124,26 @@
 }
 
 IN_PROC_BROWSER_TEST_F(MerchantTrustChipButtonInteractiveUITest,
+                       MerchantTrustChipOmniboxEdit) {
+  RunTestSequence(
+      InstrumentTab(kWebContentsElementId),
+      NavigateWebContents(kWebContentsElementId, GetURL()),
+      // The merchant chip is shown.
+      WaitForShow(MerchantTrustChipButtonController::kElementIdForTesting),
+      // Start typing.
+      EnterText(kOmniboxElementId, u"query"),
+      // The chip is hidden while typing.
+      WaitForHide(MerchantTrustChipButtonController::kElementIdForTesting),
+      // Note: SendAccelerator doesn't work here.
+      // Clear the input.
+      SendKeyPress(ui::VKEY_ESCAPE, false, false),
+      // Exit the editing mode.
+      SendKeyPress(ui::VKEY_ESCAPE, false, false),
+      // The merchant chip is shown again.
+      WaitForShow(MerchantTrustChipButtonController::kElementIdForTesting));
+}
+
+IN_PROC_BROWSER_TEST_F(MerchantTrustChipButtonInteractiveUITest,
                        LocationBarIconClick) {
   RunTestSequence(
       InstrumentTab(kWebContentsElementId),
@@ -83,3 +153,48 @@
       WaitForShow(PageInfoMainView::kMerchantTrustElementId),
       EnsurePresent(MerchantTrustChipButtonController::kElementIdForTesting));
 }
+
+IN_PROC_BROWSER_TEST_F(MerchantTrustChipButtonInteractiveUITest,
+                       PermissionRequestOverridesChip) {
+  RunTestSequence(
+      InstrumentTab(kWebContentsElementId),
+      NavigateWebContents(kWebContentsElementId, GetURL()),
+      // The merchant chip is shown.
+      WaitForShow(MerchantTrustChipButtonController::kElementIdForTesting),
+      // ...and the permission indicator is not.
+      EnsureNotPresent(PermissionChipView::kElementIdForTesting),
+      // Request notifications.
+      ExecuteJs(kWebContentsElementId, "requestNotification"),
+      // Make sure the request chip is visible.
+      WaitForShow(PermissionChipView::kElementIdForTesting),
+      // ...and the merchant chip is not.
+      WaitForHide(MerchantTrustChipButtonController::kElementIdForTesting),
+      // Make sure the permission popup bubble is visible.
+      WaitForShow(PermissionPromptBubbleBaseView::kMainViewId),
+      PressButton(PermissionChipView::kElementIdForTesting),
+      WaitForHide(PermissionPromptBubbleBaseView::kMainViewId),
+      // The permission chip is hidden since the permission request was
+      // dismissed...
+      WaitForHide(PermissionChipView::kElementIdForTesting),
+      // ...and the merchant chip is visible again.
+      WaitForShow(MerchantTrustChipButtonController::kElementIdForTesting));
+}
+
+IN_PROC_BROWSER_TEST_F(MerchantTrustChipButtonInteractiveUITest,
+                       PermissionInUseOverridesChip) {
+  SetPermission(ContentSettingsType::MEDIASTREAM_CAMERA, CONTENT_SETTING_ALLOW);
+
+  RunTestSequence(
+      InstrumentTab(kWebContentsElementId),
+      NavigateWebContents(kWebContentsElementId, GetURL()),
+      // The merchant chip is shown...
+      WaitForShow(MerchantTrustChipButtonController::kElementIdForTesting),
+      // ...and the permission indicator is not.
+      EnsureNotPresent(PermissionChipView::kElementIdForTesting),
+      // Requesting to use the camera (camera is in-use now).
+      ExecuteJs(kWebContentsElementId, "requestCamera"),
+      // Make sure the in-use indicator is visible...
+      WaitForShow(PermissionChipView::kElementIdForTesting),
+      // ...and the merchant chip is not.
+      WaitForHide(MerchantTrustChipButtonController::kElementIdForTesting));
+}
diff --git a/chrome/browser/ui/views/page_info/merchant_trust_side_panel_coordinator_browsertest.cc b/chrome/browser/ui/views/page_info/merchant_trust_side_panel_coordinator_browsertest.cc
index ae4084d1..e4f0e01 100644
--- a/chrome/browser/ui/views/page_info/merchant_trust_side_panel_coordinator_browsertest.cc
+++ b/chrome/browser/ui/views/page_info/merchant_trust_side_panel_coordinator_browsertest.cc
@@ -34,8 +34,8 @@
 
 namespace {
 const char kMerchantReviewsUrl[] = "reviews.test";
-const char kUrlWithMerchantTrustData[] = "merchant.test";
-const char kUrlWithoutMerchantTrustData[] = "no-merchant.test";
+const char kUrlWithMerchantTrustData[] = "a.test";
+const char kUrlWithoutMerchantTrustData[] = "b.test";
 
 page_info::MerchantData CreateValidMerchantData() {
   page_info::MerchantData merchant_data;
@@ -49,8 +49,7 @@
 
 class MockMerchantTrustService : public page_info::MerchantTrustService {
  public:
- MockMerchantTrustService()
-      : MerchantTrustService(nullptr, false, nullptr) {}
+  MockMerchantTrustService() : MerchantTrustService(nullptr, false, nullptr) {}
   MOCK_METHOD(void,
               GetMerchantTrustInfo,
               (const GURL&, page_info::MerchantDataCallback),
@@ -193,8 +192,104 @@
             kMerchantReviewsGURL);
 }
 
-// TODO(crbug.com/378671877): Add tests for same tab, replace history
-// navigations.
+IN_PROC_BROWSER_TEST_F(MerchantTrustSidePanelCoordinatorBrowserTest,
+                       ShowSameTabNavSameDocumentReplaceState) {
+  GURL kGURLWithMerchantTrustData = CreateUrl(kUrlWithMerchantTrustData);
+  ASSERT_TRUE(
+      ui_test_utils::NavigateToURL(browser(), kGURLWithMerchantTrustData));
+  ASSERT_EQ(side_panel_coordinator()->GetCurrentEntryId(), std::nullopt);
+
+  // Test showing a side panel.
+  GURL kMerchantReviewsGURL = CreateUrl(kMerchantReviewsUrl);
+  ShowMerchantTrustSidePanel(web_contents(), kMerchantReviewsGURL);
+  EXPECT_TRUE(side_panel_coordinator()->IsSidePanelShowing());
+  EXPECT_EQ(side_panel_coordinator()->GetCurrentEntryId(),
+            SidePanelEntry::Id::kMerchantTrust);
+
+  // Replace state with new path.
+  GURL kUrlMerchantTrustWithPath2 =
+      kGURLWithMerchantTrustData.Resolve("/title2.html");
+  ASSERT_TRUE(content::ExecJs(web_contents(),
+                              "history.replaceState({},'','title2.html')"));
+  EXPECT_TRUE(content::WaitForLoadStop(web_contents()));
+
+  // Check that side panel remains open on replace state.
+  EXPECT_TRUE(side_panel_coordinator()->IsSidePanelShowing());
+  EXPECT_EQ(side_panel_coordinator()->GetCurrentEntryId(),
+            SidePanelEntry::Id::kMerchantTrust);
+
+  // Check that the MerchantTrust url remains the same.
+  EXPECT_TRUE(side_panel_coordinator()->GetCurrentSidePanelEntryForTesting());
+  EXPECT_EQ(side_panel_coordinator()
+                ->GetCurrentSidePanelEntryForTesting()
+                ->GetOpenInNewTabURL(),
+            kMerchantReviewsGURL);
+}
+
+IN_PROC_BROWSER_TEST_F(MerchantTrustSidePanelCoordinatorBrowserTest,
+                       ShowSameTabNavSameDocumentReplaceStateRef) {
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(), CreateUrl(kUrlWithMerchantTrustData)));
+  ASSERT_EQ(side_panel_coordinator()->GetCurrentEntryId(), std::nullopt);
+
+  // Test showing a side panel.
+  GURL kMerchantReviewsGURL = CreateUrl(kMerchantReviewsUrl);
+  ShowMerchantTrustSidePanel(web_contents(), kMerchantReviewsGURL);
+  EXPECT_TRUE(side_panel_coordinator()->IsSidePanelShowing());
+  EXPECT_EQ(side_panel_coordinator()->GetCurrentEntryId(),
+            SidePanelEntry::Id::kMerchantTrust);
+
+  // Replace state with anchor.
+  ASSERT_TRUE(
+      content::ExecJs(web_contents(), "history.replaceState({},'','#ref')"));
+  EXPECT_TRUE(content::WaitForLoadStop(web_contents()));
+
+  // Check that side panel remains open on replace state.
+  EXPECT_TRUE(side_panel_coordinator()->IsSidePanelShowing());
+  EXPECT_EQ(side_panel_coordinator()->GetCurrentEntryId(),
+            SidePanelEntry::Id::kMerchantTrust);
+
+  // Check that the AboutThisSite url remains the same.
+  EXPECT_TRUE(side_panel_coordinator()->GetCurrentSidePanelEntryForTesting());
+  EXPECT_EQ(side_panel_coordinator()
+                ->GetCurrentSidePanelEntryForTesting()
+                ->GetOpenInNewTabURL(),
+            kMerchantReviewsGURL);
+}
+
+IN_PROC_BROWSER_TEST_F(MerchantTrustSidePanelCoordinatorBrowserTest,
+                       ShowSameTabNavSameDocumentPushState) {
+  GURL kGURLWithMerchantTrustData = CreateUrl(kUrlWithMerchantTrustData);
+  ASSERT_TRUE(
+      ui_test_utils::NavigateToURL(browser(), kGURLWithMerchantTrustData));
+  ASSERT_EQ(side_panel_coordinator()->GetCurrentEntryId(), std::nullopt);
+
+  // Test showing a side panel.
+  ShowMerchantTrustSidePanel(web_contents(), kGURLWithMerchantTrustData);
+  EXPECT_TRUE(side_panel_coordinator()->IsSidePanelShowing());
+  EXPECT_EQ(side_panel_coordinator()->GetCurrentEntryId(),
+            SidePanelEntry::Id::kMerchantTrust);
+
+  // Push state with new path.
+  GURL kUrlMerchantTrustWithPath2 =
+      kGURLWithMerchantTrustData.Resolve("/title2.html");
+  ASSERT_TRUE(content::ExecJs(web_contents(),
+                              "history.pushState({},'','title2.html')"));
+  EXPECT_TRUE(content::WaitForLoadStop(web_contents()));
+
+  // Check that side panel remains open on push state.
+  EXPECT_TRUE(side_panel_coordinator()->IsSidePanelShowing());
+  EXPECT_EQ(side_panel_coordinator()->GetCurrentEntryId(),
+            SidePanelEntry::Id::kMerchantTrust);
+
+  // Check that the MerchantTrust url isn't changed.
+
+  EXPECT_TRUE(side_panel_coordinator()->GetCurrentSidePanelEntryForTesting());
+  EXPECT_EQ(side_panel_coordinator()
+                ->GetCurrentSidePanelEntryForTesting()
+                ->GetOpenInNewTabURL(),
+            kGURLWithMerchantTrustData);
+}
 
 IN_PROC_BROWSER_TEST_F(MerchantTrustSidePanelCoordinatorBrowserTest,
                        RemainsClosedOnNonMerchantSameTabNav) {
diff --git a/chrome/browser/ui/views/payments/contact_info_editor_view_controller.cc b/chrome/browser/ui/views/payments/contact_info_editor_view_controller.cc
index c8b1d0c..bb7b391f 100644
--- a/chrome/browser/ui/views/payments/contact_info_editor_view_controller.cc
+++ b/chrome/browser/ui/views/payments/contact_info_editor_view_controller.cc
@@ -12,10 +12,10 @@
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/autofill_structured_address_component.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/geo/autofill_country.h"
 #include "components/autofill/core/browser/geo/phone_number_i18n.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/payments/content/payment_request_spec.h"
 #include "components/payments/content/payment_request_state.h"
diff --git a/chrome/browser/ui/views/payments/payment_request_views_util.cc b/chrome/browser/ui/views/payments/payment_request_views_util.cc
index 1cb4a679..939c5552 100644
--- a/chrome/browser/ui/views/payments/payment_request_views_util.cc
+++ b/chrome/browser/ui/views/payments/payment_request_views_util.cc
@@ -14,10 +14,10 @@
 #include "chrome/browser/ui/views/payments/payment_request_sheet_controller.h"
 #include "chrome/grit/branded_strings.h"
 #include "chrome/grit/theme_resources.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/geo/phone_number_i18n.h"
 #include "components/payments/content/icon/icon_size.h"
diff --git a/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.cc b/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.cc
index 20ac59d2..c3b3fcb2 100644
--- a/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.cc
+++ b/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.cc
@@ -14,16 +14,16 @@
 #include "chrome/browser/ui/views/payments/validating_textfield.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/autofill/core/browser/address_data_manager.h"
-#include "components/autofill/core/browser/address_normalizer.h"
 #include "components/autofill/core/browser/autofill_address_util.h"
 #include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/data_quality/addresses/address_normalizer.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/geo/address_i18n.h"
 #include "components/autofill/core/browser/geo/autofill_country.h"
 #include "components/autofill/core/browser/geo/phone_number_i18n.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/ui/country_combobox_model.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/autofill/core/common/autofill_l10n_util.h"
 #include "components/payments/content/payment_request_state.h"
diff --git a/chrome/browser/ui/views/tabs/fade_footer_view.cc b/chrome/browser/ui/views/tabs/fade_footer_view.cc
index baa1d8a..ef70f2e 100644
--- a/chrome/browser/ui/views/tabs/fade_footer_view.cc
+++ b/chrome/browser/ui/views/tabs/fade_footer_view.cc
@@ -111,13 +111,14 @@
 BEGIN_TEMPLATE_METADATA(FooterRow_PerformanceRowData, FooterRow)
 END_METADATA
 
-using FooterRow_RecentActivityRowData = FooterRow<RecentActivityRowData>;
-BEGIN_TEMPLATE_METADATA(FooterRow_RecentActivityRowData, FooterRow)
+using FooterRow_CollaborationMessagingRowData =
+    FooterRow<CollaborationMessagingRowData>;
+BEGIN_TEMPLATE_METADATA(FooterRow_CollaborationMessagingRowData, FooterRow)
 END_METADATA
 
 template class FooterRow<AlertFooterRowData>;
 template class FooterRow<PerformanceRowData>;
-template class FooterRow<RecentActivityRowData>;
+template class FooterRow<CollaborationMessagingRowData>;
 
 // FadeAlertFooterRow
 // -----------------------------------------------------------------------
@@ -178,14 +179,15 @@
 BEGIN_METADATA(FadePerformanceFooterRow)
 END_METADATA
 
-// FadeRecentActivityFooterRow
+// FadeCollaborationMessagingFooterRow
 // -----------------------------------------------------------------------
 
-void FadeRecentActivityFooterRow::SetData(const RecentActivityRowData& data) {
+void FadeCollaborationMessagingFooterRow::SetData(
+    const CollaborationMessagingRowData& data) {
   data_ = data;
 
-  if (!data_.should_show_recent_activity) {
-    // Empty section if recent activity should be hidden.
+  if (!data_.should_show_collaboration_messaging) {
+    // Empty section if collaboration messaging should be hidden.
     SetContent(ui::ImageModel(), std::u16string());
     return;
   }
@@ -204,14 +206,14 @@
              data_.text);
 }
 
-RecentActivityRowData::RecentActivityRowData() = default;
-RecentActivityRowData::~RecentActivityRowData() = default;
-RecentActivityRowData::RecentActivityRowData(
-    const RecentActivityRowData& other) = default;
-RecentActivityRowData& RecentActivityRowData::operator=(
-    const RecentActivityRowData& other) = default;
+CollaborationMessagingRowData::CollaborationMessagingRowData() = default;
+CollaborationMessagingRowData::~CollaborationMessagingRowData() = default;
+CollaborationMessagingRowData::CollaborationMessagingRowData(
+    const CollaborationMessagingRowData& other) = default;
+CollaborationMessagingRowData& CollaborationMessagingRowData::operator=(
+    const CollaborationMessagingRowData& other) = default;
 
-BEGIN_METADATA(FadeRecentActivityFooterRow)
+BEGIN_METADATA(FadeCollaborationMessagingFooterRow)
 END_METADATA
 
 // FooterView
@@ -236,11 +238,12 @@
       std::make_unique<FadePerformanceFooterRow>(/* is_fade_out_view =*/false),
       std::make_unique<FadePerformanceFooterRow>(/* is_fade_out_view =*/true)));
 
-  recent_activity_row_ = AddChildView(std::make_unique<RecentActivityFadeView>(
-      std::make_unique<FadeRecentActivityFooterRow>(
-          /* is_fade_out_view =*/false),
-      std::make_unique<FadeRecentActivityFooterRow>(
-          /* is_fade_out_view =*/true)));
+  collaboration_messaging_row_ =
+      AddChildView(std::make_unique<CollaborationMessagingFadeView>(
+          std::make_unique<FadeCollaborationMessagingFooterRow>(
+              /* is_fade_out_view =*/false),
+          std::make_unique<FadeCollaborationMessagingFooterRow>(
+              /* is_fade_out_view =*/true)));
 
   alert_row_->SetProperty(
       views::kFlexBehaviorKey,
@@ -254,7 +257,7 @@
                                views::MinimumFlexSizeRule::kScaleToMinimum,
                                views::MaximumFlexSizeRule::kUnbounded, true));
 
-  recent_activity_row_->SetProperty(
+  collaboration_messaging_row_->SetProperty(
       views::kFlexBehaviorKey,
       views::FlexSpecification(views::LayoutOrientation::kHorizontal,
                                views::MinimumFlexSizeRule::kScaleToMinimum,
@@ -274,21 +277,23 @@
   UpdateVisibility();
 }
 
-void FooterView::SetRecentActivityData(const RecentActivityRowData& data) {
-  recent_activity_row_->SetData(data);
+void FooterView::SetCollaborationMessagingData(
+    const CollaborationMessagingRowData& data) {
+  collaboration_messaging_row_->SetData(data);
   UpdateVisibility();
 }
 
 void FooterView::SetFade(double percent) {
   alert_row_->SetFade(percent);
   performance_row_->SetFade(percent);
-  recent_activity_row_->SetFade(percent);
+  collaboration_messaging_row_->SetFade(percent);
 }
 
 void FooterView::UpdateVisibility() {
   SetVisible(performance_row_->CalculatePreferredSize({}).height() > 0 ||
              alert_row_->CalculatePreferredSize({}).height() > 0 ||
-             recent_activity_row_->CalculatePreferredSize({}).height() > 0);
+             collaboration_messaging_row_->CalculatePreferredSize({}).height() >
+                 0);
 }
 
 using FadeWrapper_View_PerformanceRowData =
@@ -303,10 +308,11 @@
 BEGIN_TEMPLATE_METADATA(FadeWrapper_View_AlertFooterRowData, FadeWrapper)
 END_METADATA
 
-using FadeWrapper_View_RecentActivityRowData =
-    FadeWrapper<views::View, RecentActivityRowData>;
+using FadeWrapper_View_CollaborationMessagingRowData =
+    FadeWrapper<views::View, CollaborationMessagingRowData>;
 
-BEGIN_TEMPLATE_METADATA(FadeWrapper_View_RecentActivityRowData, FadeWrapper)
+BEGIN_TEMPLATE_METADATA(FadeWrapper_View_CollaborationMessagingRowData,
+                        FadeWrapper)
 END_METADATA
 
 using FadeView_FadeAlertFooterRow_FadeAlertFooterRow_AlertFooterRowData =
@@ -327,13 +333,13 @@
     FadeView)
 END_METADATA
 
-using FadeView_FadeRecentActivityFooterRow_FadeRecentActivityFooterRow_RecentActivityRowData =
-    FadeView<FadeRecentActivityFooterRow,
-             FadeRecentActivityFooterRow,
-             RecentActivityRowData>;
+using FadeView_FadeCollaborationMessagingFooterRow_FadeCollaborationMessagingFooterRow_CollaborationMessagingRowData =
+    FadeView<FadeCollaborationMessagingFooterRow,
+             FadeCollaborationMessagingFooterRow,
+             CollaborationMessagingRowData>;
 
 BEGIN_TEMPLATE_METADATA(
-    FadeView_FadeRecentActivityFooterRow_FadeRecentActivityFooterRow_RecentActivityRowData,
+    FadeView_FadeCollaborationMessagingFooterRow_FadeCollaborationMessagingFooterRow_CollaborationMessagingRowData,
     FadeView)
 END_METADATA
 
diff --git a/chrome/browser/ui/views/tabs/fade_footer_view.h b/chrome/browser/ui/views/tabs/fade_footer_view.h
index 04875939..bede8528 100644
--- a/chrome/browser/ui/views/tabs/fade_footer_view.h
+++ b/chrome/browser/ui/views/tabs/fade_footer_view.h
@@ -27,15 +27,16 @@
   int64_t memory_usage_in_bytes = 0;
 };
 
-struct RecentActivityRowData {
-  bool should_show_recent_activity = false;
+struct CollaborationMessagingRowData {
+  bool should_show_collaboration_messaging = false;
   std::u16string text;
   std::optional<ui::ImageModel> avatar = std::nullopt;
 
-  RecentActivityRowData();
-  ~RecentActivityRowData();
-  RecentActivityRowData(const RecentActivityRowData& other);
-  RecentActivityRowData& operator=(const RecentActivityRowData& other);
+  CollaborationMessagingRowData();
+  ~CollaborationMessagingRowData();
+  CollaborationMessagingRowData(const CollaborationMessagingRowData& other);
+  CollaborationMessagingRowData& operator=(
+      const CollaborationMessagingRowData& other);
 };
 
 template <typename T>
@@ -76,9 +77,10 @@
     FadeWrapper<views::View, PerformanceRowData>;
 DECLARE_TEMPLATE_METADATA(FadeWrapper_View_PerformanceRowData, FadeWrapper);
 
-using FadeWrapper_View_RecentActivityRowData =
-    FadeWrapper<views::View, RecentActivityRowData>;
-DECLARE_TEMPLATE_METADATA(FadeWrapper_View_RecentActivityRowData, FadeWrapper);
+using FadeWrapper_View_CollaborationMessagingRowData =
+    FadeWrapper<views::View, CollaborationMessagingRowData>;
+DECLARE_TEMPLATE_METADATA(FadeWrapper_View_CollaborationMessagingRowData,
+                          FadeWrapper);
 
 using FooterRow_AlertFooterRowData = FooterRow<AlertFooterRowData>;
 DECLARE_TEMPLATE_METADATA(FooterRow_AlertFooterRowData, FooterRow);
@@ -86,8 +88,9 @@
 using FooterRow_PerformanceRowData = FooterRow<PerformanceRowData>;
 DECLARE_TEMPLATE_METADATA(FooterRow_PerformanceRowData, FooterRow);
 
-using FooterRow_RecentActivityRowData = FooterRow<RecentActivityRowData>;
-DECLARE_TEMPLATE_METADATA(FooterRow_RecentActivityRowData, FooterRow);
+using FooterRow_CollaborationMessagingRowData =
+    FooterRow<CollaborationMessagingRowData>;
+DECLARE_TEMPLATE_METADATA(FooterRow_CollaborationMessagingRowData, FooterRow);
 
 class FadeAlertFooterRow : public FooterRow<AlertFooterRowData> {
   using FooterRowAlertFooterRowData = FooterRow<AlertFooterRowData>;
@@ -115,17 +118,20 @@
   void SetData(const PerformanceRowData& data) override;
 };
 
-class FadeRecentActivityFooterRow : public FooterRow<RecentActivityRowData> {
-  using FooterRowRecentActivityRowData = FooterRow<RecentActivityRowData>;
-  METADATA_HEADER(FadeRecentActivityFooterRow, FooterRowRecentActivityRowData)
+class FadeCollaborationMessagingFooterRow
+    : public FooterRow<CollaborationMessagingRowData> {
+  using FooterRowCollaborationMessagingRowData =
+      FooterRow<CollaborationMessagingRowData>;
+  METADATA_HEADER(FadeCollaborationMessagingFooterRow,
+                  FooterRowCollaborationMessagingRowData)
 
  public:
-  explicit FadeRecentActivityFooterRow(bool is_fade_out_view)
-      : FooterRow<RecentActivityRowData>(is_fade_out_view) {}
-  ~FadeRecentActivityFooterRow() override = default;
+  explicit FadeCollaborationMessagingFooterRow(bool is_fade_out_view)
+      : FooterRow<CollaborationMessagingRowData>(is_fade_out_view) {}
+  ~FadeCollaborationMessagingFooterRow() override = default;
 
   // FadeWrapper:
-  void SetData(const RecentActivityRowData& data) override;
+  void SetData(const CollaborationMessagingRowData& data) override;
 };
 
 class FooterView : public views::View {
@@ -137,9 +143,10 @@
   using PerformanceFadeView = FadeView<FadePerformanceFooterRow,
                                        FadePerformanceFooterRow,
                                        PerformanceRowData>;
-  using RecentActivityFadeView = FadeView<FadeRecentActivityFooterRow,
-                                          FadeRecentActivityFooterRow,
-                                          RecentActivityRowData>;
+  using CollaborationMessagingFadeView =
+      FadeView<FadeCollaborationMessagingFooterRow,
+               FadeCollaborationMessagingFooterRow,
+               CollaborationMessagingRowData>;
   DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kHoverCardFooterElementId);
 
   FooterView();
@@ -147,7 +154,7 @@
 
   void SetAlertData(const AlertFooterRowData& data);
   void SetPerformanceData(const PerformanceRowData& data);
-  void SetRecentActivityData(const RecentActivityRowData& data);
+  void SetCollaborationMessagingData(const CollaborationMessagingRowData& data);
   void SetFade(double percent);
 
   AlertFadeView* GetAlertRowForTesting() { return alert_row_; }
@@ -156,8 +163,8 @@
     return performance_row_;
   }
 
-  RecentActivityFadeView* GetRecentActivityRowForTesting() {
-    return recent_activity_row_;
+  CollaborationMessagingFadeView* GetCollaborationMessagingRowForTesting() {
+    return collaboration_messaging_row_;
   }
 
   views::FlexLayout* flex_layout() { return flex_layout_; }
@@ -166,7 +173,8 @@
   raw_ptr<views::FlexLayout> flex_layout_ = nullptr;
   raw_ptr<AlertFadeView> alert_row_ = nullptr;
   raw_ptr<PerformanceFadeView> performance_row_ = nullptr;
-  raw_ptr<RecentActivityFadeView> recent_activity_row_ = nullptr;
+  raw_ptr<CollaborationMessagingFadeView> collaboration_messaging_row_ =
+      nullptr;
 
   void UpdateVisibility();
 };
diff --git a/chrome/browser/ui/views/tabs/glic_button.cc b/chrome/browser/ui/views/tabs/glic_button.cc
index 063ec45..47b0f3b5 100644
--- a/chrome/browser/ui/views/tabs/glic_button.cc
+++ b/chrome/browser/ui/views/tabs/glic_button.cc
@@ -17,7 +17,8 @@
 #include "ui/views/view_class_properties.h"
 
 #if BUILDFLAG(ENABLE_GLIC)
-#include "chrome/browser/glic/glic_window_manager.h"
+#include "chrome/browser/glic/glic_keyed_service.h"
+#include "chrome/browser/glic/glic_keyed_service_factory.h"
 #endif  // BUILDFLAG(ENABLE_GLIC)
 
 namespace glic {
@@ -48,8 +49,9 @@
 void GlicButton::NotifyClick(const ui::Event& event) {
   TabStripControlButton::NotifyClick(event);
 #if BUILDFLAG(ENABLE_GLIC)
-  GlicWindowManager::GetInstance()->ShowGlicWindowForProfile(
-      tab_strip_controller_->GetProfile());
+  glic::GlicKeyedServiceFactory::GetGlicKeyedService(
+      tab_strip_controller_->GetProfile())
+      ->LaunchUI();
 #endif  // BUILDFLAG(ENABLE_GLIC)
 }
 
diff --git a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc
index 611c1a3..6ff2e463 100644
--- a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc
+++ b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc
@@ -25,6 +25,7 @@
 #include "base/ranges/algorithm.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/collaboration/collaboration_service_factory.h"
 #include "chrome/browser/data_sharing/data_sharing_service_factory.h"
 #include "chrome/browser/feature_engagement/tracker_factory.h"
 #include "chrome/browser/profiles/profile.h"
@@ -59,10 +60,13 @@
 #include "chrome/browser/user_education/user_education_service.h"
 #include "chrome/browser/user_education/user_education_service_factory.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/collaboration/public/collaboration_service.h"
 #include "components/data_sharing/public/features.h"
+#include "components/data_sharing/public/group_data.h"
 #include "components/feature_engagement/public/feature_constants.h"
 #include "components/saved_tab_groups/public/features.h"
 #include "components/saved_tab_groups/public/saved_tab_group.h"
+#include "components/saved_tab_groups/public/types.h"
 #include "components/tab_groups/tab_group_color.h"
 #include "components/tab_groups/tab_group_id.h"
 #include "components/tab_groups/tab_group_visual_data.h"
@@ -329,7 +333,10 @@
   } else if (tab_groups::IsTabGroupsSaveV2Enabled()) {
     menu_items_.push_back(AddChildView(BuildNewTabInGroupButton()));
     menu_items_.push_back(AddChildView(BuildMoveGroupToNewWindowButton()));
-    menu_items_.push_back(AddChildView(BuildUngroupButton()));
+
+    if (OwnsGroup()) {
+      menu_items_.push_back(AddChildView(BuildUngroupButton()));
+    }
 
     if (CanShareGroups()) {
       menu_items_.push_back(AddChildView(BuildManageSharedGroupButton()));
@@ -381,8 +388,6 @@
         button->SetVisible(CanMoveGroupToNewWindow());
         break;
       }
-      default: {
-      }
     }
   }
 }
@@ -606,9 +611,9 @@
 }
 
 bool TabGroupEditorBubbleView::CanSaveGroups() const {
-  return (browser_->profile()->IsRegularProfile() &&
-          tab_groups::SavedTabGroupUtils::GetServiceForProfile(
-              browser_->profile()));
+  return browser_->profile()->IsRegularProfile() &&
+         tab_groups::SavedTabGroupUtils::GetServiceForProfile(
+             browser_->profile());
 }
 
 bool TabGroupEditorBubbleView::CanShareGroups() const {
@@ -618,6 +623,37 @@
              data_sharing::features::kDataSharingFeature);
 }
 
+bool TabGroupEditorBubbleView::OwnsGroup() const {
+  tab_groups::TabGroupSyncService* tab_group_service =
+      tab_groups::SavedTabGroupUtils::GetServiceForProfile(browser_->profile());
+  if (!tab_group_service) {
+    return true;
+  }
+
+  const std::optional<tab_groups::SavedTabGroup> maybe_saved_group =
+      tab_group_service->GetGroup(group_);
+  if (!maybe_saved_group.has_value()) {
+    return true;
+  }
+
+  std::optional<tab_groups::CollaborationId> collaboration_id =
+      maybe_saved_group->collaboration_id();
+  if (!collaboration_id) {
+    return true;
+  }
+
+  collaboration::CollaborationService* collaboration_service =
+      collaboration::CollaborationServiceFactory::GetForProfile(
+          browser_->profile());
+  if (!collaboration_service) {
+    return true;
+  }
+
+  data_sharing::GroupId group_id(collaboration_id->value());
+  return data_sharing::MemberRole::kOwner ==
+         collaboration_service->GetCurrentUserRoleForGroup(group_id);
+}
+
 bool TabGroupEditorBubbleView::IsGroupSaved() const {
   tab_groups::TabGroupSyncService* tab_group_service =
       tab_groups::SavedTabGroupUtils::GetServiceForProfile(browser_->profile());
diff --git a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.h b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.h
index 758be4e9..fcfe03d 100644
--- a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.h
+++ b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.h
@@ -87,6 +87,9 @@
   bool IsGroupSaved() const;
   bool IsGroupShared() const;
   bool ShouldShowSavedFooter() const;
+  // Returns true if the user created the group. Returns false in cases where
+  // the user was invited to join the group.
+  bool OwnsGroup() const;
 
   // When certain settings change, the menu items need to be updated, this
   // method destroys the children of the view, and then recreates them in the
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
index 87a5ccf..615f39ad 100644
--- a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
+++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/ui/color/chrome_color_id.h"
 #include "chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.h"
+#include "chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.h"
 #include "chrome/browser/ui/tabs/tab_renderer_data.h"
 #include "chrome/browser/ui/tabs/tab_style.h"
 #include "chrome/browser/ui/thumbnails/thumbnail_image.h"
@@ -474,32 +475,36 @@
 
 TabHoverCardBubbleView::~TabHoverCardBubbleView() = default;
 
-RecentActivityRowData TabHoverCardBubbleView::GetRecentActivityData(
+CollaborationMessagingRowData
+TabHoverCardBubbleView::GetCollaborationMessagingData(
     const TabRendererData& tab_data) {
-  RecentActivityRowData recent_activity_data;
-  bool show_recent_activity = false;
+  using collaboration::messaging::CollaborationEvent;
 
-  if (auto message = tab_data.recent_activity) {
-    if (auto member = message->attribution.triggering_user) {
-      using collaboration::messaging::CollaborationEvent;
+  CollaborationMessagingRowData collaboration_messaging_data;
+  collaboration_messaging_data.should_show_collaboration_messaging = false;
 
-      const std::u16string username = base::UTF8ToUTF16(member->display_name);
-      const CollaborationEvent action = message->collaboration_event;
-
-      if (action == CollaborationEvent::TAB_ADDED) {
-        recent_activity_data.text = l10n_util::GetStringFUTF16(
-            IDS_DATA_SHARING_RECENT_ACTIVITY_MEMBER_ADDED_THIS_TAB, username);
-        show_recent_activity = true;
-      } else if (action == CollaborationEvent::TAB_UPDATED) {
-        recent_activity_data.text = l10n_util::GetStringFUTF16(
-            IDS_DATA_SHARING_RECENT_ACTIVITY_MEMBER_CHANGED_THIS_TAB, username);
-        show_recent_activity = true;
-      }
-    }
+  auto data = tab_data.collaboration_messaging;
+  if (!data || !data->HasMessage()) {
+    return collaboration_messaging_data;
   }
-  recent_activity_data.should_show_recent_activity = show_recent_activity;
 
-  return recent_activity_data;
+  switch (data->collaboration_event()) {
+    case CollaborationEvent::TAB_ADDED:
+      collaboration_messaging_data.text = l10n_util::GetStringFUTF16(
+          IDS_DATA_SHARING_RECENT_ACTIVITY_MEMBER_ADDED_THIS_TAB,
+          data->given_name());
+      break;
+    case CollaborationEvent::TAB_UPDATED:
+      collaboration_messaging_data.text = l10n_util::GetStringFUTF16(
+          IDS_DATA_SHARING_RECENT_ACTIVITY_MEMBER_CHANGED_THIS_TAB,
+          data->given_name());
+      break;
+    default:
+      NOTREACHED();
+  }
+  collaboration_messaging_data.should_show_collaboration_messaging = true;
+
+  return collaboration_messaging_data;
 }
 
 void TabHoverCardBubbleView::UpdateCardContent(const Tab* tab) {
@@ -565,12 +570,15 @@
   title_label_->SetData({title, is_filename});
   domain_label_->SetData({domain, false});
 
-  RecentActivityRowData recent_activity_data = GetRecentActivityData(tab_data);
-  bool show_recent_activity = recent_activity_data.should_show_recent_activity;
+  CollaborationMessagingRowData collaboration_messaging_data =
+      GetCollaborationMessagingData(tab_data);
+  bool show_collaboration_messaging =
+      collaboration_messaging_data.should_show_collaboration_messaging;
 
-  // Recent activity takes precedence over discard status for shared tabs.
+  // Collaboration messaging takes precedence over discard status for shared
+  // tabs.
   const bool show_discard_status =
-      !show_recent_activity && tab_data.should_show_discard_status;
+      !show_collaboration_messaging && tab_data.should_show_discard_status;
   const int64_t tab_memory_usage_in_bytes =
       tab_data.tab_resource_usage
           ? tab_data.tab_resource_usage->memory_usage_in_bytes()
@@ -581,14 +589,14 @@
           : false;
   // High memory usage notification is considered a tab alert. Show it even
   // if the memory usage in hover cards pref is disabled.
-  // However, recent activity takes precedence over memory usage for
+  // However, collaboration messaging takes precedence over memory usage for
   // shared tabs.
   const bool show_memory_usage =
-      !show_recent_activity && !show_discard_status &&
+      !show_collaboration_messaging && !show_discard_status &&
       ((bubble_params_.show_memory_usage && tab_memory_usage_in_bytes > 0) ||
        is_high_memory_usage);
   const bool show_footer = alert_state_.has_value() || show_discard_status ||
-                           show_memory_usage || show_recent_activity;
+                           show_memory_usage || show_collaboration_messaging;
 
   footer_view_->SetAlertData({alert_state_, show_discard_status,
                               tab_data.discarded_memory_savings_in_bytes});
@@ -596,7 +604,7 @@
   footer_view_->SetPerformanceData(
       {show_memory_usage, is_high_memory_usage, tab_memory_usage_in_bytes});
 
-  footer_view_->SetRecentActivityData(recent_activity_data);
+  footer_view_->SetCollaborationMessagingData(collaboration_messaging_data);
 
   if (thumbnail_view_) {
     // We only clip the corners of the fade image when there isn't a footer.
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.h b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.h
index 3844fa2..c138228 100644
--- a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.h
+++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.h
@@ -63,8 +63,9 @@
   TabHoverCardBubbleView& operator=(const TabHoverCardBubbleView&) = delete;
   ~TabHoverCardBubbleView() override;
 
-  // Create the RecentActivityRowData from TabRendererData.
-  RecentActivityRowData GetRecentActivityData(const TabRendererData& tab_data);
+  // Create the CollaborationMessagingRowData from TabRendererData.
+  CollaborationMessagingRowData GetCollaborationMessagingData(
+      const TabRendererData& tab_data);
 
   // Updates and formats title, alert state, domain, and preview image.
   void UpdateCardContent(const Tab* tab);
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_hover_card_controller_interactive_uitest.cc
index ce3fad5c..ba01ee9 100644
--- a/chrome/browser/ui/views/tabs/tab_hover_card_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_hover_card_controller_interactive_uitest.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.h"
 #include "chrome/browser/ui/performance_controls/test_support/memory_metrics_refresh_waiter.h"
 #include "chrome/browser/ui/performance_controls/test_support/memory_saver_interactive_test_mixin.h"
+#include "chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.h"
 #include "chrome/browser/ui/tabs/tab_enums.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/views/tabs/fade_footer_view.h"
@@ -38,6 +39,8 @@
 #include "chrome/test/base/interactive_test_utils.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "chrome/test/interaction/interactive_browser_test.h"
+#include "components/collaboration/public/messaging/message.h"
+#include "components/data_sharing/public/group_data.h"
 #include "components/lookalikes/core/safety_tip_test_utils.h"
 #include "components/performance_manager/public/decorators/process_metrics_decorator.h"
 #include "components/performance_manager/public/performance_manager.h"
@@ -81,6 +84,25 @@
   return new_tab_data;
 }
 
+collaboration::messaging::PersistentMessage CreateMessage(
+    std::string given_name,
+    std::string avatar_url,
+    collaboration::messaging::CollaborationEvent event) {
+  data_sharing::GroupMember member;
+  member.given_name = given_name;
+  member.avatar_url = GURL(avatar_url);
+
+  collaboration::messaging::MessageAttribution attribution;
+  attribution.triggering_user = member;
+
+  collaboration::messaging::PersistentMessage message;
+  message.type = collaboration::messaging::PersistentNotificationType::CHIP;
+  message.attribution = attribution;
+  message.collaboration_event = event;
+
+  return message;
+}
+
 }  // namespace
 
 class TabHoverCardInteractiveUiTest
@@ -461,10 +483,11 @@
         ->GetPrimaryViewForTesting();
   }
 
-  FadeRecentActivityFooterRow* GetPrimaryRecentActivityRowFromHoverCard(
+  FadeCollaborationMessagingFooterRow*
+  GetPrimaryCollaborationMessagingRowFromHoverCard(
       TabHoverCardBubbleView* bubble) {
     return bubble->GetFooterViewForTesting()
-        ->GetRecentActivityRowForTesting()
+        ->GetCollaborationMessagingRowForTesting()
         ->GetPrimaryViewForTesting();
   }
 
@@ -783,10 +806,10 @@
   EXPECT_EQ(hover_card_size.height(), total_children_height);
 }
 
-// Mocks that a tab has recent activity and verifies that the correct string
-// is displayed on the hover card.
+// Mocks that a tab has collaboration messaging and verifies that the correct
+// string is displayed on the hover card.
 IN_PROC_BROWSER_TEST_F(TabHoverCardFadeFooterInteractiveUiTest,
-                       HoverCardFooterShowsRecentActivity) {
+                       HoverCardFooterShowsCollaborationMessaging) {
   TabStrip* const tab_strip = GetTabStrip(browser());
   ASSERT_TRUE(
       AddTabAtIndex(1, GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_TYPED));
@@ -794,52 +817,52 @@
 
   // Clear alert state. Alerts take precedence over all other footers.
   tab_renderer_data.alert_state = {};
+  tab_groups::CollaborationMessagingTabData data;
+  tab_renderer_data.collaboration_messaging = data.GetWeakPtr();
 
   // Create a mock PersistentMessage
-  // Show recent activity status with TAB_ADDED event.
-  std::string username = std::string("User");
-  collaboration::messaging::PersistentMessage msg;
-  data_sharing::GroupMember triggering_user;
-  triggering_user.display_name = username;
-  msg.attribution.triggering_user = triggering_user;
-  msg.collaboration_event =
-      collaboration::messaging::CollaborationEvent::TAB_ADDED;
-  tab_renderer_data.recent_activity = msg;
+  // Show collaboration messaging status with TAB_ADDED event.
+  std::string given_name = "User";
+  std::string avatar_url = "URL";
+  data.SetMessage(
+      CreateMessage(given_name, avatar_url,
+                    collaboration::messaging::CollaborationEvent::TAB_ADDED));
 
   tab_strip->SetTabData(1, tab_renderer_data);
-  FadeRecentActivityFooterRow* const recent_activity_row =
-      GetPrimaryRecentActivityRowFromHoverCard(SimulateHoverTab(browser(), 1));
+  FadeCollaborationMessagingFooterRow* const collaboration_messaging_row =
+      GetPrimaryCollaborationMessagingRowFromHoverCard(
+          SimulateHoverTab(browser(), 1));
   EXPECT_EQ(l10n_util::GetStringFUTF16(
                 IDS_DATA_SHARING_RECENT_ACTIVITY_MEMBER_ADDED_THIS_TAB,
-                base::UTF8ToUTF16(username)),
-            recent_activity_row->footer_label()->GetText());
-  EXPECT_FALSE(recent_activity_row->icon()->GetImageModel().IsEmpty());
+                base::UTF8ToUTF16(given_name)),
+            collaboration_messaging_row->footer_label()->GetText());
+  EXPECT_FALSE(collaboration_messaging_row->icon()->GetImageModel().IsEmpty());
 
   // Hover card footer should update when we hover over another tab that is
   // not discarded
   SimulateHoverTab(browser(), 0);
-  EXPECT_TRUE(recent_activity_row->footer_label()->GetText().empty());
-  EXPECT_TRUE(recent_activity_row->icon()->GetImageModel().IsEmpty());
+  EXPECT_TRUE(collaboration_messaging_row->footer_label()->GetText().empty());
+  EXPECT_TRUE(collaboration_messaging_row->icon()->GetImageModel().IsEmpty());
 
   // Reset tab data by setting intermediate object. Without this, the new
   // tab_data is ignored because it is the same object.
   tab_strip->SetTabData(1, MakeTabRendererData());
 
-  // Change username and action to show recent activity with TAB_UPDATED event.
-  std::string username2 = std::string("Another User");
-  triggering_user.display_name = username2;
-  msg.attribution.triggering_user = triggering_user;
-  msg.collaboration_event =
-      collaboration::messaging::CollaborationEvent::TAB_UPDATED;
-  tab_renderer_data.recent_activity = msg;
+  // Change username and action to show collaboration messaging with TAB_UPDATED
+  // event.
+  std::string given_name2 = "Another User";
+  std::string avatar_url2 = "URL2";
+  data.SetMessage(
+      CreateMessage(given_name2, avatar_url2,
+                    collaboration::messaging::CollaborationEvent::TAB_UPDATED));
 
   tab_strip->SetTabData(1, tab_renderer_data);
   SimulateHoverTab(browser(), 1);
   EXPECT_EQ(l10n_util::GetStringFUTF16(
                 IDS_DATA_SHARING_RECENT_ACTIVITY_MEMBER_CHANGED_THIS_TAB,
-                base::UTF8ToUTF16(username2)),
-            recent_activity_row->footer_label()->GetText());
-  EXPECT_FALSE(recent_activity_row->icon()->GetImageModel().IsEmpty());
+                base::UTF8ToUTF16(given_name2)),
+            collaboration_messaging_row->footer_label()->GetText());
+  EXPECT_FALSE(collaboration_messaging_row->icon()->GetImageModel().IsEmpty());
 }
 
 #if BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/ui/views/tabs/tab_strip_combo_button.cc b/chrome/browser/ui/views/tabs/tab_strip_combo_button.cc
index a7255195..e4b303e 100644
--- a/chrome/browser/ui/views/tabs/tab_strip_combo_button.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip_combo_button.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/views/tabs/tab_strip_combo_button.h"
 
+#include "base/time/time.h"
 #include "chrome/browser/ui/browser_element_identifiers.h"
 #include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
 #include "chrome/browser/ui/layout_constants.h"
@@ -23,10 +24,26 @@
 #include "ui/views/view_class_properties.h"
 
 namespace {
+
+// LINT.IfChange(AccidentalClickType)
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class AccidentalClickType {
+  kClick = 0,
+  kAccidentalClick = 1,
+  kMaxValue = kAccidentalClick,
+};
+// LINT.ThenChange(//tools/metrics/histograms/metadata/tab/enums.xml:AccidentalClickType)
+
 constexpr int kSeparatorBorderRadius = 2;
 constexpr int kSeparatorWidth = 2;
 constexpr int kSeparatorWidthNoBackground = 1;
 constexpr int kSeparatorHeight = 16;
+constexpr base::TimeDelta kAccidentalClickThreshold = base::Seconds(1);
+constexpr char kNewTabButtonAccidentalClickName[] =
+    "Tabs.NewTabButton.AccidentalClicks";
+constexpr char kTabSearchAccidentalClickName[] =
+    "Tabs.TabSearch.AccidentalClicks";
 }  // namespace
 
 TabStripComboButton::TabStripComboButton(BrowserWindowInterface* browser,
@@ -57,7 +74,7 @@
   new_tab_button->GetViewAccessibility().SetName(
       l10n_util::GetStringUTF16(IDS_ACCNAME_NEWTAB));
   subscriptions_.push_back(new_tab_button->AddStateChangedCallback(
-      base::BindRepeating(&TabStripComboButton::UpdateSeparatorVisibility,
+      base::BindRepeating(&TabStripComboButton::OnNewTabButtonStateChanged,
                           base::Unretained(this))));
 
 #if BUILDFLAG(IS_LINUX)
@@ -87,8 +104,9 @@
                                     views::LayoutAlignment::kCenter);
   subscriptions_.push_back(
       tab_search_container->tab_search_button()->AddStateChangedCallback(
-          base::BindRepeating(&TabStripComboButton::UpdateSeparatorVisibility,
-                              base::Unretained(this))));
+          base::BindRepeating(
+              &TabStripComboButton::OnTabSearchButtonStateChanged,
+              base::Unretained(this))));
 
   auto* button_container = AddChildView(std::make_unique<views::View>());
   auto* separator_container = AddChildView(std::make_unique<views::View>());
@@ -110,6 +128,39 @@
 
 TabStripComboButton::~TabStripComboButton() {}
 
+void TabStripComboButton::OnNewTabButtonStateChanged() {
+  if (new_tab_button_->GetState() == views::Button::STATE_PRESSED) {
+    new_tab_button_last_pressed_ = base::TimeTicks::Now();
+    base::UmaHistogramEnumeration(kNewTabButtonAccidentalClickName,
+                                  AccidentalClickType::kClick);
+    if (!tab_search_button_last_pressed_.is_null() &&
+        (new_tab_button_last_pressed_ - tab_search_button_last_pressed_) <
+            kAccidentalClickThreshold) {
+      base::UmaHistogramEnumeration(kTabSearchAccidentalClickName,
+                                    AccidentalClickType::kAccidentalClick);
+    }
+  }
+
+  UpdateSeparatorVisibility();
+}
+
+void TabStripComboButton::OnTabSearchButtonStateChanged() {
+  if (tab_search_container_->tab_search_button()->GetState() ==
+      views::Button::STATE_PRESSED) {
+    tab_search_button_last_pressed_ = base::TimeTicks::Now();
+    base::UmaHistogramEnumeration(kTabSearchAccidentalClickName,
+                                  AccidentalClickType::kClick);
+    if (!new_tab_button_last_pressed_.is_null() &&
+        (tab_search_button_last_pressed_ - new_tab_button_last_pressed_) <
+            kAccidentalClickThreshold) {
+      base::UmaHistogramEnumeration(kNewTabButtonAccidentalClickName,
+                                    AccidentalClickType::kAccidentalClick);
+    }
+  }
+
+  UpdateSeparatorVisibility();
+}
+
 void TabStripComboButton::UpdateSeparatorVisibility() {
   const views::Button::ButtonState new_tab_button_state =
       new_tab_button_->GetState();
diff --git a/chrome/browser/ui/views/tabs/tab_strip_combo_button.h b/chrome/browser/ui/views/tabs/tab_strip_combo_button.h
index c5d3dae..60bf442 100644
--- a/chrome/browser/ui/views/tabs/tab_strip_combo_button.h
+++ b/chrome/browser/ui/views/tabs/tab_strip_combo_button.h
@@ -25,6 +25,8 @@
   TabStripComboButton& operator=(const TabStripComboButton&) = delete;
   ~TabStripComboButton() override;
 
+  void OnNewTabButtonStateChanged();
+  void OnTabSearchButtonStateChanged();
   void UpdateSeparatorVisibility();
 
   views::Button* new_tab_button() { return new_tab_button_; }
@@ -38,6 +40,8 @@
   raw_ptr<TabSearchContainer> tab_search_container_ = nullptr;
   raw_ptr<views::Separator> separator_ = nullptr;
 
+  base::TimeTicks new_tab_button_last_pressed_;
+  base::TimeTicks tab_search_button_last_pressed_;
   std::list<base::CallbackListSubscription> subscriptions_;
 };
 
diff --git a/chrome/browser/ui/views/user_education/browser_user_education_service.cc b/chrome/browser/ui/views/user_education/browser_user_education_service.cc
index 8134ae2..5b873847 100644
--- a/chrome/browser/ui/views/user_education/browser_user_education_service.cc
+++ b/chrome/browser/ui/views/user_education/browser_user_education_service.cc
@@ -256,20 +256,6 @@
                     .SetMetadata(115, "vykochko@chromium.org",
                                  "Triggered after autofill popup appears.")));
 
-  // kIPHAutofillManualFallbackFeature:
-  registry.RegisterFeature(std::move(
-      FeaturePromoSpecification::CreateForToastPromo(
-          feature_engagement::kIPHAutofillManualFallbackFeature,
-          kAutofillManualFallbackElementId, IDS_AUTOFILL_IPH_MANUAL_FALLBACK,
-          IDS_AUTOFILL_IPH_MANUAL_FALLBACK_SCREENREADER,
-          FeaturePromoSpecification::AcceleratorInfo())
-          .SetBubbleArrow(HelpBubbleArrow::kTopRight)
-          .SetMetadata(
-              123, "theocristea@chromium.org",
-              "User focuses a field, but autofill cannot be triggered "
-              "automatically because the field has autocomplete=garbage. In "
-              "this case, autofill can be triggered from the context menu.")));
-
   // kIPHAutofillPredictionImprovementsFeature:
   registry.RegisterFeature(std::move(
       FeaturePromoSpecification::CreateForCustomAction(
diff --git a/chrome/browser/ui/views/user_education/browser_user_education_service_unittest.cc b/chrome/browser/ui/views/user_education/browser_user_education_service_unittest.cc
index be2e9f04..f50818a 100644
--- a/chrome/browser/ui/views/user_education/browser_user_education_service_unittest.cc
+++ b/chrome/browser/ui/views/user_education/browser_user_education_service_unittest.cc
@@ -207,7 +207,6 @@
       &feature_engagement::kIPHBackNavigationMenuFeature,
       &feature_engagement::kIPHAutofillCreditCardBenefitFeature,
       &feature_engagement::kIPHAutofillExternalAccountProfileSuggestionFeature,
-      &feature_engagement::kIPHAutofillManualFallbackFeature,
       &feature_engagement::kIPHAutofillVirtualCardCVCSuggestionFeature,
       &feature_engagement::kIPHAutofillVirtualCardSuggestionFeature,
       &feature_engagement::kIPHCookieControlsFeature,
diff --git a/chrome/browser/ui/views/webid/account_selection_modal_view.cc b/chrome/browser/ui/views/webid/account_selection_modal_view.cc
index 08a49b70..0416914 100644
--- a/chrome/browser/ui/views/webid/account_selection_modal_view.cc
+++ b/chrome/browser/ui/views/webid/account_selection_modal_view.cc
@@ -898,14 +898,14 @@
     body_label_->SetFocusBehavior(FocusBehavior::ALWAYS);
   }
 
-  // Make sure not to keep dangling pointers around first. We do not reset
-  // `header_view_`, `title_label_`, `body_label_` and `brand_icon_` because
-  // this method does not remove the header.
+  // Make sure not to keep dangling pointers around first. We do not need to
+  // reset pointers to views in the header.
   use_other_account_button_ = nullptr;
   back_button_ = nullptr;
   continue_button_ = nullptr;
   cancel_button_ = nullptr;
   account_chooser_ = nullptr;
+  verifying_focus_view_ = nullptr;
 
   const std::vector<raw_ptr<views::View, VectorExperimental>> child_views =
       children();
diff --git a/chrome/browser/ui/views/webid/account_selection_modal_view.h b/chrome/browser/ui/views/webid/account_selection_modal_view.h
index da5c815..38bb338 100644
--- a/chrome/browser/ui/views/webid/account_selection_modal_view.h
+++ b/chrome/browser/ui/views/webid/account_selection_modal_view.h
@@ -167,58 +167,50 @@
   void ShowAccounts(const std::vector<IdentityRequestAccountPtr>& accounts,
                     bool is_single_account_chooser);
 
+  // The following are raw_ptrs for views in the header. These do not need to be
+  // reset by RemoveNonHeaderChildViewsAndUpdateHeaderIfNeeded().
   // View containing the header.
   raw_ptr<views::View> header_view_ = nullptr;
-
   // View containing the header icons.
   raw_ptr<views::View> header_icon_view_ = nullptr;
-
-  // View containing the use other account button.
-  raw_ptr<views::MdTextButton> use_other_account_button_ = nullptr;
-
-  // View containing the back button.
-  raw_ptr<views::View> back_button_ = nullptr;
-
-  // View containing the continue button.
-  raw_ptr<views::MdTextButton> continue_button_ = nullptr;
-
-  // View containing the cancel button.
-  raw_ptr<views::View> cancel_button_ = nullptr;
-
-  // View containing the account chooser.
-  raw_ptr<views::View> account_chooser_ = nullptr;
-
-  // View containing the view to focus on in the verifying sheet.
-  raw_ptr<views::View> verifying_focus_view_ = nullptr;
-
   // View containing the title.
   raw_ptr<views::Label> title_label_ = nullptr;
-
   // View containing the body.
   raw_ptr<views::Label> body_label_ = nullptr;
-
   // View containing the IDP brand icon image. This view is constructed in the
   // loading dialog but is only visible after the loading dialog.
   raw_ptr<BrandIconImageView> idp_brand_icon_ = nullptr;
-
   // View containing the spinner in the header. This spinner is shown until the
   // IDP brand icon is fetched.
   raw_ptr<views::Throbber> header_icon_spinner_ = nullptr;
-
   // View containing the IDP brand icon image meant to be shown in the request
   // permission dialog together with the RP icon. This icon is a smaller version
   // of `idp_brand_icon_` because it has to share the space in the header with
   // the RP icon.
   raw_ptr<BrandIconImageView> combined_icons_idp_brand_icon_ = nullptr;
-
   // View containing the RP brand icon image in the request permission dialog.
   raw_ptr<BrandIconImageView> combined_icons_rp_brand_icon_ = nullptr;
-
   // BoxLayoutView containing the IDP icon, arrow icon and RP icon in that
   // order, horizontally. This view is constructed in the loading dialog but
   // will be made visible only in the request permission dialog.
   raw_ptr<views::BoxLayoutView> combined_icons_ = nullptr;
 
+  // The following are raw_ptrs for view outside of the header. These MUST be
+  // reset in RemoveNonHeaderChildViewsAndUpdateHeaderIfNeeded(), as not
+  // resetting could result in a UAF.
+  // View containing the use other account button.
+  raw_ptr<views::MdTextButton> use_other_account_button_ = nullptr;
+  // View containing the back button.
+  raw_ptr<views::View> back_button_ = nullptr;
+  // View containing the continue button.
+  raw_ptr<views::MdTextButton> continue_button_ = nullptr;
+  // View containing the cancel button.
+  raw_ptr<views::View> cancel_button_ = nullptr;
+  // View containing the account chooser.
+  raw_ptr<views::View> account_chooser_ = nullptr;
+  // View containing the view to focus on in the verifying sheet.
+  raw_ptr<views::View> verifying_focus_view_ = nullptr;
+
   // Whether a spinner is present.
   bool has_spinner_{false};
 
diff --git a/chrome/browser/ui/views/webid/account_selection_modal_view_browsertest.cc b/chrome/browser/ui/views/webid/account_selection_modal_view_browsertest.cc
index a69dcf7..fb96e7b 100644
--- a/chrome/browser/ui/views/webid/account_selection_modal_view_browsertest.cc
+++ b/chrome/browser/ui/views/webid/account_selection_modal_view_browsertest.cc
@@ -540,7 +540,12 @@
                        const std::u16string expected_description,
                        const std::string& error_code,
                        const GURL& error_url) {
-    CreateAccountSelectionModal();
+    IdentityRequestAccountPtr account = CreateTestIdentityRequestAccount(
+        /*account_suffix=*/"account", idp_data_,
+        content::IdentityRequestAccount::LoginState::kSignUp);
+    CreateAndShowSingleAccountPicker(/*show_back_button=*/false, *account);
+    dialog_->ShowVerifyingSheet(account, kTitleSignIn);
+    account_selection_view_->UpdateDialogPosition();
     dialog_->ShowErrorDialog(
         kIdpETLDPlusOne, idp_data_->idp_metadata,
         content::IdentityCredentialTokenError(error_code, error_url));
diff --git a/chrome/browser/ui/webauthn/sheet_models.cc b/chrome/browser/ui/webauthn/sheet_models.cc
index 6eb0293..7897f8dd 100644
--- a/chrome/browser/ui/webauthn/sheet_models.cc
+++ b/chrome/browser/ui/webauthn/sheet_models.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/ui/webauthn/user_actions.h"
 #include "chrome/browser/ui/webauthn/webauthn_ui_helpers.h"
 #include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
+#include "chrome/browser/webauthn/webauthn_metrics_util.h"
 #include "chrome/grit/browser_resources.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/signin/public/identity_manager/account_info.h"
@@ -1376,6 +1377,9 @@
     : AuthenticatorSheetModelBase(dialog_model,
                                   OtherMechanismButtonVisibility::kHidden) {
   vector_illustrations_.emplace(kPasskeyErrorIcon, kPasskeyErrorDarkIcon);
+  if (dialog_model->in_onboarding_flow) {
+    RecordOnboardingEvent(webauthn::metrics::OnboardingEvents::kFailure);
+  }
   webauthn::user_actions::RecordGpmFailureShown();
 }
 
@@ -1669,6 +1673,14 @@
   dialog_model()->OnGPMPinEntered(pin_);
 }
 
+void AuthenticatorGpmPinSheetModelBase::OnCancel() {
+  if (dialog_model()->in_onboarding_flow) {
+    RecordOnboardingEvent(webauthn::metrics::OnboardingEvents::
+                              kAuthenticatorGpmPinSheetCancelled);
+  }
+  AuthenticatorSheetModelBase::OnCancel();
+}
+
 void AuthenticatorGpmPinSheetModelBase::OnForgotGPMPin() const {
   webauthn::user_actions::RecordGpmForgotPinClick();
   dialog_model()->OnForgotGPMPinPressed();
@@ -1955,6 +1967,22 @@
   dialog_model()->OnGPMCreatePasskey();
 }
 
+void AuthenticatorCreateGpmPasskeySheetModel::OnCancel() {
+  if (dialog_model()->in_onboarding_flow) {
+    RecordOnboardingEvent(
+        webauthn::metrics::OnboardingEvents::kCreateGpmPasskeySheetCancelled);
+  }
+  AuthenticatorSheetModelBase::OnCancel();
+}
+
+void AuthenticatorCreateGpmPasskeySheetModel::OnBack() {
+  if (dialog_model()->in_onboarding_flow) {
+    RecordOnboardingEvent(webauthn::metrics::OnboardingEvents::
+                              kCreateGpmPasskeySheetSaveAnotherWaySelected);
+  }
+  AuthenticatorSheetModelBase::OnBack();
+}
+
 // AuthenticatorGpmIncognitoCreateSheetModel ---------------------------------
 AuthenticatorGpmIncognitoCreateSheetModel::
     AuthenticatorGpmIncognitoCreateSheetModel(
diff --git a/chrome/browser/ui/webauthn/sheet_models.h b/chrome/browser/ui/webauthn/sheet_models.h
index 0446b15b..7603083 100644
--- a/chrome/browser/ui/webauthn/sheet_models.h
+++ b/chrome/browser/ui/webauthn/sheet_models.h
@@ -701,6 +701,7 @@
   bool IsForgotGPMPinButtonVisible() const override;
   bool IsGPMPinOptionsButtonVisible() const override;
   void OnAccept() override;
+  void OnCancel() override;
   void OnForgotGPMPin() const override;
   void OnGPMPinOptionChosen(bool is_arbitrary) const override;
 };
@@ -800,6 +801,9 @@
   bool IsAcceptButtonVisible() const override;
   std::u16string GetAcceptButtonLabel() const override;
   void OnAccept() override;
+  // "Save another way" button handler.
+  void OnBack() override;
+  void OnCancel() override;
 };
 
 // The sheet shown for warning a user about creating a Google Password Manager
diff --git a/chrome/browser/ui/webui/ash/settings/integration_tests/os_settings_password_setup_browsertest.cc b/chrome/browser/ui/webui/ash/settings/integration_tests/os_settings_password_setup_browsertest.cc
index 14c3514e..1ae5a8d4 100644
--- a/chrome/browser/ui/webui/ash/settings/integration_tests/os_settings_password_setup_browsertest.cc
+++ b/chrome/browser/ui/webui/ash/settings/integration_tests/os_settings_password_setup_browsertest.cc
@@ -52,6 +52,7 @@
   mojom::PasswordSettingsApiAsyncWaiter password_settings =
       GoToPasswordSettings(lock_screen_settings);
   password_settings.AssertCanRemovePassword(false);
+  password_settings.AssertCanSwitchToLocalPassword(true);
   password_settings.AssertCanOpenLocalPasswordDialog();
   password_settings.AssertSubmitButtonDisabledForInvalidPasswordInput();
   password_settings.AssertSubmitButtonEnabledForValidPasswordInput();
@@ -72,6 +73,7 @@
   mojom::PasswordSettingsApiAsyncWaiter password_settings =
       GoToPasswordSettings(lock_screen_settings);
   password_settings.AssertCanRemovePassword(false);
+  password_settings.AssertCanSwitchToLocalPassword(false);
 }
 
 class OSSettingsAuthFactorSetupTestWithManagedUser
diff --git a/chrome/browser/ui/webui/ash/settings/pages/people/people_section.cc b/chrome/browser/ui/webui/ash/settings/pages/people/people_section.cc
index 79f2453a..ac89f41 100644
--- a/chrome/browser/ui/webui/ash/settings/pages/people/people_section.cc
+++ b/chrome/browser/ui/webui/ash/settings/pages/people/people_section.cc
@@ -330,9 +330,6 @@
   html_source->AddBoolean(
       "lockScreenHideSensitiveNotificationsSupported",
       ash::features::IsLockScreenHideSensitiveNotificationsSupported());
-  html_source->AddBoolean("changePasswordFactorSetupEnabled",
-                          ash::features::IsChangePasswordFactorSetupEnabled());
-
   html_source->AddString(
       "lockScreenSwitchLocalPasswordDescription",
       l10n_util::GetStringFUTF16(
diff --git a/chrome/browser/ui/webui/chrome_urls/chrome_urls_handler.cc b/chrome/browser/ui/webui/chrome_urls/chrome_urls_handler.cc
index 55994e9f..b509a22e 100644
--- a/chrome/browser/ui/webui/chrome_urls/chrome_urls_handler.cc
+++ b/chrome/browser/ui/webui/chrome_urls/chrome_urls_handler.cc
@@ -104,13 +104,19 @@
     result->command_urls.push_back(GURL(url));
   }
 
-  // Note: |local_state| may be null in unit tests.
   PrefService* local_state = g_browser_process->local_state();
   result->internal_debugging_uis_enabled =
-      !!local_state &&
       local_state->FindPreference(prefs::kInternalOnlyUisEnabled) &&
       local_state->GetBoolean(prefs::kInternalOnlyUisEnabled);
   std::move(callback).Run(std::move(result));
 }
 
+void ChromeUrlsHandler::SetDebugPagesEnabled(
+    bool enabled,
+    SetDebugPagesEnabledCallback callback) {
+  PrefService* local_state = g_browser_process->local_state();
+  local_state->SetBoolean(prefs::kInternalOnlyUisEnabled, enabled);
+  std::move(callback).Run();
+}
+
 }  // namespace chrome_urls
diff --git a/chrome/browser/ui/webui/chrome_urls/chrome_urls_handler.h b/chrome/browser/ui/webui/chrome_urls/chrome_urls_handler.h
index 6be5098..daa92f2 100644
--- a/chrome/browser/ui/webui/chrome_urls/chrome_urls_handler.h
+++ b/chrome/browser/ui/webui/chrome_urls/chrome_urls_handler.h
@@ -32,7 +32,10 @@
  private:
   // chrome_urls::mojom::PageHandler
   void GetUrls(GetUrlsCallback callback) override;
+  void SetDebugPagesEnabled(bool enabled,
+                            SetDebugPagesEnabledCallback callback) override;
   FRIEND_TEST_ALL_PREFIXES(ChromeUrlsHandlerTest, GetUrls);
+  FRIEND_TEST_ALL_PREFIXES(ChromeUrlsHandlerTest, SetDebugPagesEnabled);
 
   // These are located at the end of the list of member variables to ensure the
   // WebUI page is disconnected before other members are destroyed.
diff --git a/chrome/browser/ui/webui/chrome_urls/chrome_urls_handler_unittest.cc b/chrome/browser/ui/webui/chrome_urls/chrome_urls_handler_unittest.cc
index 7968331..e88bd705 100644
--- a/chrome/browser/ui/webui/chrome_urls/chrome_urls_handler_unittest.cc
+++ b/chrome/browser/ui/webui/chrome_urls/chrome_urls_handler_unittest.cc
@@ -8,7 +8,10 @@
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/ui/webui/internal_webui_config.h"
 #include "chrome/common/chrome_features.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/common/webui_url_constants.h"
+#include "chrome/test/base/scoped_testing_local_state.h"
+#include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/chrome_urls_ui/mojom/chrome_urls.mojom.h"
 #include "content/public/browser/webui_config.h"
@@ -95,7 +98,9 @@
 
 class ChromeUrlsHandlerTest : public testing::Test {
  public:
-  ChromeUrlsHandlerTest() : profile_(std::make_unique<TestingProfile>()) {}
+  ChromeUrlsHandlerTest()
+      : local_state_(TestingBrowserProcess::GetGlobal()),
+        profile_(std::make_unique<TestingProfile>()) {}
 
   void SetUp() override {
     handler_ = std::make_unique<chrome_urls::ChromeUrlsHandler>(
@@ -108,6 +113,7 @@
  protected:
   base::test::ScopedFeatureList feature_list_{features::kInternalOnlyUisPref};
   content::BrowserTaskEnvironment task_environment_;
+  ScopedTestingLocalState local_state_;
   std::unique_ptr<TestingProfile> profile_;
   testing::NiceMock<MockPage> mock_page_;
   std::unique_ptr<chrome_urls::ChromeUrlsHandler> handler_;
@@ -211,4 +217,18 @@
   }
 }
 
+TEST_F(ChromeUrlsHandlerTest, SetDebugPagesEnabled) {
+  // Initialize the pref to false.
+  local_state_.Get()->SetUserPref(prefs::kInternalOnlyUisEnabled,
+                                  std::make_unique<base::Value>(false));
+  base::MockCallback<base::RepeatingClosure> callback;
+  EXPECT_CALL(callback, Run).Times(1);
+  handler_->SetDebugPagesEnabled(true, callback.Get());
+
+  // Pref value is true after SetDebugPagesEnabled() is called.
+  const base::Value* pref =
+      local_state_.Get()->GetUserPref(prefs::kInternalOnlyUisEnabled);
+  EXPECT_TRUE(!!pref && pref->GetBool());
+}
+
 }  // namespace chrome_urls
diff --git a/chrome/browser/ui/webui/cr_components/history_embeddings/history_embeddings_handler.cc b/chrome/browser/ui/webui/cr_components/history_embeddings/history_embeddings_handler.cc
index fa51fae..6197441 100644
--- a/chrome/browser/ui/webui/cr_components/history_embeddings/history_embeddings_handler.cc
+++ b/chrome/browser/ui/webui/cr_components/history_embeddings/history_embeddings_handler.cc
@@ -10,6 +10,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/feedback/show_feedback_page.h"
 #include "chrome/browser/history_embeddings/history_embeddings_service_factory.h"
+#include "chrome/browser/history_embeddings/history_embeddings_utils.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
@@ -119,7 +120,7 @@
   mojom_search_result->query = native_search_result.query;
 
   bool has_answer = false;
-  if (history_embeddings::IsHistoryEmbeddingsAnswersEnabled()) {
+  if (history_embeddings::IsHistoryEmbeddingsAnswersFeatureEnabled()) {
     mojom_search_result->answer_status = AnswererAnswerStatusToMojoAnswerStatus(
         native_search_result.answerer_result.status);
     if (!native_search_result.AnswerText().empty()) {
diff --git a/chrome/browser/ui/webui/glic/glic_page_handler.cc b/chrome/browser/ui/webui/glic/glic_page_handler.cc
index 4328c65e..9baa2820 100644
--- a/chrome/browser/ui/webui/glic/glic_page_handler.cc
+++ b/chrome/browser/ui/webui/glic/glic_page_handler.cc
@@ -8,7 +8,6 @@
 #include "chrome/browser/glic/glic_keyed_service.h"
 #include "chrome/browser/glic/glic_keyed_service_factory.h"
 #include "chrome/browser/glic/glic_window_controller.h"
-#include "chrome/browser/glic/glic_window_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/webui/glic/glic.mojom.h"
 #include "ui/gfx/geometry/mojom/geometry.mojom.h"
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index e0ee592..1465a6f 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/browser_process_platform_part.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/file_system_access/chrome_file_system_access_permission_context.h"
+#include "chrome/browser/history_embeddings/history_embeddings_utils.h"
 #include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/obsolete_system/obsolete_system.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
@@ -76,7 +77,6 @@
 #include "components/dom_distiller/core/dom_distiller_features.h"
 #include "components/google/core/common/google_util.h"
 #include "components/history/core/common/pref_names.h"
-#include "components/history_embeddings/history_embeddings_features.h"
 #include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
 #include "components/password_manager/core/browser/manage_passwords_referrer.h"
 #include "components/password_manager/core/common/password_manager_features.h"
@@ -1751,7 +1751,7 @@
       OptimizationGuideKeyedServiceFactory::GetForProfile(profile);
   html_source->AddBoolean(
       "historyEmbeddingsAnswersFeatureEnabled",
-      history_embeddings::IsHistoryEmbeddingsAnswersEnabled() &&
+      history_embeddings::IsHistoryEmbeddingsAnswersFeatureEnabled() &&
           optimization_guide_keyed_service &&
           optimization_guide_keyed_service
               ->ShouldModelExecutionBeAllowedForUser());
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_ui.cc b/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
index 7eaa5cb..0119353 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
+++ b/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
@@ -162,6 +162,8 @@
        IDS_DECLUTTER_INACTIVE_TITLE_NO_DEDUPE},
       {"declutterTimestamp", IDS_DECLUTTER_TIMESTAMP},
       {"declutterTitle", IDS_DECLUTTER_TITLE},
+      {"duplicateItemTitleMulti", IDS_DUPLICATE_ITEM_TITLE_MULTI},
+      {"duplicateItemTitleSingle", IDS_DUPLICATE_ITEM_TITLE_SINGLE},
       // Selector UI strings
       {"autoTabGroupsSelectorHeading", IDS_AUTO_TAB_GROUPS_SELECTOR_HEADING},
       {"autoTabGroupsSelectorSubheading",
diff --git a/chrome/browser/web_applications/commands/install_from_sync_command_browsertest.cc b/chrome/browser/web_applications/commands/install_from_sync_command_browsertest.cc
index 753e5a42..8db9595 100644
--- a/chrome/browser/web_applications/commands/install_from_sync_command_browsertest.cc
+++ b/chrome/browser/web_applications/commands/install_from_sync_command_browsertest.cc
@@ -127,14 +127,10 @@
   loop.Run();
   // Check first install.
   {
-    EXPECT_TRUE(provider->registrar_unsafe().IsInstallState(
-        id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-             proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-             proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
-    EXPECT_EQ(AreAppsLocallyInstalledBySync(),
-              provider->registrar_unsafe().IsInstallState(
-                  id, {proto::INSTALLED_WITHOUT_OS_INTEGRATION,
-                       proto::INSTALLED_WITH_OS_INTEGRATION}));
+    EXPECT_EQ(provider->registrar_unsafe().GetInstallState(id),
+              AreAppsLocallyInstalledBySync()
+                  ? proto::INSTALLED_WITH_OS_INTEGRATION
+                  : proto::SUGGESTED_FROM_ANOTHER_DEVICE);
 
     SkColor icon_color =
         IconManagerReadAppIconPixel(provider->icon_manager(), id, 96);
@@ -142,14 +138,10 @@
   }
   // Check second install.
   {
-    EXPECT_TRUE(provider->registrar_unsafe().IsInstallState(
-        other_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-                   proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-                   proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
-    EXPECT_EQ(AreAppsLocallyInstalledBySync(),
-              provider->registrar_unsafe().IsInstallState(
-                  other_id, {proto::INSTALLED_WITHOUT_OS_INTEGRATION,
-                             proto::INSTALLED_WITH_OS_INTEGRATION}));
+    EXPECT_EQ(provider->registrar_unsafe().GetInstallState(other_id),
+              AreAppsLocallyInstalledBySync()
+                  ? proto::INSTALLED_WITH_OS_INTEGRATION
+                  : proto::SUGGESTED_FROM_ANOTHER_DEVICE);
 
     SkColor icon_color =
         IconManagerReadAppIconPixel(provider->icon_manager(), other_id, 96);
@@ -210,10 +202,7 @@
   content::WebContentsDestroyedWatcher web_contents_destroyed_observer(
       web_contents);
   web_contents_destroyed_observer.Wait();
-  EXPECT_FALSE(provider->registrar_unsafe().IsInstallState(
-      id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-           proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-           proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_TRUE(provider->registrar_unsafe().IsNotInRegistrar(id));
 }
 
 }  // namespace
diff --git a/chrome/browser/web_applications/commands/install_from_sync_command_unittest.cc b/chrome/browser/web_applications/commands/install_from_sync_command_unittest.cc
index 0bb7ba0..5365413 100644
--- a/chrome/browser/web_applications/commands/install_from_sync_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/install_from_sync_command_unittest.cc
@@ -211,10 +211,10 @@
   EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
             result.install_code);
   EXPECT_EQ(result.installed_app_id, app_id);
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+            AreAppsLocallyInstalledBySync()
+                ? proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+                : proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE);
 
   // Check that the manifest info was installed.
   EXPECT_THAT(GetAppName(app_id), Eq(kManifestName));
@@ -248,10 +248,12 @@
   EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
             result.install_code);
   EXPECT_EQ(result.installed_app_id, app_id);
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+            AreAppsLocallyInstalledBySync()
+                ? proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+                : proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE
+
+  );
 
   // Check that the document & fallback info was installed.
   EXPECT_THAT(registrar().GetAppShortName(app_id), Eq(kFallbackTitle));
@@ -287,10 +289,12 @@
   EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
             result.install_code);
   EXPECT_EQ(result.installed_app_id, app_id);
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+            AreAppsLocallyInstalledBySync()
+                ? proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+                : proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE
+
+  );
 
   // Check that the manifest was used & document icons were used.
   EXPECT_THAT(GetAppName(app_id), Eq(kManifestName));
@@ -325,10 +329,12 @@
   EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
             result.install_code);
   EXPECT_EQ(result.installed_app_id, app_id);
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+            AreAppsLocallyInstalledBySync()
+                ? proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+                : proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE
+
+  );
 
   // Check that the fallback info was installed.
   EXPECT_THAT(registrar().GetAppShortName(app_id), Eq(kFallbackTitle));
@@ -363,10 +369,12 @@
   EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
             result.install_code);
   EXPECT_EQ(result.installed_app_id, app_id);
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+            AreAppsLocallyInstalledBySync()
+                ? proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+                : proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE
+
+  );
 
   // Check that the fallback info was installed.
   EXPECT_THAT(registrar().GetAppShortName(app_id), Eq(kFallbackTitle));
@@ -407,10 +415,12 @@
   EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
             result.install_code);
   EXPECT_EQ(result.installed_app_id, app_id);
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+            AreAppsLocallyInstalledBySync()
+                ? proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+                : proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE
+
+  );
 
   // Check that the fallback info was installed.
   EXPECT_THAT(registrar().GetAppShortName(app_id), Eq(kFallbackTitle));
@@ -492,14 +502,18 @@
   content::WebContentsDestroyedWatcher web_contents_obserser(web_contents);
   web_contents_obserser.Wait();
   EXPECT_FALSE(command_manager().web_contents_for_testing());
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id1, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-                proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-                proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id2, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-                proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-                proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id1),
+            AreAppsLocallyInstalledBySync()
+                ? proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+                : proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE
+
+  );
+  EXPECT_EQ(registrar().GetInstallState(app_id2),
+            AreAppsLocallyInstalledBySync()
+                ? proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+                : proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE
+
+  );
   std::vector<Event> expected;
   if (AreAppsLocallyInstalledBySync()) {
     expected = {
@@ -550,10 +564,7 @@
   ASSERT_TRUE(future.Wait());
   EXPECT_EQ(future.Get<webapps::InstallResultCode>(),
             webapps::InstallResultCode::kCancelledOnWebAppProviderShuttingDown);
-  EXPECT_FALSE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_TRUE(registrar().IsNotInRegistrar(app_id));
 }
 
 }  // namespace
diff --git a/chrome/browser/web_applications/commands/launch_web_app_command_browsertest.cc b/chrome/browser/web_applications/commands/launch_web_app_command_browsertest.cc
index d0b026c..bc14bd1 100644
--- a/chrome/browser/web_applications/commands/launch_web_app_command_browsertest.cc
+++ b/chrome/browser/web_applications/commands/launch_web_app_command_browsertest.cc
@@ -241,9 +241,8 @@
     ASSERT_FALSE(first_run_service);
   }
 
-  ASSERT_TRUE(GetProvider().registrar_unsafe().IsInstallState(
-      app_id, {proto::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::INSTALLED_WITH_OS_INTEGRATION}));
+  ASSERT_EQ(GetProvider().registrar_unsafe().GetInstallState(app_id),
+            proto::INSTALLED_WITH_OS_INTEGRATION);
 
   Browser* browser = LaunchWebAppBrowser(app_id);
   ASSERT_EQ(browser == nullptr, GetParam());
@@ -266,9 +265,8 @@
     ASSERT_FALSE(first_run_service);
   }
 
-  ASSERT_TRUE(GetProvider().registrar_unsafe().IsInstallState(
-      app_id, {proto::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::INSTALLED_WITH_OS_INTEGRATION}));
+  ASSERT_EQ(GetProvider().registrar_unsafe().GetInstallState(
+      app_id), proto::INSTALLED_WITH_OS_INTEGRATION));
 
   Browser* browser = LaunchBrowserForWebAppInTab(app_id);
   ASSERT_TRUE(browser);
@@ -447,8 +445,6 @@
                   .registrar_unsafe()
                   .GetAppCurrentOsIntegrationState(app_id)
                   ->has_shortcut());
-  // TODO(crbug.com/340952100): Evaluate call sites of IsInstallState for
-  // correctness.
   EXPECT_EQ(proto::InstallState::INSTALLED_WITH_OS_INTEGRATION,
             provider().registrar_unsafe().GetInstallState(app_id));
 }
diff --git a/chrome/browser/web_applications/externally_managed_app_manager_browsertest.cc b/chrome/browser/web_applications/externally_managed_app_manager_browsertest.cc
index 90a257d4a..e6a082b 100644
--- a/chrome/browser/web_applications/externally_managed_app_manager_browsertest.cc
+++ b/chrome/browser/web_applications/externally_managed_app_manager_browsertest.cc
@@ -1068,11 +1068,7 @@
 
   // Wait for the placeholder removal task to be done.
   ASSERT_TRUE(base::test::RunUntil([&]() -> bool {
-    return !registrar().IsInstallState(
-        placeholder_app_id,
-        {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-         proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-         proto::InstallState::INSTALLED_WITH_OS_INTEGRATION});
+    return registrar().IsNotInRegistrar(placeholder_app_id);
   }));
 
   // Check that the new app is launched.
@@ -1082,10 +1078,8 @@
   WaitUntilDisplayNotificationCount(/*display_count=*/0u);
 
   EXPECT_NE(final_app_id, placeholder_app_id);
-  EXPECT_TRUE(registrar().IsInstallState(
-      final_app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-                     proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-                     proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(final_app_id),
+            proto::InstallState::INSTALLED_WITH_OS_INTEGRATION);
   EXPECT_FALSE(
       registrar().IsPlaceholderApp(final_app_id, WebAppManagement::kPolicy));
   EXPECT_EQ(0, registrar().CountUserInstalledApps());
diff --git a/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc b/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc
index b961475..57c6e81 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc
+++ b/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc
@@ -313,10 +313,7 @@
   GURL start_url = embedded_test_server()->GetURL("/web_apps/basic.html");
   webapps::AppId app_id =
       GenerateAppId(/*manifest_id=*/std::nullopt, start_url);
-  EXPECT_FALSE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_TRUE(registrar().IsNotInRegistrar(app_id));
 
   constexpr char kAppConfigTemplate[] =
       R"({
@@ -330,10 +327,13 @@
   EXPECT_EQ(SyncPreinstalledAppConfig(start_url, app_config),
             webapps::InstallResultCode::kSuccessNewInstall);
 
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+#if BUILDFLAG(IS_CHROMEOS)
+            proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+#else
+            proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION
+#endif
+  );
   EXPECT_EQ(registrar().GetAppStartUrl(app_id).spec(), start_url);
 
   GURL launch_url =
@@ -361,10 +361,7 @@
       "/web_apps/query_params_in_start_url.html?query_params=in&start=url");
   webapps::AppId app_id =
       GenerateAppId(/*manifest_id=*/std::nullopt, start_url);
-  EXPECT_FALSE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_TRUE(registrar().IsNotInRegistrar(app_id));
 
   constexpr char kAppConfigTemplate[] =
       R"({
@@ -378,10 +375,13 @@
   EXPECT_EQ(SyncPreinstalledAppConfig(install_url, app_config),
             webapps::InstallResultCode::kSuccessNewInstall);
 
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+#if BUILDFLAG(IS_CHROMEOS)
+            proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+#else
+            proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION
+#endif
+  );
   EXPECT_EQ(registrar().GetAppStartUrl(app_id).spec(), start_url);
 
   // We should not duplicate the query param if start_url already has it.
@@ -407,10 +407,7 @@
       "/web_apps/basic.html?more=than&one=query&param");
   webapps::AppId app_id =
       GenerateAppId(/*manifest_id=*/std::nullopt, start_url);
-  EXPECT_FALSE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_TRUE(registrar().IsNotInRegistrar(app_id));
 
   constexpr char kAppConfigTemplate[] =
       R"({
@@ -424,10 +421,13 @@
   EXPECT_EQ(SyncPreinstalledAppConfig(start_url, app_config),
             webapps::InstallResultCode::kSuccessNewInstall);
 
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+#if BUILDFLAG(IS_CHROMEOS)
+            proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+#else
+            proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION
+#endif
+  );
   EXPECT_EQ(registrar().GetAppStartUrl(app_id).spec(), start_url);
   EXPECT_EQ(registrar().GetAppLaunchUrl(app_id), launch_url);
 
@@ -452,10 +452,7 @@
       "/web_apps/query_params_in_start_url.html?query_params=in&start=url");
   webapps::AppId app_id =
       GenerateAppId(/*manifest_id=*/std::nullopt, start_url);
-  EXPECT_FALSE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_TRUE(registrar().IsNotInRegistrar(app_id));
 
   constexpr char kAppConfigTemplate[] =
       R"({
@@ -469,10 +466,13 @@
   EXPECT_EQ(SyncPreinstalledAppConfig(install_url, app_config),
             webapps::InstallResultCode::kSuccessNewInstall);
 
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+#if BUILDFLAG(IS_CHROMEOS)
+            proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+#else
+            proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION
+#endif
+  );
   EXPECT_EQ(registrar().GetAppStartUrl(app_id).spec(), start_url);
 
   GURL launch_url = embedded_test_server()->GetURL(
@@ -617,10 +617,13 @@
 
   webapps::AppId app_id = GenerateAppId(/*manifest_id=*/std::nullopt,
                                         GURL{kSimpleManifestStartUrl});
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+#if BUILDFLAG(IS_CHROMEOS)
+            proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+#else
+            proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION
+#endif
+  );
 }
 
 IN_PROC_BROWSER_TEST_F(PreinstalledWebAppManagerBrowserTest,
@@ -640,10 +643,13 @@
 
   webapps::AppId app_id = GenerateAppId(/*manifest_id=*/std::nullopt,
                                         GURL{kSimpleManifestStartUrl});
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+#if BUILDFLAG(IS_CHROMEOS)
+            proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+#else
+            proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION
+#endif
+  );
 }
 
 IN_PROC_BROWSER_TEST_F(PreinstalledWebAppManagerBrowserTest,
@@ -662,10 +668,7 @@
 
   webapps::AppId app_id = GenerateAppId(/*manifest_id=*/std::nullopt,
                                         GURL{kNoManifestTestPageStartUrl});
-  EXPECT_FALSE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_TRUE(registrar().IsNotInRegistrar(app_id));
 }
 
 IN_PROC_BROWSER_TEST_F(PreinstalledWebAppManagerBrowserTest,
@@ -685,10 +688,7 @@
 
   webapps::AppId app_id = GenerateAppId(/*manifest_id=*/std::nullopt,
                                         GURL{kNoManifestTestPageStartUrl});
-  EXPECT_FALSE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_TRUE(registrar().IsNotInRegistrar(app_id));
 }
 
 const char kFeatureNameOrInstalledConfig[] = R"({
@@ -717,10 +717,13 @@
 
   webapps::AppId app_id =
       GenerateAppId(/*manifest_id=*/std::nullopt, GetAppUrl());
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+#if BUILDFLAG(IS_CHROMEOS)
+            proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+#else
+            proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION
+#endif
+  );
 }
 
 // When the "feature_name_or_installed" feature is disabled, the app should not
@@ -738,10 +741,7 @@
 
   webapps::AppId app_id =
       GenerateAppId(/*manifest_id=*/std::nullopt, GetAppUrl());
-  EXPECT_FALSE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_TRUE(registrar().IsNotInRegistrar(app_id));
 }
 
 // When the "feature_name_or_installed" feature is disabled, any existing
@@ -763,20 +763,26 @@
     EXPECT_EQ(SyncPreinstalledAppConfig(GetAppUrl(), app_config),
               webapps::InstallResultCode::kSuccessNewInstall);
 
-    EXPECT_TRUE(registrar().IsInstallState(
-        app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-                 proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-                 proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+    EXPECT_EQ(registrar().GetInstallState(app_id),
+#if BUILDFLAG(IS_CHROMEOS)
+              proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+#else
+              proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION
+#endif
+    );
   }
 
   {
     EXPECT_EQ(SyncPreinstalledAppConfig(GetAppUrl(), app_config),
               webapps::InstallResultCode::kSuccessAlreadyInstalled);
 
-    EXPECT_TRUE(registrar().IsInstallState(
-        app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-                 proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-                 proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+    EXPECT_EQ(registrar().GetInstallState(app_id),
+#if BUILDFLAG(IS_CHROMEOS)
+              proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+#else
+              proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION
+#endif
+    );
   }
 }
 
@@ -801,10 +807,13 @@
     base::HistogramTester tester;
     EXPECT_EQ(SyncPreinstalledAppConfig(GetAppUrl(), config),
               webapps::InstallResultCode::kSuccessNewInstall);
-    EXPECT_TRUE(registrar().IsInstallState(
-        app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-                 proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-                 proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+    EXPECT_EQ(registrar().GetInstallState(app_id),
+#if BUILDFLAG(IS_CHROMEOS)
+              proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+#else
+              proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION
+#endif
+    );
     tester.ExpectUniqueSample("WebApp.Preinstalled.DisabledReason",
                               /*kNotDisabled*/ 0, 1);
   }
@@ -824,10 +833,13 @@
     base::HistogramTester tester;
     EXPECT_EQ(SyncPreinstalledAppConfig(GetAppUrl(), config),
               webapps::InstallResultCode::kSuccessAlreadyInstalled);
-    EXPECT_TRUE(registrar().IsInstallState(
-        app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-                 proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-                 proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+    EXPECT_EQ(registrar().GetInstallState(app_id),
+#if BUILDFLAG(IS_CHROMEOS)
+              proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+#else
+              proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION
+#endif
+    );
     tester.ExpectUniqueSample("WebApp.Preinstalled.DisabledReason",
                               /*kIgnorePreviouslyUninstalledByUser*/ 17, 1);
   }
@@ -838,20 +850,14 @@
     provider().scheduler().RemoveUserUninstallableManagements(
         app_id, webapps::WebappUninstallSource::kAppMenu, future.GetCallback());
     ASSERT_EQ(future.Get(), webapps::UninstallResultCode::kAppRemoved);
-    ASSERT_FALSE(registrar().IsInstallState(
-        app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-                 proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-                 proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+    ASSERT_TRUE(registrar().IsNotInRegistrar(app_id));
   }
 
   // Check web app does not get installed by PWAM sync.
   {
     base::HistogramTester tester;
     EXPECT_EQ(SyncPreinstalledAppConfig(GetAppUrl(), config), std::nullopt);
-    EXPECT_FALSE(registrar().IsInstallState(
-        app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-                 proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-                 proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+    EXPECT_TRUE(registrar().IsNotInRegistrar(app_id));
     tester.ExpectUniqueSample("WebApp.Preinstalled.DisabledReason",
                               /*kIgnorePreviouslyUninstalledByUser*/ 17, 1);
   }
@@ -878,10 +884,7 @@
       {GetAppUrl().spec()}, nullptr);
   webapps::AppId app_id =
       GenerateAppId(/*manifest_id=*/std::nullopt, GetAppUrl());
-  ASSERT_FALSE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  ASSERT_TRUE(registrar().IsNotInRegistrar(app_id));
   UserUninstalledPreinstalledWebAppPrefs prefs(profile()->GetPrefs());
   prefs.Add(app_id, {GetAppUrl()});
 
@@ -894,10 +897,13 @@
   const auto& ignore_configs = manager().debug_info()->ignore_configs;
   EXPECT_EQ(SyncPreinstalledAppConfig(GetAppUrl(), manifest),
             webapps::InstallResultCode::kSuccessNewInstall);
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+#if BUILDFLAG(IS_CHROMEOS)
+            proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+#else
+            proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION
+#endif
+  );
   EXPECT_EQ(ignore_configs.size(), 0u);
 }
 
@@ -949,10 +955,7 @@
 
   webapps::AppId app_id =
       GenerateAppId(/*manifest_id=*/std::nullopt, GURL(kAppStartUrl));
-  EXPECT_FALSE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_TRUE(registrar().IsNotInRegistrar(app_id));
 
   constexpr char kAppConfigTemplate[] =
       R"({
@@ -974,10 +977,8 @@
   EXPECT_EQ(SyncPreinstalledAppConfig(GURL(kAppInstallUrl), app_config),
             webapps::InstallResultCode::kSuccessOfflineFallbackInstall);
 
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+            proto::InstallState::INSTALLED_WITH_OS_INTEGRATION);
   EXPECT_EQ(registrar().GetAppShortName(app_id), kAppName);
   EXPECT_EQ(registrar().GetAppStartUrl(app_id).spec(), kAppStartUrl);
   EXPECT_EQ(registrar().GetAppScope(app_id).spec(), kAppScope);
@@ -1007,10 +1008,7 @@
 
   webapps::AppId offline_app_id =
       GenerateAppId(/*manifest_id=*/std::nullopt, offline_start_url);
-  EXPECT_FALSE(registrar().IsInstallState(
-      offline_app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-                       proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-                       proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_TRUE(registrar().IsNotInRegistrar(offline_app_id));
 
   constexpr char kAppConfigTemplate[] =
       R"({
@@ -1032,18 +1030,13 @@
   EXPECT_EQ(SyncPreinstalledAppConfig(install_url, app_config),
             webapps::InstallResultCode::kSuccessNewInstall);
 
-  EXPECT_FALSE(registrar().IsInstallState(
-      offline_app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-                       proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-                       proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_TRUE(registrar().IsNotInRegistrar(offline_app_id));
 
   // basic.html's manifest start_url is basic.html.
   webapps::AppId app_id =
       GenerateAppId(/*manifest_id=*/std::nullopt, install_url);
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+            proto::InstallState::INSTALLED_WITH_OS_INTEGRATION);
   EXPECT_EQ(registrar().GetAppShortName(app_id), "Basic web app");
   EXPECT_EQ(registrar().GetAppStartUrl(app_id).spec(), install_url);
   EXPECT_EQ(registrar().GetAppScope(app_id).spec(), scope);
@@ -1062,10 +1055,7 @@
 
   webapps::AppId app_id =
       GenerateAppId(/*manifest_id=*/std::nullopt, GURL(kAppStartUrl));
-  EXPECT_FALSE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_TRUE(registrar().IsNotInRegistrar(app_id));
 
   constexpr char kAppConfigTemplate[] =
       R"({
@@ -1088,10 +1078,8 @@
   EXPECT_EQ(SyncPreinstalledAppConfig(GURL(kAppInstallUrl), app_config),
             webapps::InstallResultCode::kSuccessOfflineOnlyInstall);
 
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+            proto::InstallState::INSTALLED_WITH_OS_INTEGRATION);
   EXPECT_EQ(registrar().GetAppShortName(app_id), kAppName);
   EXPECT_EQ(registrar().GetAppStartUrl(app_id).spec(), kAppStartUrl);
   EXPECT_EQ(registrar().GetAppScope(app_id).spec(), kAppScope);
@@ -1121,10 +1109,7 @@
 
   webapps::AppId app_id =
       GenerateAppId(/*manifest_id=*/std::nullopt, start_url);
-  EXPECT_FALSE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_TRUE(registrar().IsNotInRegistrar(app_id));
 
   constexpr char kAppConfigTemplate[] =
       R"({
@@ -1147,10 +1132,8 @@
   EXPECT_EQ(SyncPreinstalledAppConfig(install_url, app_config),
             webapps::InstallResultCode::kSuccessOfflineOnlyInstall);
 
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+            proto::InstallState::INSTALLED_WITH_OS_INTEGRATION);
   EXPECT_EQ(registrar().GetAppShortName(app_id), kAppName);
   EXPECT_EQ(registrar().GetAppStartUrl(app_id).spec(), start_url);
   EXPECT_EQ(registrar().GetAppScope(app_id).spec(), scope);
@@ -1307,10 +1290,7 @@
       "stylus support.";
 
   EXPECT_EQ(SyncPreinstalledAppConfig(GetAppUrl(), manifest), std::nullopt);
-  EXPECT_FALSE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_TRUE(registrar().IsNotInRegistrar(app_id));
   EXPECT_EQ(ignore_configs.size(), 1u);
   EXPECT_EQ(ignore_configs.back().second, GetAppUrl().spec() + kErrorMessage);
 }
@@ -1346,10 +1326,8 @@
 
   EXPECT_EQ(SyncPreinstalledAppConfig(GetAppUrl(), manifest),
             webapps::InstallResultCode::kSuccessNewInstall);
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+            proto::InstallState::INSTALLED_WITH_OS_INTEGRATION);
 }
 
 // Verify that stylus detection works even if DeviceDataManager is slow to
@@ -1456,15 +1434,9 @@
                            apps::UninstallSource::kUnknown);
 
   // Default app should be removed from local app list but remain in sync list.
-  EXPECT_FALSE(registrar().IsInstallState(
-      preinstalled_app_id,
-      {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-       proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-       proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
-  EXPECT_TRUE(registrar().IsInstallState(
-      user_app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-                    proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-                    proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_TRUE(registrar().IsNotInRegistrar(preinstalled_app_id));
+  EXPECT_EQ(registrar().GetInstallState(user_app_id),
+            proto::InstallState::INSTALLED_WITH_OS_INTEGRATION);
   EXPECT_FALSE(app_list_test_api.HasApp(preinstalled_app_id));
   EXPECT_TRUE(app_list_test_api.HasApp(user_app_id));
   EXPECT_EQ(
@@ -1648,10 +1620,13 @@
   // Install the app for the first time.
   EXPECT_EQ(SyncPreinstalledAppConfig(GetAppUrl(), manifest),
             webapps::InstallResultCode::kSuccessNewInstall);
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+#if BUILDFLAG(IS_CHROMEOS)
+            proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+#else
+            proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION
+#endif
+  );
 
   // Verify that the app is the preferred app if requested in the manifest.
   WaitForSupportedLinksPreference(app_id, IsPreferredAppForSupportedLinks());
@@ -1662,10 +1637,13 @@
   // Reinstall the app.
   EXPECT_EQ(SyncPreinstalledAppConfig(GetAppUrl(), manifest),
             webapps::InstallResultCode::kSuccessAlreadyInstalled);
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+#if BUILDFLAG(IS_CHROMEOS)
+            proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+#else
+            proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION
+#endif
+  );
 
   // Verify that the app is *not* the preferred app after re-installation as the
   // user may have already updated their preference.
@@ -1778,10 +1756,13 @@
   // Install the app for the first time.
   EXPECT_EQ(SyncPreinstalledAppConfig(GetAppUrl(), manifest),
             webapps::InstallResultCode::kSuccessNewInstall);
-  EXPECT_TRUE(registrar().IsInstallState(
-      app_id, {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-               proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION,
-               proto::InstallState::INSTALLED_WITH_OS_INTEGRATION}));
+  EXPECT_EQ(registrar().GetInstallState(app_id),
+#if BUILDFLAG(IS_CHROMEOS)
+            proto::InstallState::INSTALLED_WITH_OS_INTEGRATION
+#else
+            proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION
+#endif
+  );
   EXPECT_EQ(ShouldCaptureLinks(), registrar().CapturesLinksInScope(app_id));
 }
 
diff --git a/chrome/browser/web_applications/web_app_registrar_unittest.cc b/chrome/browser/web_applications/web_app_registrar_unittest.cc
index 0c030ba..733785e 100644
--- a/chrome/browser/web_applications/web_app_registrar_unittest.cc
+++ b/chrome/browser/web_applications/web_app_registrar_unittest.cc
@@ -223,11 +223,7 @@
   EXPECT_TRUE(registrar().is_empty());
   EXPECT_TRUE(registrar().IsNotInRegistrar(webapps::AppId()));
   EXPECT_EQ(std::nullopt, registrar().GetInstallState(webapps::AppId()));
-  EXPECT_FALSE(registrar().IsInstallState(
-      webapps::AppId(),
-      {proto::InstallState::SUGGESTED_FROM_ANOTHER_DEVICE,
-       proto::InstallState::INSTALLED_WITH_OS_INTEGRATION,
-       proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION}));
+  EXPECT_TRUE(registrar().IsNotInRegistrar(webapps::AppId()));
   EXPECT_EQ(nullptr, registrar().GetAppById(webapps::AppId()));
   EXPECT_EQ(std::string(), registrar().GetAppShortName(webapps::AppId()));
   EXPECT_EQ(GURL(), registrar().GetAppStartUrl(webapps::AppId()));
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.h b/chrome/browser/webauthn/authenticator_request_dialog_model.h
index eb33bf3..c863cf88 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model.h
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model.h
@@ -453,6 +453,12 @@
   bool show_security_key_on_qr_sheet = false;
   bool is_off_the_record = false;
 
+  // Tracks whether the model is in the GPM onboarding state.
+  // This value is set/reset only in GPMEnclaveController::OnGPMSelected and
+  // read only to record metrics (WebAuthentication.OnboardingEvents) during the
+  // onboarding flow.
+  bool in_onboarding_flow = false;
+
   std::optional<int> max_bio_samples;
   std::optional<int> bio_samples_remaining;
   uint32_t min_pin_length = device::kMinPinLength;
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
index 282eaab..51bdbed5 100644
--- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
+++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
@@ -51,6 +51,7 @@
 #include "chrome/browser/webauthn/enclave_manager.h"
 #include "chrome/browser/webauthn/gpm_enclave_controller.h"
 #include "chrome/browser/webauthn/passkey_model_factory.h"
+#include "chrome/browser/webauthn/webauthn_metrics_util.h"
 #include "chrome/browser/webauthn/webauthn_pref_names.h"
 #include "chrome/common/chrome_version.h"
 #include "chrome/common/pref_names.h"
@@ -507,6 +508,9 @@
   }
 #endif  // BUILDFLAG(IS_MAC)
   if (authenticator_type == device::AuthenticatorType::kEnclave) {
+    if (dialog_model_->in_onboarding_flow) {
+      RecordOnboardingEvent(webauthn::metrics::OnboardingEvents::kSucceeded);
+    }
     webauthn::user_actions::RecordGpmSuccess();
   }
 }
diff --git a/chrome/browser/webauthn/gpm_enclave_controller.cc b/chrome/browser/webauthn/gpm_enclave_controller.cc
index b3ba7a9..f3b5860 100644
--- a/chrome/browser/webauthn/gpm_enclave_controller.cc
+++ b/chrome/browser/webauthn/gpm_enclave_controller.cc
@@ -54,6 +54,7 @@
 #include "chrome/browser/webauthn/gpm_user_verification_policy.h"
 #include "chrome/browser/webauthn/passkey_model_factory.h"
 #include "chrome/browser/webauthn/proto/enclave_local_state.pb.h"
+#include "chrome/browser/webauthn/webauthn_metrics_util.h"
 #include "chrome/browser/webauthn/webauthn_pref_names.h"
 #include "components/device_event_log/device_event_log.h"
 #include "components/prefs/pref_service.h"
@@ -892,6 +893,9 @@
 }
 
 void GPMEnclaveController::OnGPMSelected() {
+  // Reset after each GPM selection to ensure correct metric emission.
+  model_->in_onboarding_flow = false;
+
   if (model_->is_off_the_record && !off_the_record_confirmed_) {
     model_->SetStep(Step::kGPMConfirmOffTheRecordCreate);
     return;
@@ -899,6 +903,10 @@
 
   switch (account_state_) {
     case AccountState::kEmpty:
+      // Set to true to indicate that the user has entered the GPM onboarding
+      // flow. This enables emission of onboarding-specific metrics.
+      model_->in_onboarding_flow = true;
+      RecordOnboardingEvent(webauthn::metrics::OnboardingEvents::kStarted);
       model_->SetStep(Step::kGPMCreatePasskey);
       break;
 
diff --git a/chrome/browser/webauthn/webauthn_metrics_util.cc b/chrome/browser/webauthn/webauthn_metrics_util.cc
index 55d149e..dcbb90a99 100644
--- a/chrome/browser/webauthn/webauthn_metrics_util.cc
+++ b/chrome/browser/webauthn/webauthn_metrics_util.cc
@@ -18,3 +18,7 @@
   base::UmaHistogramExactLinear("WebAuthentication.ConditionalUiPasskeyCount",
                                 passkey_count, kPasskeyCountMax);
 }
+
+void RecordOnboardingEvent(webauthn::metrics::OnboardingEvents event) {
+  base::UmaHistogramEnumeration("WebAuthentication.OnboardingEvents", event);
+}
diff --git a/chrome/browser/webauthn/webauthn_metrics_util.h b/chrome/browser/webauthn/webauthn_metrics_util.h
index f3ac613..be99d9a6 100644
--- a/chrome/browser/webauthn/webauthn_metrics_util.h
+++ b/chrome/browser/webauthn/webauthn_metrics_util.h
@@ -5,6 +5,23 @@
 #ifndef CHROME_BROWSER_WEBAUTHN_WEBAUTHN_METRICS_UTIL_H_
 #define CHROME_BROWSER_WEBAUTHN_WEBAUTHN_METRICS_UTIL_H_
 
+namespace webauthn::metrics {
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class OnboardingEvents {
+  // LINT.IfChange
+  kStarted = 0,
+  kSucceeded = 1,
+  kCreateGpmPasskeySheetCancelled = 2,
+  kCreateGpmPasskeySheetSaveAnotherWaySelected = 3,
+  kAuthenticatorGpmPinSheetCancelled = 4,
+  kFailure = 5,
+  kMaxValue = kFailure,
+  // LINT.ThenChange(//tools/metrics/histograms/metadata/webauthn/enums.xml)
+};
+}  // namespace webauthn::metrics
+
 void ReportConditionalUiPasskeyCount(int passkey_count);
+void RecordOnboardingEvent(webauthn::metrics::OnboardingEvents event);
 
 #endif  // CHROME_BROWSER_WEBAUTHN_WEBAUTHN_METRICS_UTIL_H_
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt
index 0f5eb0e..a875f3c 100644
--- a/chrome/build/android-arm32.pgo.txt
+++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@
-chrome-android32-main-1733723928-0f1f5341431d6e83f62b6c0774b2583bc1c7294b-74352ad82725a2d6fb47c495e87999fa58c92fd1.profdata
+chrome-android32-main-1733767079-ed63c072f29731992bce06cff737692ed97385b5-106ceb1dbb65b494b52551528e96d9ece104b539.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index 42c884c..c2bffcc 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1733735873-8775daf1a6850add7765c548b0314a10eec5d125-676d0798b74a7b1337894304e0d109f546eca2de.profdata
+chrome-android64-main-1733758660-6bd047258bdfd29188813790761e3500274e6cc4-245e27183c48c7b124c3bc1193d0d5dc7e63130d.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 7d02a54a..1c5a35f 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1733723928-2634c7c298f3ba5180716ea9712ffaebbf812062-74352ad82725a2d6fb47c495e87999fa58c92fd1.profdata
+chrome-linux-main-1733767079-752e3b1cb989f1f4dac2e4d2cdc0051a81a98ac8-106ceb1dbb65b494b52551528e96d9ece104b539.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index f926b8c6..8796b32 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1733320636-afa2760f4d14e1493ec996ddcd3198acb410c201-108e9dad5849ba794cbe017e3e0c948ede0f957c.profdata
+chrome-mac-arm-main-1733759988-73f341c23a89b1dd22214a1b9644b48947fbc6a2-aaefa3855137630b072cd2051f074efb0ebccd91.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 8b6915a..a1b3144 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1733678699-f22cef7d7cab6351d2e94e9c19ba885edca8304b-3fae4a6b3b6af604fb32b4feaff8140241539905.profdata
+chrome-mac-main-1733745579-44062b63f629613412e19880dc974a30bc76d6d0-edc5771bf97c2fc8dafde8f6a50f1e45718ca406.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt
index e1fc247..70625867 100644
--- a/chrome/build/win-arm64.pgo.txt
+++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@
-chrome-win-arm64-main-1733700963-b9873b1fe424e91147e99b1a775cfba3fb170a75-dbd627c281626780e25f6d17321d3805b28f18dc.profdata
+chrome-win-arm64-main-1733745579-33be28ee17cb0ac5389fefc9c581f1968ec63f23-edc5771bf97c2fc8dafde8f6a50f1e45718ca406.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index e27a341..f40a0b1b 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1733713049-1920a4d524e661147d31be05731d0388c53cb784-7b32ccf3209f02fe570b28e65f890c89a6c7a2f7.profdata
+chrome-win32-main-1733756395-e4c778782a9b1052b6d4449ac271d0c10391f18e-ab9e8b4788f6c05494f8c5b1ced0918acf62dda1.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index b519e5f..3572395 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1733713049-8a8a48e893a61149f2a07b8bd38bc33208409cb7-7b32ccf3209f02fe570b28e65f890c89a6c7a2f7.profdata
+chrome-win64-main-1733745579-183d580d7d1d9c1a0995c9bfb4ea63eede5a8fb2-edc5771bf97c2fc8dafde8f6a50f1e45718ca406.profdata
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 9f2a4cd..51a9e15 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -10,6 +10,7 @@
 #include "build/branding_buildflags.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
+#include "chrome/common/buildflags.h"
 #include "chrome/common/pref_font_webkit_names.h"
 #include "components/compose/buildflags.h"
 #include "components/offline_pages/buildflags/buildflags.h"
@@ -3241,9 +3242,18 @@
 
 inline constexpr char kInternalOnlyUisEnabled[] = "internal_only_uis_enabled";
 
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
+#if BUILDFLAG(ENABLE_GLIC)
 inline constexpr char kGlicLauncherEnabled[] = "glic.launcher_enabled";
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
+// Boolean pref that enables or disables microphone access for Glic.
+inline constexpr char kGlicMicrophoneEnabled[] = "glic.microphone_enabled";
+// Boolean pref that enables or disables geolocation access for Glic.
+inline constexpr char kGlicGeolocationEnabled[] = "glic.geolocation_enabled";
+// Boolean pref that enables or disables tab context for Glic.
+inline constexpr char kGlicTabContextEnabled[] = "glic.tab_context_enabled";
+// Dictionary pref that keeps track of the registered hotkey for Glic.
+inline constexpr char kGlicLauncherGlobalHotkey[] =
+    "glic.launcher_global_hotkey";
+#endif  // BUILDFLAG(ENABLE_GLIC)
 
 // *************** SERVICE PREFS ***************
 // These are attached to the service process.
diff --git a/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc b/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc
index 6b1882e..4fd416f 100644
--- a/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc
+++ b/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc
@@ -13,9 +13,9 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/path_service.h"
 #include "base/ranges/algorithm.h"
-#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/test_discardable_memory_allocator.h"
+#include "base/test/test_future.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/renderer/chrome_content_renderer_client.h"
 #include "chrome/test/base/chrome_render_view_test.h"
@@ -215,23 +215,15 @@
       scoped_refptr<const base::RefCountedString16> page_text) {
     feature_map_.Clear();
 
-    classifier_->BeginClassification(
-        page_text,
-        base::BindOnce(&PhishingClassifierTest::ClassificationFinished,
-                       base::Unretained(this)));
-    run_loop_.Run();
-  }
-
-  // Completion callback for classification.
-  void ClassificationFinished(
-      const ClientPhishingRequest& verdict,
-      PhishingClassifier::Result phishing_classifier_result) {
-    verdict_ = verdict;
-    for (int i = 0; i < verdict.feature_map_size(); ++i) {
-      feature_map_.AddRealFeature(verdict.feature_map(i).name(),
-                                  verdict.feature_map(i).value());
+    base::test::TestFuture<const ClientPhishingRequest&,
+                           PhishingClassifier::Result>
+        test_future;
+    classifier_->BeginClassification(page_text, test_future.GetCallback());
+    verdict_ = test_future.Get<0>();
+    for (int i = 0; i < verdict_.feature_map_size(); ++i) {
+      feature_map_.AddRealFeature(verdict_.feature_map(i).name(),
+                                  verdict_.feature_map(i).value());
     }
-    run_loop_.Quit();
   }
 
   void LoadHtml(const GURL& url, const std::string& content) {
@@ -246,7 +238,6 @@
 
   std::string response_content_;
   std::unique_ptr<PhishingClassifier> classifier_;
-  base::RunLoop run_loop_;
   base::MappedReadOnlyRegion mapped_region_;
 
   // Features that are in the model.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 50bbabb..648b675 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -6797,8 +6797,7 @@
   }
 
   if (enable_glic) {
-    sources += [ "../browser/glic/glic_enabling_unittest.cc" ]
-    deps += [ "//chrome/browser/glic:enabling" ]
+    deps += [ "//chrome/browser/glic:unit_tests" ]
   }
 
   if (is_win || is_mac) {
@@ -7565,6 +7564,7 @@
       "../browser/ui/tabs/organization/trigger_observer_unittest.cc",
       "../browser/ui/tabs/organization/trigger_policies_unittest.cc",
       "../browser/ui/tabs/organization/trigger_unittest.cc",
+      "../browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data_unittest.cc",
       "../browser/ui/tabs/saved_tab_groups/saved_tab_group_keyed_service_unittest.cc",
       "../browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy_unittest.cc",
       "../browser/ui/thumbnails/thumbnail_capture_driver_unittest.cc",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn
index 2c5f261..b1a174f 100644
--- a/chrome/test/android/BUILD.gn
+++ b/chrome/test/android/BUILD.gn
@@ -210,12 +210,12 @@
     "javatests/src/org/chromium/chrome/test/transit/edge_to_edge/EdgeToEdgeBottomChinFacility.java",
     "javatests/src/org/chromium/chrome/test/transit/edge_to_edge/EdgeToEdgeConditions.java",
     "javatests/src/org/chromium/chrome/test/transit/edge_to_edge/ViewportFitCoverPageStation.java",
+    "javatests/src/org/chromium/chrome/test/transit/hub/CardAtPositionCondition.java",
     "javatests/src/org/chromium/chrome/test/transit/hub/HubBaseStation.java",
     "javatests/src/org/chromium/chrome/test/transit/hub/HubStationUtils.java",
     "javatests/src/org/chromium/chrome/test/transit/hub/IncognitoTabSwitcherStation.java",
     "javatests/src/org/chromium/chrome/test/transit/hub/NewTabGroupDialogFacility.java",
     "javatests/src/org/chromium/chrome/test/transit/hub/RegularTabSwitcherStation.java",
-    "javatests/src/org/chromium/chrome/test/transit/hub/CardAtPositionCondition.java",
     "javatests/src/org/chromium/chrome/test/transit/hub/TabGroupDialogFacility.java",
     "javatests/src/org/chromium/chrome/test/transit/hub/TabListEditorAppMenu.java",
     "javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherAppMenuFacility.java",
@@ -277,6 +277,7 @@
     "//chrome/browser/hub:java",
     "//chrome/browser/hub/internal:java",
     "//chrome/browser/profiles/android:java",
+    "//chrome/browser/settings:java",
     "//chrome/browser/settings:test_support_java",
     "//chrome/browser/tab:java",
     "//chrome/browser/tab_ui/android:java",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/AppMenuFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/AppMenuFacility.java
index 72639e2..3005f4d 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/AppMenuFacility.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/AppMenuFacility.java
@@ -31,6 +31,7 @@
 import org.chromium.base.test.transit.Station;
 import org.chromium.base.test.transit.ViewSpec;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.settings.MainSettings;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuItemProperties;
 import org.chromium.chrome.test.transit.ntp.IncognitoNewTabPageStation;
 import org.chromium.chrome.test.transit.ntp.RegularNewTabPageStation;
@@ -164,8 +165,8 @@
     }
 
     /** Default behavior for "Settings". */
-    protected SettingsStation createSettingsStation() {
-        return new SettingsStation();
+    protected SettingsStation<MainSettings> createSettingsStation() {
+        return new SettingsStation<>(MainSettings.class);
     }
 
     protected static Matcher<View> itemViewMatcher(@IdRes int id) {
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/settings/PreferenceFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/settings/PreferenceFacility.java
index 4f19acc..a04e9abc 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/settings/PreferenceFacility.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/settings/PreferenceFacility.java
@@ -22,7 +22,7 @@
 import org.chromium.base.test.transit.ViewSpec;
 
 /** The facility describing one setting preference item in the MainSettings fragment. */
-public class PreferenceFacility extends Facility<SettingsStation> {
+public class PreferenceFacility extends Facility<SettingsStation<?>> {
     private final ViewSpec mPrefViewSpec;
 
     private ViewElement mPrefView;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/settings/SettingsActivityPublicTransitEntryPoints.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/settings/SettingsActivityPublicTransitEntryPoints.java
index 29c8a402..8df4c08 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/settings/SettingsActivityPublicTransitEntryPoints.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/settings/SettingsActivityPublicTransitEntryPoints.java
@@ -32,11 +32,11 @@
      *
      * @return the active entry {@link SettingsStation}
      */
-    public SettingsStation startMainSettingsNonBatched() {
+    public SettingsStation<MainSettings> startMainSettingsNonBatched() {
         EntryPointSentinelStation sentinel = new EntryPointSentinelStation();
         sentinel.setAsEntryPoint();
 
-        SettingsStation entryPageStation = new SettingsStation();
+        SettingsStation<MainSettings> entryPageStation = new SettingsStation<>(MainSettings.class);
         return sentinel.travelToSync(
                 entryPageStation, mSettingsActivityTestRule::startSettingsActivity);
     }
@@ -46,16 +46,16 @@
      *
      * @return the active entry {@link SettingsStation}
      */
-    public SettingsStation startMainSettings(
-            BatchedPublicTransitRule<SettingsStation> batchedRule) {
+    public SettingsStation<MainSettings> startMainSettings(
+            BatchedPublicTransitRule<SettingsStation<MainSettings>> batchedRule) {
         return startBatched(batchedRule, this::startMainSettingsNonBatched);
     }
 
-    private SettingsStation startBatched(
-            BatchedPublicTransitRule<SettingsStation> batchedRule,
-            Callable<SettingsStation> entryPointCallable) {
+    private SettingsStation<MainSettings> startBatched(
+            BatchedPublicTransitRule<SettingsStation<MainSettings>> batchedRule,
+            Callable<SettingsStation<MainSettings>> entryPointCallable) {
         mSettingsActivityTestRule.setFinishActivity(false);
-        SettingsStation station = batchedRule.getHomeStation();
+        SettingsStation<MainSettings> station = batchedRule.getHomeStation();
         if (station == null) {
             try {
                 station = entryPointCallable.call();
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/settings/SettingsStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/settings/SettingsStation.java
index d0c0e69..70f423f 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/settings/SettingsStation.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/settings/SettingsStation.java
@@ -9,37 +9,39 @@
 import org.chromium.base.test.transit.FragmentElement;
 import org.chromium.base.test.transit.Station;
 import org.chromium.base.test.transit.Transition;
-import org.chromium.chrome.browser.settings.MainSettings;
+import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment;
 import org.chromium.chrome.browser.settings.SettingsActivity;
 
 /**
- * The initial and main Settings screen.
+ * A Settings screen.
  *
- * <p>TODO(crbug.com/328277614): This is a stub; add more elements and methods.
+ * @param <FragmentT> type of ChromeBaseSettingsFragment shown in this screen
  */
-public class SettingsStation extends Station<SettingsActivity> {
-    private FragmentElement<MainSettings, SettingsActivity> mMainSettings;
+public class SettingsStation<FragmentT extends ChromeBaseSettingsFragment>
+        extends Station<SettingsActivity> {
+    private final Class<FragmentT> mFragmentClass;
+    private FragmentElement<FragmentT, SettingsActivity> mFragmentElement;
 
-    public SettingsStation() {
+    public SettingsStation(Class<FragmentT> fragmentClass) {
         super(SettingsActivity.class);
+        mFragmentClass = fragmentClass;
     }
 
     @Override
     public void declareElements(Elements.Builder elements) {
         super.declareElements(elements);
-        mMainSettings =
-                elements.declareElement(
-                        new FragmentElement<>(MainSettings.class, mActivityElement));
+        mFragmentElement =
+                elements.declareElement(new FragmentElement<>(mFragmentClass, mActivityElement));
     }
 
     public PreferenceFacility scrollToPref(String prefKey) {
         assertSuppliersCanBeUsed();
-        String title = mMainSettings.get().findPreference(prefKey).getTitle().toString();
+        String title = mFragmentElement.get().findPreference(prefKey).getTitle().toString();
         return enterFacilitySync(
                 new PreferenceFacility(title),
                 Transition.newOptions().withPossiblyAlreadyFulfilled().build(),
                 () ->
                         ThreadUtils.runOnUiThreadBlocking(
-                                () -> mMainSettings.get().scrollToPreference(prefKey)));
+                                () -> mFragmentElement.get().scrollToPreference(prefKey)));
     }
 }
diff --git a/chrome/test/base/browser_with_test_window_test.cc b/chrome/test/base/browser_with_test_window_test.cc
index ffd86b7..f1d5067 100644
--- a/chrome/test/base/browser_with_test_window_test.cc
+++ b/chrome/test/base/browser_with_test_window_test.cc
@@ -81,6 +81,12 @@
     ash::AshTestHelper::InitParams ash_init;
     ash_init.local_state = g_browser_process->local_state();
     ash_test_helper_.SetUp(std::move(ash_init));
+
+    // Do not auto create user pref service because it will be provided
+    // in `CreateProfile`.
+    ash_test_helper()
+        ->test_session_controller_client()
+        ->set_default_provide_pref_service(false);
   }
 #endif
 
@@ -330,6 +336,9 @@
   // may be injected.
   auto* user_manager = user_manager::UserManager::Get();
   user_manager->OnUserProfileCreated(account_id, profile->GetPrefs());
+  ash_test_helper()
+      ->test_session_controller_client()
+      ->SetUnownedUserPrefService(account_id, profile->GetPrefs());
   auto observation =
       std::make_unique<base::ScopedObservation<Profile, ProfileObserver>>(this);
   observation->Observe(profile);
diff --git a/chrome/test/data/webui/chrome_urls/app_test.ts b/chrome/test/data/webui/chrome_urls/app_test.ts
index 5d93f26..bc0b1a8 100644
--- a/chrome/test/data/webui/chrome_urls/app_test.ts
+++ b/chrome/test/data/webui/chrome_urls/app_test.ts
@@ -102,7 +102,7 @@
     assertEquals('chrome://webui-gallery', internalItems[0]!.textContent);
     assertFalse(!!internalItems[0]!.querySelector('a'));
 
-    const message = lists[1]!.previousElementSibling;
+    const message = app.shadowRoot!.querySelector('#debug-pages-description');
     assertTrue(!!message);
     const status = message.querySelector('span.bold');
     assertTrue(!!status);
@@ -131,7 +131,7 @@
     assertEquals('chrome://webui-gallery/', link.href);
     assertEquals('chrome://webui-gallery', link.textContent);
 
-    const message = lists[1]!.previousElementSibling;
+    const message = app.shadowRoot!.querySelector('#debug-pages-description');
     assertTrue(!!message);
     const status = message.querySelector('span.bold');
     assertTrue(!!status);
@@ -139,4 +139,57 @@
 
     assertHeadings(true);
   });
+
+  test('Toggle debug UIs enabled', async () => {
+    const webuiUrls: WebuiUrlInfo[] = [
+      {url: {url: 'chrome://settings/'}, enabled: true, internal: false},
+      {url: {url: 'chrome://bookmarks/'}, enabled: false, internal: false},
+      {url: {url: 'chrome://webui-gallery/'}, enabled: true, internal: true},
+    ];
+    await finishSetup(webuiUrls);
+
+    const lists = app.shadowRoot!.querySelectorAll('ul');
+    assertEquals(3, lists.length);
+
+    // No links since debug pages are disabled.
+    let internalItems = lists[1]!.querySelectorAll('li');
+    assertEquals(1, internalItems.length);
+    assertEquals('chrome://webui-gallery', internalItems[0]!.textContent);
+    assertFalse(!!internalItems[0]!.querySelector('a'));
+
+    // Message is set to 'disabled' and button is to enable the pages.
+    const message = app.shadowRoot!.querySelector('#debug-pages-description');
+    assertTrue(!!message);
+    const status = message.querySelector('span.bold');
+    assertTrue(!!status);
+    assertEquals('disabled', status.textContent);
+    const button = app.shadowRoot!.querySelector('cr-button');
+    assertTrue(!!button);
+    assertEquals('Enable internal debugging pages', button.textContent!.trim());
+
+    // Test case of enabling debug pages.
+    button.click();
+    let enabled = await browserProxy.handler.whenCalled('setDebugPagesEnabled');
+    assertTrue(enabled);
+    await microtasksFinished();
+    // Status is enabled, button is to disable, and page is linked.
+    assertEquals('enabled', status.textContent);
+    assertEquals(
+        'Disable internal debugging pages', button.textContent!.trim());
+    internalItems = lists[1]!.querySelectorAll('li');
+    assertEquals(1, internalItems.length);
+    assertTrue(!!internalItems[0]!.querySelector('a'));
+
+    // Test case of disabling debug pages.
+    browserProxy.handler.resetResolver('setDebugPagesEnabled');
+    button.click();
+    enabled = await browserProxy.handler.whenCalled('setDebugPagesEnabled');
+    assertFalse(enabled);
+    await microtasksFinished();
+    assertEquals('disabled', status.textContent);
+    assertEquals('Enable internal debugging pages', button.textContent!.trim());
+    internalItems = lists[1]!.querySelectorAll('li');
+    assertEquals(1, internalItems.length);
+    assertFalse(!!internalItems[0]!.querySelector('a'));
+  });
 });
diff --git a/chrome/test/data/webui/chrome_urls/test_chrome_urls_browser_proxy.ts b/chrome/test/data/webui/chrome_urls/test_chrome_urls_browser_proxy.ts
index fcbf5a58..40dd81f 100644
--- a/chrome/test/data/webui/chrome_urls/test_chrome_urls_browser_proxy.ts
+++ b/chrome/test/data/webui/chrome_urls/test_chrome_urls_browser_proxy.ts
@@ -20,7 +20,7 @@
   };
 
   constructor() {
-    super(['getUrls']);
+    super(['getUrls', 'setDebugPagesEnabled']);
   }
 
   getUrls(): Promise<{urlsData: ChromeUrlsData}> {
@@ -28,6 +28,11 @@
     return Promise.resolve({urlsData: structuredClone(this.testData_)});
   }
 
+  setDebugPagesEnabled(enabled: boolean): Promise<void> {
+    this.methodCalled('setDebugPagesEnabled', enabled);
+    return Promise.resolve();
+  }
+
   setTestData(data: ChromeUrlsData) {
     this.testData_ = structuredClone(data);
   }
diff --git a/chrome/test/data/webui/chromeos/settings/os_people_page/password_settings_api.test-mojom b/chrome/test/data/webui/chromeos/settings/os_people_page/password_settings_api.test-mojom
index b04c48e..9549e9b 100644
--- a/chrome/test/data/webui/chromeos/settings/os_people_page/password_settings_api.test-mojom
+++ b/chrome/test/data/webui/chromeos/settings/os_people_page/password_settings_api.test-mojom
@@ -29,4 +29,7 @@
 
   // Checks whether the user can remove password.
   AssertCanRemovePassword(bool can_remove) => ();
+
+  // Checks whether the user can switch to local password.
+  AssertCanSwitchToLocalPassword(bool can_switch) => ();
 };
diff --git a/chrome/test/data/webui/chromeos/settings/os_people_page/password_settings_api.ts b/chrome/test/data/webui/chromeos/settings/os_people_page/password_settings_api.ts
index 9860960..bfe6f83a 100644
--- a/chrome/test/data/webui/chromeos/settings/os_people_page/password_settings_api.ts
+++ b/chrome/test/data/webui/chromeos/settings/os_people_page/password_settings_api.ts
@@ -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 {assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {isVisible} from 'chrome://webui-test/test_util.js';
 
 import {PasswordSettingsApiInterface, PasswordSettingsApiReceiver, PasswordSettingsApiRemote} from '../password_settings_api.test-mojom-webui.js';
@@ -129,4 +129,12 @@
     const buttons = this.getRemoveMenuItems();
     await assertAsync(() => canRemove === (buttons.length > 0));
   }
+
+  async assertCanSwitchToLocalPassword(canSwitch: boolean): Promise<void> {
+    const button = this.switchLocalPasswordButton();
+    if (button == null) {
+      assertFalse(canSwitch)
+    }
+    await assertAsync(() => canSwitch === isVisible(button));
+  }
 }
diff --git a/chrome/test/fuzzing/webidl_fuzzing/webidl_in_process_fuzzer.cc b/chrome/test/fuzzing/webidl_fuzzing/webidl_in_process_fuzzer.cc
index 2f26a35..806b43c 100644
--- a/chrome/test/fuzzing/webidl_fuzzing/webidl_in_process_fuzzer.cc
+++ b/chrome/test/fuzzing/webidl_fuzzing/webidl_in_process_fuzzer.cc
@@ -19,9 +19,10 @@
   const bool kDumpNativeInput = getenv("LPM_DUMP_NATIVE_INPUT");
 };
 
-constexpr std::optional<base::TimeDelta> kJsExecutionTimeout = base::Seconds(8);
+constexpr std::optional<base::TimeDelta> kJsExecutionTimeout =
+    base::Seconds(10);
 constexpr RunLoopTimeoutBehavior kJsRunLoopTimeoutBehavior =
-    RunLoopTimeoutBehavior::kDeclareInfiniteLoop;
+    RunLoopTimeoutBehavior::kContinue;
 
 // This fuzzer uses DomatoLPM to generate JS based on an existing Domato
 // rule.
diff --git a/chrome/updater/app/app_install_win.cc b/chrome/updater/app/app_install_win.cc
index c08d2f8..eff3381 100644
--- a/chrome/updater/app/app_install_win.cc
+++ b/chrome/updater/app/app_install_win.cc
@@ -21,8 +21,6 @@
 #include <vector>
 
 #include "base/check_op.h"
-#include "base/debug/alias.h"
-#include "base/debug/dump_without_crashing.h"
 #include "base/files/file_path.h"
 #include "base/functional/callback.h"
 #include "base/json/json_string_value_serializer.h"
@@ -744,19 +742,7 @@
     const UpdateService::UpdateState& update_state) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  AppInstallProgressIPC* dbg_ipc = install_progress_observer_ipc_.get();
-  base::debug::Alias(&dbg_ipc);
-  CHECK(install_progress_observer_ipc_);
-
-  // TODO(crbug.com/345250525) - understand why the check fails.
-  UpdateService::UpdateState::State state = update_state.state;
-  base::debug::Alias(&state);
-  DEBUG_ALIAS_FOR_CSTR(dbg_app_id1, app_id_.c_str(), 64);
-  DEBUG_ALIAS_FOR_CSTR(dbg_app_id2, update_state.app_id.c_str(), 64);
-  if (app_id_ != update_state.app_id) {
-    base::debug::DumpWithoutCrashing();
-    return;
-  }
+  CHECK_EQ(app_id_, update_state.app_id);
 
   switch (update_state.state) {
     case UpdateService::UpdateState::State::kCheckingForUpdates:
diff --git a/chrome/updater/ipc/update_service_proxy_win.cc b/chrome/updater/ipc/update_service_proxy_win.cc
index 23fa13b..43071b2 100644
--- a/chrome/updater/ipc/update_service_proxy_win.cc
+++ b/chrome/updater/ipc/update_service_proxy_win.cc
@@ -16,9 +16,7 @@
 #include <utility>
 #include <vector>
 
-#include "base/check.h"
-#include "base/debug/alias.h"
-#include "base/debug/dump_without_crashing.h"
+#include "base/check_op.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/logging.h"
@@ -201,13 +199,8 @@
           base::WideToUTF8(installer_cmd_line.Get());
     }
 
-    // TODO(crbug.com/345250525) - understand why the check fails.
-    base::debug::Alias(&update_service_state);
-    if (update_service_state.state ==
-        UpdateService::UpdateState::State::kUnknown) {
-      VLOG(2) << update_service_state;
-      base::debug::DumpWithoutCrashing();
-    }
+    CHECK_NE(update_service_state.state,
+             UpdateService::UpdateState::State::kUnknown);
     return update_service_state;
   }
 
diff --git a/chrome/updater/update_service_impl_impl.cc b/chrome/updater/update_service_impl_impl.cc
index e409fd5..4b1aefb6 100644
--- a/chrome/updater/update_service_impl_impl.cc
+++ b/chrome/updater/update_service_impl_impl.cc
@@ -13,12 +13,10 @@
 
 #include "base/barrier_callback.h"
 #include "base/barrier_closure.h"
-#include "base/check.h"
+#include "base/check_op.h"
 #include "base/containers/contains.h"
 #include "base/containers/flat_map.h"
 #include "base/containers/queue.h"
-#include "base/debug/alias.h"
-#include "base/debug/dump_without_crashing.h"
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/functional/bind.h"
@@ -591,12 +589,9 @@
           config->GetPrefService()->CommitPendingWrite();
         }
 
-        // TODO(crbug.com/345250525): remove dump instrumentation when fixed.
-        base::debug::Alias(&update_state);
-        if (update_state.app_id.empty() ||
-            update_state.state == UpdateService::UpdateState::State::kUnknown) {
-          base::debug::DumpWithoutCrashing();
-        }
+        CHECK(!update_state.app_id.empty());
+        CHECK_NE(update_state.state,
+                 UpdateService::UpdateState::State::kUnknown);
         callback.Run(update_state);
       },
       config, persisted_data, new_install, callback);
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 7969c75..213fe885 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-16118.0.0-1065216
\ No newline at end of file
+16123.0.0-1065321
\ No newline at end of file
diff --git a/chromeos/ash/components/standalone_browser/BUILD.gn b/chromeos/ash/components/standalone_browser/BUILD.gn
index 55c5dfd..e5a472f 100644
--- a/chromeos/ash/components/standalone_browser/BUILD.gn
+++ b/chromeos/ash/components/standalone_browser/BUILD.gn
@@ -45,7 +45,6 @@
     "channel_util_unittest.cc",
     "lacros_availability_unittest.cc",
     "lacros_selection_unittest.cc",
-    "test_util_unittest.cc",
   ]
 
   deps = [
@@ -66,11 +65,7 @@
 source_set("test_support") {
   testonly = true
 
-  sources = [
-    "feature_refs.cc",
-    "test_util.cc",
-    "test_util.h",
-  ]
+  sources = [ "feature_refs.cc" ]
 
   deps = [
     ":standalone_browser",
diff --git a/chromeos/ash/components/standalone_browser/test_util.cc b/chromeos/ash/components/standalone_browser/test_util.cc
deleted file mode 100644
index a28c293..0000000
--- a/chromeos/ash/components/standalone_browser/test_util.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromeos/ash/components/standalone_browser/test_util.h"
-
-#include <string>
-#include <string_view>
-#include <vector>
-
-#include "ash/constants/ash_switches.h"
-#include "base/command_line.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-
-namespace ash::standalone_browser {
-
-void AddLacrosArguments(base::span<std::string> new_args,
-                        base::CommandLine* command_line) {
-  // Extract the old arguments (if any). `old_switch` and `args` will be
-  // empty if the command line switch isn't present.
-  std::string old_switch =
-      command_line->GetSwitchValueASCII(switches::kLacrosChromeAdditionalArgs);
-  std::vector<std::string_view> args = base::SplitStringPieceUsingSubstr(
-      old_switch, "####", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
-
-  // Append the new args.
-  args.insert(args.end(), new_args.begin(), new_args.end());
-
-  // Replace the ash switch.
-  command_line->RemoveSwitch(switches::kLacrosChromeAdditionalArgs);
-  std::string new_switch = base::JoinString(args, "####");
-  command_line->AppendSwitchASCII(switches::kLacrosChromeAdditionalArgs,
-                                  new_switch);
-}
-
-}  // namespace ash::standalone_browser
diff --git a/chromeos/ash/components/standalone_browser/test_util.h b/chromeos/ash/components/standalone_browser/test_util.h
deleted file mode 100644
index 48a3f0b..0000000
--- a/chromeos/ash/components/standalone_browser/test_util.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROMEOS_ASH_COMPONENTS_STANDALONE_BROWSER_TEST_UTIL_H_
-#define CHROMEOS_ASH_COMPONENTS_STANDALONE_BROWSER_TEST_UTIL_H_
-
-#include <string>
-
-#include "base/component_export.h"
-#include "base/containers/span.h"
-
-namespace base {
-class CommandLine;
-}  // namespace base
-
-namespace ash::standalone_browser {
-
-// Adds command line arguments that will be passed to Lacros. `new_args` are the
-// arguments to add. If there are existing Lacros arguments, the `new_args` will
-// be appended. Arguments should include the "--" prefix, e.g. "--foo".
-// `command_line` is the current ash-chrome command line. It will be modified by
-// this function.
-COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_STANDALONE_BROWSER)
-void AddLacrosArguments(base::span<std::string> new_args,
-                        base::CommandLine* command_line);
-
-}  // namespace ash::standalone_browser
-
-#endif  // CHROMEOS_ASH_COMPONENTS_STANDALONE_BROWSER_TEST_UTIL_H_
diff --git a/chromeos/ash/components/standalone_browser/test_util_unittest.cc b/chromeos/ash/components/standalone_browser/test_util_unittest.cc
deleted file mode 100644
index 3d97762..0000000
--- a/chromeos/ash/components/standalone_browser/test_util_unittest.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromeos/ash/components/standalone_browser/test_util.h"
-
-#include <string>
-#include <vector>
-
-#include "ash/constants/ash_switches.h"
-#include "base/command_line.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace ash::standalone_browser {
-
-TEST(AddLacrosArguments, NoExistingArgs) {
-  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-  ASSERT_FALSE(command_line.HasSwitch(switches::kLacrosChromeAdditionalArgs));
-
-  std::vector<std::string> args = {"--arg1", "--arg2=value2"};
-  AddLacrosArguments(args, &command_line);
-
-  EXPECT_EQ(
-      command_line.GetSwitchValueASCII(switches::kLacrosChromeAdditionalArgs),
-      "--arg1####--arg2=value2");
-}
-
-TEST(AddLacrosArguments, WithExistingArgs) {
-  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-  ASSERT_FALSE(command_line.HasSwitch(switches::kLacrosChromeAdditionalArgs));
-
-  command_line.AppendSwitchASCII(switches::kLacrosChromeAdditionalArgs,
-                                 "--arg1####--arg2=value2");
-  std::vector<std::string> args = {"--arg3", "--arg4=value4"};
-  AddLacrosArguments(args, &command_line);
-
-  EXPECT_EQ(
-      command_line.GetSwitchValueASCII(switches::kLacrosChromeAdditionalArgs),
-      "--arg1####--arg2=value2####--arg3####--arg4=value4");
-}
-
-}  // namespace ash::standalone_browser
diff --git a/chromeos/ash/services/auth_factor_config/password_factor_editor.cc b/chromeos/ash/services/auth_factor_config/password_factor_editor.cc
index 68c4ba1..82cde3d95 100644
--- a/chromeos/ash/services/auth_factor_config/password_factor_editor.cc
+++ b/chromeos/ash/services/auth_factor_config/password_factor_editor.cc
@@ -197,15 +197,6 @@
       is_new_password_local != is_old_password_local;
 
   if (is_label_update_required) {
-    if (!features::IsChangePasswordFactorSetupEnabled()) {
-      LOG(ERROR)
-          << "Switching between online and local password is not supported";
-      auth_factor_config_->NotifyFactorObserversAfterFailure(
-          auth_token, std::move(user_context),
-          base::BindOnce(std::move(callback),
-                         mojom::ConfigureResult::kFatalError));
-      return;
-    }
     if (!is_new_password_local) {
       LOG(ERROR) << "Switching from local to online password is not supported";
       auth_factor_config_->NotifyFactorObserversAfterFailure(
diff --git a/chromeos/strings/chromeos_strings_es.xtb b/chromeos/strings/chromeos_strings_es.xtb
index 3d6e0abb..5ecb229 100644
--- a/chromeos/strings/chromeos_strings_es.xtb
+++ b/chromeos/strings/chromeos_strings_es.xtb
@@ -1082,7 +1082,7 @@
 <translation id="6231648282154119906">Navegación segura de Google analizará automáticamente los archivos sospechosos como parte de la protección mejorada que has elegido</translation>
 <translation id="6232017090690406397">Batería</translation>
 <translation id="6234024205316847054">Mostrar detalles</translation>
-<translation id="6243280677745499710">Establecido actualmente</translation>
+<translation id="6243280677745499710">Opción actual</translation>
 <translation id="6250316632541035980">huevos con beicon</translation>
 <translation id="6265268291107409527">La tecla seleccionada es <ph name="KEYS" />. <ph name="ASSIGN_INSTRUCTION" /></translation>
 <translation id="6275224645089671689">Flecha hacia la derecha</translation>
diff --git a/clank b/clank
index b043bc0..2194079 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit b043bc0a6aded7bdc2d9633940caeeafa3c7f42c
+Subproject commit 21940795d0716914166441b2043aae2ec64086f1
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 48be78bb..50f7930 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -580,6 +580,7 @@
       "//components/facilitated_payments/content/renderer:unit_tests",
       "//components/fingerprinting_protection_filter/browser:unit_tests",
       "//components/fingerprinting_protection_filter/common:unit_tests",
+      "//components/fingerprinting_protection_filter/interventions/browser:unit_tests",
       "//components/fingerprinting_protection_filter/renderer:unit_tests",
       "//components/headless/test:unit_tests",
       "//components/media_router/browser:unit_tests",
diff --git a/components/android_autofill/browser/android_autofill_client.cc b/components/android_autofill/browser/android_autofill_client.cc
index 785ac04..5e5da5e 100644
--- a/components/android_autofill/browser/android_autofill_client.cc
+++ b/components/android_autofill/browser/android_autofill_client.cc
@@ -78,8 +78,8 @@
   if (!crowdsourcing_manager_) {
     // Lazy initialization to avoid virtual function calls in the constructor.
     crowdsourcing_manager_ =
-        std::make_unique<autofill::AutofillCrowdsourcingManager>(
-            this, GetChannel(), GetLogManager());
+        std::make_unique<autofill::AutofillCrowdsourcingManager>(this,
+                                                                 GetChannel());
   }
   return *crowdsourcing_manager_;
 }
diff --git a/components/autofill/content/renderer/html_based_username_detector_browsertest.cc b/components/autofill/content/renderer/html_based_username_detector_browsertest.cc
index 9b74b1e..a3acec36 100644
--- a/components/autofill/content/renderer/html_based_username_detector_browsertest.cc
+++ b/components/autofill/content/renderer/html_based_username_detector_browsertest.cc
@@ -280,10 +280,10 @@
 }
 
 TEST_F(HtmlBasedUsernameDetectorTest, HTMLDetectorCache) {
-  const TextField text_fields[] = {
+  const auto text_fields = std::to_array<TextField>({
       {"unknown", "12345"},
       {"something", "smith"},
-  };
+  });
 
   const std::string& form_html = GetFormHTML(text_fields[0], text_fields[1]);
 
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn
index 8cba95c..00e99a1 100644
--- a/components/autofill/core/browser/BUILD.gn
+++ b/components/autofill/core/browser/BUILD.gn
@@ -69,11 +69,6 @@
     "address_data_cleaner.h",
     "address_data_manager.cc",
     "address_data_manager.h",
-    "address_normalization_manager.cc",
-    "address_normalization_manager.h",
-    "address_normalizer.h",
-    "address_normalizer_impl.cc",
-    "address_normalizer_impl.h",
     "autocomplete_history_manager.cc",
     "autocomplete_history_manager.h",
     "autofill_ablation_study.cc",
@@ -86,8 +81,6 @@
     "autofill_client.cc",
     "autofill_client.h",
     "autofill_compose_delegate.h",
-    "autofill_data_util.cc",
-    "autofill_data_util.h",
     "autofill_driver.cc",
     "autofill_driver.h",
     "autofill_driver_factory.cc",
@@ -197,6 +190,19 @@
     "data_model/phone_number.h",
     "data_model/profile_value_source.cc",
     "data_model/profile_value_source.h",
+    "data_quality/addresses/address_normalization_manager.cc",
+    "data_quality/addresses/address_normalization_manager.h",
+    "data_quality/addresses/address_normalizer.h",
+    "data_quality/addresses/address_normalizer_impl.cc",
+    "data_quality/addresses/address_normalizer_impl.h",
+    "data_quality/addresses/profile_requirement_utils.cc",
+    "data_quality/addresses/profile_requirement_utils.h",
+    "data_quality/addresses/profile_token_quality.cc",
+    "data_quality/addresses/profile_token_quality.h",
+    "data_quality/autofill_data_util.cc",
+    "data_quality/autofill_data_util.h",
+    "data_quality/validation.cc",
+    "data_quality/validation.h",
     "field_type_utils.cc",
     "field_type_utils.h",
     "field_types.cc",
@@ -500,10 +506,6 @@
     "personal_data_manager.cc",
     "personal_data_manager.h",
     "personal_data_manager_observer.h",
-    "profile_requirement_utils.cc",
-    "profile_requirement_utils.h",
-    "profile_token_quality.cc",
-    "profile_token_quality.h",
     "select_control_util.cc",
     "select_control_util.h",
     "single_field_fill_router.cc",
@@ -589,8 +591,6 @@
     "ui/suggestion_type.cc",
     "ui/suggestion_type.h",
     "ui/touch_to_fill_delegate.h",
-    "validation.cc",
-    "validation.h",
     "webdata/addresses/address_autofill_table.cc",
     "webdata/addresses/address_autofill_table.h",
     "webdata/addresses/autofill_profile_sync_bridge.cc",
@@ -891,6 +891,10 @@
     "data_model/credit_card_benefit_test_api.h",
     "data_model/test_autofill_data_model.cc",
     "data_model/test_autofill_data_model.h",
+    "data_quality/addresses/profile_token_quality_test_api.cc",
+    "data_quality/addresses/profile_token_quality_test_api.h",
+    "data_quality/addresses/test_address_normalizer.cc",
+    "data_quality/addresses/test_address_normalizer.h",
     "filling/form_filler_test_api.h",
     "filling/test_form_filler.cc",
     "filling/test_form_filler.h",
@@ -968,8 +972,6 @@
     "payments_data_manager_test_api.h",
     "personal_data_manager_test_utils.cc",
     "personal_data_manager_test_utils.h",
-    "profile_token_quality_test_api.cc",
-    "profile_token_quality_test_api.h",
     "strike_databases/payments/test_credit_card_save_strike_database.cc",
     "strike_databases/payments/test_credit_card_save_strike_database.h",
     "strike_databases/payments/test_strike_database.cc",
@@ -978,8 +980,6 @@
     "strike_databases/test_inmemory_strike_database.h",
     "test_address_data_manager.cc",
     "test_address_data_manager.h",
-    "test_address_normalizer.cc",
-    "test_address_normalizer.h",
     "test_autofill_client.cc",
     "test_autofill_client.h",
     "test_autofill_clock.cc",
@@ -1126,12 +1126,9 @@
   sources = [
     "address_data_cleaner_unittest.cc",
     "address_data_manager_unittest.cc",
-    "address_normalization_manager_unittest.cc",
-    "address_normalizer_impl_unittest.cc",
     "autocomplete_history_manager_unittest.cc",
     "autofill_ablation_study_unittest.cc",
     "autofill_address_util_unittest.cc",
-    "autofill_data_util_unittest.cc",
     "autofill_experiments_unittest.cc",
     "autofill_external_delegate_unittest.cc",
     "autofill_feedback_data_unittest.cc",
@@ -1169,6 +1166,12 @@
     "data_model/payment_instrument_unittest.cc",
     "data_model/phone_number_unittest.cc",
     "data_model/profile_value_source_unittest.cc",
+    "data_quality/addresses/address_normalization_manager_unittest.cc",
+    "data_quality/addresses/address_normalizer_impl_unittest.cc",
+    "data_quality/addresses/profile_requirement_utils_unittest.cc",
+    "data_quality/addresses/profile_token_quality_unittest.cc",
+    "data_quality/autofill_data_util_unittest.cc",
+    "data_quality/validation_unittest.cc",
     "field_type_utils_unittest.cc",
     "field_types_unittest.cc",
     "filling/addresses/field_filling_address_util_unittest.cc",
@@ -1277,8 +1280,6 @@
     "payments_data_manager_test_base.cc",
     "payments_data_manager_test_base.h",
     "payments_data_manager_unittest.cc",
-    "profile_requirement_utils_unittest.cc",
-    "profile_token_quality_unittest.cc",
     "select_control_util_unittest.cc",
     "single_field_fill_router_unittest.cc",
     "strike_databases/history_clearable_strike_database_unittest.cc",
@@ -1298,7 +1299,6 @@
     "ui/payments/save_payment_method_and_virtual_card_enroll_confirmation_ui_params_unittest.cc",
     "ui/payments/virtual_card_enroll_ui_model_unittest.cc",
     "ui/region_combobox_model_unittest.cc",
-    "validation_unittest.cc",
     "webdata/addresses/address_autofill_table_unittest.cc",
     "webdata/addresses/autofill_profile_sync_bridge_unittest.cc",
     "webdata/addresses/autofill_profile_sync_difference_tracker_unittest.cc",
diff --git a/components/autofill/core/browser/address_data_cleaner.cc b/components/autofill/core/browser/address_data_cleaner.cc
index a30e988..9e7308e 100644
--- a/components/autofill/core/browser/address_data_cleaner.cc
+++ b/components/autofill/core/browser/address_data_cleaner.cc
@@ -10,11 +10,11 @@
 #include "components/autofill/core/browser/address_data_manager.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/autofill_profile_comparator.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/metrics/address_data_cleaner_metrics.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics_utils.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/browser/profile_token_quality.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/autofill/core/common/autofill_features.h"
diff --git a/components/autofill/core/browser/address_data_cleaner_unittest.cc b/components/autofill/core/browser/address_data_cleaner_unittest.cc
index a65a6b0b..bbc4742 100644
--- a/components/autofill/core/browser/address_data_cleaner_unittest.cc
+++ b/components/autofill/core/browser/address_data_cleaner_unittest.cc
@@ -11,9 +11,9 @@
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/data_model/autofill_profile_comparator.h"
 #include "components/autofill/core/browser/data_model/autofill_profile_test_api.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality_test_api.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics_utils.h"
-#include "components/autofill/core/browser/profile_token_quality.h"
-#include "components/autofill/core/browser/profile_token_quality_test_api.h"
 #include "components/autofill/core/browser/test_address_data_manager.h"
 #include "components/autofill/core/browser/test_utils/test_profiles.h"
 #include "components/autofill/core/common/autofill_clock.h"
diff --git a/components/autofill/core/browser/address_data_manager.cc b/components/autofill/core/browser/address_data_manager.cc
index 5ebaa748..a1589a7 100644
--- a/components/autofill/core/browser/address_data_manager.cc
+++ b/components/autofill/core/browser/address_data_manager.cc
@@ -20,6 +20,7 @@
 #include "base/task/single_thread_task_runner.h"
 #include "components/autofill/core/browser/address_data_cleaner.h"
 #include "components/autofill/core/browser/country_type.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.h"
 #include "components/autofill/core/browser/geo/alternative_state_name_map_updater.h"
 #include "components/autofill/core/browser/geo/autofill_country.h"
 #include "components/autofill/core/browser/geo/country_data.h"
@@ -27,7 +28,6 @@
 #include "components/autofill/core/browser/metrics/profile_deduplication_metrics.h"
 #include "components/autofill/core/browser/metrics/profile_token_quality_metrics.h"
 #include "components/autofill/core/browser/metrics/stored_profile_metrics.h"
-#include "components/autofill/core/browser/profile_requirement_utils.h"
 #include "components/autofill/core/browser/webdata/addresses/contact_info_precondition_checker.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_features.h"
diff --git a/components/autofill/core/browser/address_data_manager_unittest.cc b/components/autofill/core/browser/address_data_manager_unittest.cc
index 081e959..f94fd08 100644
--- a/components/autofill/core/browser/address_data_manager_unittest.cc
+++ b/components/autofill/core/browser/address_data_manager_unittest.cc
@@ -20,8 +20,8 @@
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/autofill_profile_test_api.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality_test_api.h"
 #include "components/autofill/core/browser/personal_data_manager_test_utils.h"
-#include "components/autofill/core/browser/profile_token_quality_test_api.h"
 #include "components/autofill/core/browser/strike_databases/test_inmemory_strike_database.h"
 #include "components/autofill/core/browser/webdata/addresses/address_autofill_table.h"
 #include "components/autofill/core/common/autofill_clock.h"
diff --git a/components/autofill/core/browser/autocomplete_history_manager.cc b/components/autofill/core/browser/autocomplete_history_manager.cc
index 340ed44..1edabf2b 100644
--- a/components/autofill/core/browser/autocomplete_history_manager.cc
+++ b/components/autofill/core/browser/autocomplete_history_manager.cc
@@ -14,9 +14,9 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/autofill/core/browser/autofill_experiments.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics.h"
 #include "components/autofill/core/browser/ui/suggestion.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/browser/webdata/autocomplete/autocomplete_entry.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_features.h"
diff --git a/components/autofill/core/browser/autofill_client.h b/components/autofill/core/browser/autofill_client.h
index c6512ba6..9525250 100644
--- a/components/autofill/core/browser/autofill_client.h
+++ b/components/autofill/core/browser/autofill_client.h
@@ -150,7 +150,6 @@
 
   // Describes the types of Iph shown by Autofill and anchored to a field.
   enum class IphFeature {
-    kManualFallback,
     kPredictionImprovements,
   };
 
diff --git a/components/autofill/core/browser/autofill_driver.cc b/components/autofill/core/browser/autofill_driver.cc
index 9c7adcdc..14a15cf 100644
--- a/components/autofill/core/browser/autofill_driver.cc
+++ b/components/autofill/core/browser/autofill_driver.cc
@@ -5,14 +5,58 @@
 #include "components/autofill/core/browser/autofill_driver.h"
 
 #include "base/check.h"
-#include "base/functional/function_ref.h"
-#include "components/autofill/core/browser/autofill_manager.h"
 
 namespace autofill {
 
+namespace {
+
+#if DCHECK_IS_ON()
+// Returns true iff the transition is a valid transition according to the
+// diagram in AutofillDriver's class-level documentation.
+// LINT.IfChange(LifecycleStateChanges)
+bool IsValidTransition(AutofillDriver::LifecycleState previous_state,
+                       AutofillDriver::LifecycleState old_state,
+                       AutofillDriver::LifecycleState new_state) {
+  using enum AutofillDriver::LifecycleState;
+  switch (old_state) {
+    case kInactive:
+      return new_state == kActive || new_state == kPendingReset ||
+             new_state == kPendingDeletion;
+    case kActive:
+      return new_state == kInactive || new_state == kPendingReset ||
+             new_state == kPendingDeletion;
+    case kPendingReset:
+      return new_state == previous_state &&
+             (new_state == kInactive || new_state == kActive);
+    case kPendingDeletion:
+      return false;
+  }
+  return false;
+}
+// LINT.ThenChange(autofill_driver.h:LifecycleStateChanges)
+#endif
+
+}  // namespace
+
 AutofillDriver::~AutofillDriver() {
-  CHECK_EQ(lifecycle_state_, LifecycleState::kPendingDeletion,
-           base::NotFatalUntil::M130);
+  CHECK_EQ(lifecycle_state_, LifecycleState::kPendingDeletion);
+}
+
+void AutofillDriver::SetLifecycleState(
+    LifecycleState new_state,
+    base::PassKey<AutofillDriverFactory> pass_key) {
+  DCHECK_NE(lifecycle_state_, new_state);
+#if DCHECK_IS_ON()
+  DCHECK(
+      IsValidTransition(previous_lifecycle_state_, lifecycle_state_, new_state))
+      << "Invalid AutofillDriver::LifecycleState change "
+      << base::to_underlying(previous_lifecycle_state_) << " -> "
+      << base::to_underlying(lifecycle_state_) << " -> "
+      << base::to_underlying(new_state);
+  previous_lifecycle_state_ = lifecycle_state_;
+#endif
+
+  lifecycle_state_ = new_state;
 }
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_driver.h b/components/autofill/core/browser/autofill_driver.h
index c42e84c3..120cebad 100644
--- a/components/autofill/core/browser/autofill_driver.h
+++ b/components/autofill/core/browser/autofill_driver.h
@@ -69,12 +69,16 @@
   //
   // The possible transitions are:
   //
-  //   ╭───────────────────────────╮
-  //   │                           ▼
-  // kInactive ◄──► kActive ──► kPendingDeletion
-  //   ▲                ▲
-  //   │                ╰─────► kPendingReset
-  //   ╰──────────────────────► kPendingReset
+  // LINT.IfChange(LifecycleStateChanges)
+  //
+  //     ╭───────────────────────────╮
+  //     │                           ▼
+  //   kInactive ◄──► kActive ──► kPendingDeletion
+  //     ▲                ▲
+  //     │                ╰─────► kPendingReset
+  //     ╰──────────────────────► kPendingReset
+  //
+  // LINT.ThenChange(autofill_driver.cc:LifecycleStateChanges)
   //
   // The initial state is kInactive.
   //
@@ -121,10 +125,7 @@
   // - notify observers,
   // - destruct the driver.
   void SetLifecycleState(LifecycleState new_state,
-                         base::PassKey<AutofillDriverFactory> pass_key) {
-    DCHECK_NE(lifecycle_state_, new_state);
-    lifecycle_state_ = new_state;
-  }
+                         base::PassKey<AutofillDriverFactory> pass_key);
 
   // Returns the uniquely identifying frame token.
   virtual LocalFrameToken GetFrameToken() const = 0;
@@ -334,6 +335,10 @@
   friend class AutofillDriverTestApi;
 
   LifecycleState lifecycle_state_ = LifecycleState::kInactive;
+
+#if DCHECK_IS_ON()
+  LifecycleState previous_lifecycle_state_ = LifecycleState::kInactive;
+#endif
 };
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_external_delegate.cc b/components/autofill/core/browser/autofill_external_delegate.cc
index 2878179..edd80a5 100644
--- a/components/autofill/core/browser/autofill_external_delegate.cc
+++ b/components/autofill/core/browser/autofill_external_delegate.cc
@@ -1203,8 +1203,8 @@
                                  /*field_type_used=*/std::nullopt);
   } else {
     // Full form filling.
-    Suggestion::PredictionImprovementsPayload payload =
-        suggestion.GetPayload<Suggestion::PredictionImprovementsPayload>();
+    Suggestion::AutofillAiPayload payload =
+        suggestion.GetPayload<Suggestion::AutofillAiPayload>();
     manager_->FillOrPreviewFormWithPredictionImprovements(
         mojom::ActionPersistence::kFill, payload.ignorable_skip_reasons,
         query_form_, query_field_, payload.values_to_fill);
diff --git a/components/autofill/core/browser/autofill_external_delegate_unittest.cc b/components/autofill/core/browser/autofill_external_delegate_unittest.cc
index dc9312af..a8c5ce3 100644
--- a/components/autofill/core/browser/autofill_external_delegate_unittest.cc
+++ b/components/autofill/core/browser/autofill_external_delegate_unittest.cc
@@ -1265,7 +1265,7 @@
 }
 
 // Tests that on acceptance of a `kFillPredictionImprovements` suggestion with
-// `Suggestion::PredictionImprovementsPayload` payload, the full form is filled
+// `Suggestion::AutofillAiPayload` payload, the full form is filled
 // accordingly.
 TEST_F(AutofillExternalDelegateTest,
        DidAcceptFillPredictionImprovementsFillsFullForm) {
@@ -1284,7 +1284,7 @@
       /*update_datalist=*/false);
   Suggestion fill_suggestion =
       Suggestion(u"Autocomplete", SuggestionType::kFillAutofillAi);
-  fill_suggestion.payload = Suggestion::PredictionImprovementsPayload(
+  fill_suggestion.payload = Suggestion::AutofillAiPayload(
       {{field_to_fill->global_id(), value_to_fill}}, {});
 
   std::vector<FormFieldData> filled_fields;
diff --git a/components/autofill/core/browser/browser_autofill_manager.cc b/components/autofill/core/browser/browser_autofill_manager.cc
index ef17b0fd..06f61b2 100644
--- a/components/autofill/core/browser/browser_autofill_manager.cc
+++ b/components/autofill/core/browser/browser_autofill_manager.cc
@@ -62,7 +62,6 @@
 #include "components/autofill/core/browser/autofill_browser_util.h"
 #include "components/autofill/core/browser/autofill_client.h"
 #include "components/autofill/core/browser/autofill_compose_delegate.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_experiments.h"
 #include "components/autofill/core/browser/autofill_external_delegate.h"
 #include "components/autofill/core/browser/autofill_field.h"
@@ -78,6 +77,9 @@
 #include "components/autofill/core/browser/data_model/borrowed_transliterator.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/autofill/core/browser/data_model/phone_number.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/field_type_utils.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/filling/addresses/field_filling_address_util.h"
@@ -104,7 +106,6 @@
 #include "components/autofill/core/browser/payments/credit_card_access_manager.h"
 #include "components/autofill/core/browser/payments_data_manager.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/browser/profile_token_quality.h"
 #include "components/autofill/core/browser/suggestions/addresses/address_suggestion_generator.h"
 #include "components/autofill/core/browser/suggestions/payments/payments_suggestion_generator.h"
 #include "components/autofill/core/browser/suggestions/suggestions_context.h"
@@ -112,7 +113,6 @@
 #include "components/autofill/core/browser/ui/suggestion.h"
 #include "components/autofill/core/browser/ui/suggestion_hiding_reason.h"
 #include "components/autofill/core/browser/ui/suggestion_type.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/aliases.h"
 #include "components/autofill/core/common/autocomplete_parsing_util.h"
 #include "components/autofill/core/common/autofill_clock.h"
@@ -842,8 +842,8 @@
 
     DeterminePossibleFieldTypesForUpload(
         std::move(copied_profiles), std::move(copied_credit_cards),
-        client().GetVotesUploader().last_unlocked_credit_card_cvc_,
-        client().GetAppLocale(), submitted_form.get());
+        last_unlocked_credit_card_cvc_, client().GetAppLocale(),
+        submitted_form.get());
 
     delegate->MaybeImportForm(
         std::move(submitted_form),
@@ -909,7 +909,8 @@
   client().GetVotesUploader().MaybeStartVoteUploadProcess(
       std::move(submitted_form),
       /*observed_submission=*/true, GetCurrentPageLanguage(),
-      metrics_->initial_interaction_timestamp, driver().GetPageUkmSourceId());
+      metrics_->initial_interaction_timestamp, last_unlocked_credit_card_cvc_,
+      driver().GetPageUkmSourceId());
 }
 
 void BrowserAutofillManager::UpdatePendingForm(const FormData& form) {
@@ -944,7 +945,8 @@
   client().GetVotesUploader().MaybeStartVoteUploadProcess(
       std::move(upload_form),
       /*observed_submission=*/false, GetCurrentPageLanguage(),
-      metrics_->initial_interaction_timestamp, driver().GetPageUkmSourceId());
+      metrics_->initial_interaction_timestamp, last_unlocked_credit_card_cvc_,
+      driver().GetPageUkmSourceId());
 }
 
 void BrowserAutofillManager::LogSubmissionMetrics(
@@ -1177,13 +1179,6 @@
     autofill_field->set_was_focused(true);
   }
 
-  // Once the user triggers autofill from the context menu, this event is
-  // recorded, because the IPH configuration limits how many times the IPH can
-  // be shown.
-  if (IsAutofillManuallyTriggered(trigger_source)) {
-    client().NotifyIphFeatureUsed(AutofillClient::IphFeature::kManualFallback);
-  }
-
   const FormFieldData& field = CHECK_DEREF(form.FindFieldByGlobalId(field_id));
   external_delegate_->OnQuery(form, field, caret_bounds, trigger_source,
                               /*update_datalist=*/true);
@@ -1426,11 +1421,6 @@
     return;
   }
 
-  if (should_offer_other_suggestions) {
-    MaybeShowIphForManualFallback(field, autofill_field, trigger_source,
-                                  context.suppress_reason);
-  }
-
   // Whether or not to request single field form fill suggestions.
   const bool should_offer_single_field_form_fill =
       should_offer_other_suggestions &&
@@ -1569,45 +1559,6 @@
                           std::nullopt);
 }
 
-void BrowserAutofillManager::MaybeShowIphForManualFallback(
-    const FormFieldData& field,
-    const AutofillField* autofill_field,
-    AutofillSuggestionTriggerSource trigger_source,
-    SuppressReason suppress_reason) {
-  if (trigger_source ==
-      AutofillSuggestionTriggerSource::kTextareaFocusedWithoutClick) {
-    return;
-  }
-  if (suppress_reason != SuppressReason::kAutocompleteUnrecognized) {
-    return;
-  }
-  if (!autofill_field) {
-    return;
-  }
-  if (FieldTypeGroupToFormType(autofill_field->Type().group()) !=
-      FormType::kAddressForm) {
-    return;
-  }
-  if (std::ranges::none_of(client()
-                               .GetPersonalDataManager()
-                               .address_data_manager()
-                               .GetProfiles(),
-                           [type = autofill_field->Type().GetStorableType()](
-                               const AutofillProfile* profile) {
-                             return profile->HasInfo(type);
-                           })) {
-    return;
-  }
-
-  if (!base::FeatureList::IsEnabled(
-          features::kAutofillEnableManualFallbackIPH)) {
-    return;
-  }
-
-  client().ShowAutofillFieldIphForFeature(
-      field, AutofillClient::IphFeature::kManualFallback);
-}
-
 void BrowserAutofillManager::OnGenerateSuggestionsComplete(
     const FormData& form,
     const FormFieldData& field,
@@ -1682,8 +1633,8 @@
     return;
   }
   form_filler_->FillOrPreviewForm(action_persistence, form, &profile,
-                                  form_structure, autofill_field,
-                                  trigger_source);
+                                  CHECK_DEREF(form_structure),
+                                  CHECK_DEREF(autofill_field), trigger_source);
 }
 
 void BrowserAutofillManager::FillOrPreviewFormWithPredictionImprovements(
@@ -1844,9 +1795,9 @@
                                &autofill_field)) {
       return;
     }
-    form_filler_->FillOrPreviewForm(action_persistence, form, &credit_card,
-                                    form_structure, autofill_field,
-                                    trigger_source, /*is_refill=*/false);
+    form_filler_->FillOrPreviewForm(
+        action_persistence, form, &credit_card, CHECK_DEREF(form_structure),
+        CHECK_DEREF(autofill_field), trigger_source, /*is_refill=*/false);
   }
 }
 
@@ -2216,7 +2167,7 @@
   DCHECK(!pending_form_data_);
 
   four_digit_combinations_in_dom_.clear();
-  client().GetVotesUploader().last_unlocked_credit_card_cvc_.clear();
+  last_unlocked_credit_card_cvc_.clear();
   if (touch_to_fill_delegate_) {
     touch_to_fill_delegate_->Reset();
   }
@@ -2536,8 +2487,7 @@
 
 void BrowserAutofillManager::OnCreditCardFetchedSuccessfully(
     const CreditCard& credit_card) {
-  client().GetVotesUploader().last_unlocked_credit_card_cvc_ =
-      credit_card.cvc();
+  last_unlocked_credit_card_cvc_ = credit_card.cvc();
   // If the synced down card is a virtual card or a server card enrolled in
   // runtime retrieval, let the client know so that it can show the UI to help
   // user to manually fill the form, if needed.
diff --git a/components/autofill/core/browser/browser_autofill_manager.h b/components/autofill/core/browser/browser_autofill_manager.h
index 800559da..7c6e8f5 100644
--- a/components/autofill/core/browser/browser_autofill_manager.h
+++ b/components/autofill/core/browser/browser_autofill_manager.h
@@ -561,14 +561,6 @@
       OnGenerateSuggestionsCallback callback,
       std::vector<std::vector<Suggestion>> suggestion_lists);
 
-  // Displays IPH for manual fallbacks if the form can be autofilled and the
-  // user has profiles which can fill the current field.
-  void MaybeShowIphForManualFallback(
-      const FormFieldData& field,
-      const AutofillField* autofill_field,
-      AutofillSuggestionTriggerSource trigger_source,
-      SuppressReason suppress_reason);
-
   // Triggered when the user undoes the filling of an address profile using an
   // email override.
   void OnEmailOverrideUndone(const std::u16string& original_email,
@@ -693,7 +685,7 @@
   // Helper class to autofill forms and fields. Do not use directly, use
   // form_filler() instead, because tests inject test objects.
   std::unique_ptr<FormFiller> form_filler_ =
-      std::make_unique<FormFiller>(*this, log_manager());
+      std::make_unique<FormFiller>(*this);
 
   // Contains a list of four digit combinations that were found in the webpage
   // DOM. Populated after a standalone cvc field is processed on a form. Used to
@@ -701,6 +693,8 @@
   // on file case.
   std::vector<std::string> four_digit_combinations_in_dom_;
 
+  std::u16string last_unlocked_credit_card_cvc_;
+
   base::WeakPtrFactory<BrowserAutofillManager> weak_ptr_factory_{this};
 };
 
diff --git a/components/autofill/core/browser/browser_autofill_manager_unittest.cc b/components/autofill/core/browser/browser_autofill_manager_unittest.cc
index 337ae3d6..cff58d26 100644
--- a/components/autofill/core/browser/browser_autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/browser_autofill_manager_unittest.cc
@@ -48,6 +48,9 @@
 #include "components/autofill/core/browser/data_model/autofill_profile_test_api.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/autofill/core/browser/data_model/iban.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality_test_api.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/filling_product.h"
 #include "components/autofill/core/browser/form_import/form_data_importer_test_api.h"
@@ -69,8 +72,6 @@
 #include "components/autofill/core/browser/payments/test_payments_network_interface.h"
 #include "components/autofill/core/browser/payments_data_manager.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/browser/profile_token_quality.h"
-#include "components/autofill/core/browser/profile_token_quality_test_api.h"
 #include "components/autofill/core/browser/strike_databases/payments/test_credit_card_save_strike_database.h"
 #include "components/autofill/core/browser/suggestions/addresses/address_suggestion_generator.h"
 #include "components/autofill/core/browser/suggestions/payments/payments_suggestion_generator.h"
@@ -85,7 +86,6 @@
 #include "components/autofill/core/browser/ui/suggestion.h"
 #include "components/autofill/core/browser/ui/suggestion_test_helpers.h"
 #include "components/autofill/core/browser/ui/suggestion_type.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autocomplete_parsing_util.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_payments_features.h"
diff --git a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc
index 3594e95..b728f8b 100644
--- a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc
+++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc
@@ -19,12 +19,12 @@
 #include "base/types/optional_ref.h"
 #include "components/autofill/core/browser/crowdsourcing/randomized_encoder.h"
 #include "components/autofill/core/browser/crowdsourcing/server_prediction_overrides.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/form_structure_rationalizer.h"
 #include "components/autofill/core/browser/form_structure_sectioning_util.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics.h"
 #include "components/autofill/core/browser/metrics/log_event.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_internals/log_message.h"
 #include "components/autofill/core/common/autofill_internals/logging_scope.h"
diff --git a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.cc b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.cc
index 130d8f6c..5a5b280 100644
--- a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.cc
+++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.cc
@@ -678,20 +678,16 @@
 
 AutofillCrowdsourcingManager::QueryResponse::~QueryResponse() = default;
 
-AutofillCrowdsourcingManager::AutofillCrowdsourcingManager(AutofillClient* client,
-                                                 version_info::Channel channel,
-                                                 LogManager* log_manager)
-    : AutofillCrowdsourcingManager(client,
-                              GetAPIKeyForUrl(channel),
-                              log_manager) {}
+AutofillCrowdsourcingManager::AutofillCrowdsourcingManager(
+    AutofillClient* client,
+    version_info::Channel channel)
+    : AutofillCrowdsourcingManager(client, GetAPIKeyForUrl(channel)) {}
 
 AutofillCrowdsourcingManager::AutofillCrowdsourcingManager(
     AutofillClient* client,
-    std::string api_key,
-    LogManager* log_manager)
+    std::string api_key)
     : client_(client),
       api_key_(std::move(api_key)),
-      log_manager_(log_manager),
       autofill_server_url_(GetAutofillServerURL()),
       throttle_reset_period_(GetThrottleResetPeriod()),
       max_form_cache_size_(kAutofillCrowdsourcingManagerMaxFormCacheSize),
@@ -750,8 +746,9 @@
 
   std::string query_data;
   if (CheckCacheForQueryRequest(queried_form_signatures, &query_data)) {
-    LOG_AF(log_manager_) << LoggingScope::kAutofillServer
-                         << LogMessage::kCachedAutofillQuery << Br{} << query;
+    LOG_AF(client_->GetLogManager())
+        << LoggingScope::kAutofillServer << LogMessage::kCachedAutofillQuery
+        << Br{} << query;
     if (scoped_callback_runner) {
       std::move(scoped_callback_runner)
           .Release()
@@ -761,9 +758,9 @@
     return true;
   }
 
-  LOG_AF(log_manager_) << LoggingScope::kAutofillServer
-                       << LogMessage::kSendAutofillQuery << Br{}
-                       << "Signatures: " << query;
+  LOG_AF(client_->GetLogManager())
+      << LoggingScope::kAutofillServer << LogMessage::kSendAutofillQuery << Br{}
+      << "Signatures: " << query;
   return StartRequest(FormRequestData{
       .callback = std::move(scoped_callback_runner),
       .form_signatures = std::move(queried_form_signatures),
@@ -817,7 +814,8 @@
 
   // For debugging purposes, even throttled uploads are logged. If no log
   // manager is active, the function can exit early for throttled uploads.
-  const bool needs_logging = log_manager_ && log_manager_->IsLoggingActive();
+  LogManager* log_manager = client_->GetLogManager();
+  const bool needs_logging = log_manager && log_manager->IsLoggingActive();
   if (!needs_logging && !allow_upload)
     return false;
 
@@ -828,10 +826,10 @@
       return false;
     }
 
-    LOG_AF(log_manager_) << LoggingScope::kAutofillServer
-                         << LogMessage::kSendAutofillUpload << Br{}
-                         << "Allow upload?: " << allow_upload << Br{}
-                         << "Data: " << Br{} << upload;
+    LOG_AF(log_manager) << LoggingScope::kAutofillServer
+                        << LogMessage::kSendAutofillUpload << Br{}
+                        << "Allow upload?: " << allow_upload << Br{}
+                        << "Data: " << Br{} << upload;
 
     if (!allow_upload)
       return false;
diff --git a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h
index adf0809..6851bbd 100644
--- a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h
+++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h
@@ -31,7 +31,6 @@
 namespace autofill {
 
 class AutofillClient;
-class LogManager;
 
 inline constexpr size_t kMaxQueryGetSize = 10240;  // 10 KiB
 
@@ -56,8 +55,7 @@
   // `channel` determines the value for the the Google-API-key HTTP header and
   // whether raw metadata uploading is enabled.
   AutofillCrowdsourcingManager(AutofillClient* client,
-                          version_info::Channel channel,
-                          LogManager* log_manager);
+                               version_info::Channel channel);
 
   virtual ~AutofillCrowdsourcingManager();
 
@@ -106,9 +104,7 @@
   static int GetMaxServerAttempts();
 
  protected:
-  AutofillCrowdsourcingManager(AutofillClient* client,
-                               std::string api_key,
-                               LogManager* log_manager);
+  AutofillCrowdsourcingManager(AutofillClient* client, std::string api_key);
 
   // Gets the length of the payload from request data. Used to simulate
   // different payload sizes when testing without the need for data. Do not use
@@ -162,9 +158,6 @@
   // Callback function to retrieve API key.
   const std::string api_key_;
 
-  // Access to leave log messages for chrome://autofill-internals, may be null.
-  const raw_ptr<LogManager> log_manager_;
-
   // The autofill server URL root: scheme://host[:port]/path excluding the
   // final path component for the request and the query params.
   const GURL autofill_server_url_;
diff --git a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager_test_api.h b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager_test_api.h
index be5aa4a..f329643 100644
--- a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager_test_api.h
+++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager_test_api.h
@@ -21,9 +21,7 @@
   static std::unique_ptr<AutofillCrowdsourcingManager> CreateManagerForApiKey(
       AutofillClient* client,
       const std::string& api_key) {
-    return base::WrapUnique(
-        new AutofillCrowdsourcingManager(client, api_key,
-                                         /*log_manager=*/nullptr));
+    return base::WrapUnique(new AutofillCrowdsourcingManager(client, api_key));
   }
 
   explicit AutofillCrowdsourcingManagerTestApi(
diff --git a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager_unittest.cc b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager_unittest.cc
index b1b25d0..859f65c2 100644
--- a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager_unittest.cc
+++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h"
 
+#include <array>
 #include <list>
 #include <memory>
 #include <string_view>
@@ -179,10 +180,7 @@
   AutofillCrowdsourcingManagerWithCustomPayloadSize(AutofillClient* client,
                                                     const std::string& api_key,
                                                     size_t length)
-      : AutofillCrowdsourcingManager(client,
-                                     api_key,
-                                     /*log_manager=*/nullptr),
-        length_(length) {}
+      : AutofillCrowdsourcingManager(client, api_key), length_(length) {}
   ~AutofillCrowdsourcingManagerWithCustomPayloadSize() override = default;
 
  protected:
@@ -343,7 +341,7 @@
       /*is_password_manager_upload=*/false));
 
   // Server responseses - returned  out of sequence.
-  const char* response_contents[] = {
+  auto response_contents = std::to_array<const char*>({
       "<autofillqueryresponse>"
       "<field autofilltype=\"86\" />"
       "<field autofilltype=\"3\" />"
@@ -354,7 +352,7 @@
       "</autofillqueryresponse>",
       "",
       "<html></html>",
-  };
+  });
 
   // Request 1: Successful upload.
   request = url_loader_factory().GetPendingRequest(1);
@@ -914,7 +912,7 @@
 
   test_api(crowdsourcing_manager()).set_max_form_cache_size(2);
 
-  const char* response_contents[] = {
+  auto response_contents = std::to_array<const char*>({
       "<autofillqueryresponse>"
       "<field autofilltype=\"0\" />"
       "<field autofilltype=\"3\" />"
@@ -933,7 +931,7 @@
       "<field autofilltype=\"9\" />"
       "<field autofilltype=\"0\" />"
       "</autofillqueryresponse>",
-  };
+  });
 
   base::HistogramTester histogram;
   // Request with id 0.
@@ -1159,7 +1157,7 @@
 
     ScopedActiveAutofillExperiments scoped_active_autofill_experiments;
     AutofillCrowdsourcingManager crowdsourcing_manager(
-        &client(), version_info::Channel::UNKNOWN, nullptr);
+        &client(), version_info::Channel::UNKNOWN);
     bool succeeded = crowdsourcing_manager.StartQueryRequest(
         ToRawPointerVector(form_structures), driver_.GetIsolationInfo(),
         base::BindOnce(
@@ -1182,7 +1180,7 @@
 
     ScopedActiveAutofillExperiments scoped_active_autofill_experiments;
     AutofillCrowdsourcingManager crowdsourcing_manager(
-        &client(), version_info::Channel::UNKNOWN, nullptr);
+        &client(), version_info::Channel::UNKNOWN);
 
     std::vector<AutofillUploadContents> upload_contents = EncodeUploadRequest(
         form, available_field_types, login_form_signature, observed_submission);
@@ -1229,7 +1227,7 @@
 
 TEST_P(AutofillServerCommunicationTest, IsEnabled) {
   AutofillCrowdsourcingManager crowdsourcing_manager(
-      &client(), version_info::Channel::UNKNOWN, nullptr);
+      &client(), version_info::Channel::UNKNOWN);
   EXPECT_EQ(crowdsourcing_manager.IsEnabled(), GetParam() != DISABLED);
 }
 
@@ -1243,7 +1241,7 @@
 
 TEST_P(AutofillServerCommunicationTest, Upload) {
   AutofillCrowdsourcingManager crowdsourcing_manager(
-      &client(), version_info::Channel::UNKNOWN, nullptr);
+      &client(), version_info::Channel::UNKNOWN);
   EXPECT_EQ(GetParam() != DISABLED,
             SendUploadRequest(
                 FormStructure(
@@ -1465,7 +1463,7 @@
 
   // Setup the form structures to query.
   AutofillCrowdsourcingManager crowdsourcing_manager(
-      &client(), version_info::Channel::UNKNOWN, nullptr);
+      &client(), version_info::Channel::UNKNOWN);
   std::vector<std::unique_ptr<FormStructure>> form_structures;
   form_structures.push_back(std::make_unique<FormStructure>(form));
 
@@ -1549,7 +1547,7 @@
   test_api(form).Append(field);
 
   AutofillCrowdsourcingManager crowdsourcing_manager(
-      &client(), version_info::Channel::UNKNOWN, nullptr);
+      &client(), version_info::Channel::UNKNOWN);
   FormStructure form_structure(form);
   form_structure.set_current_page_language(LanguageCode("fr"));
   SetCorrectFieldHostFormSignatures(form_structure);
@@ -1627,7 +1625,7 @@
   ASSERT_NE(DISABLED, GetParam());
 
   AutofillCrowdsourcingManager crowdsourcing_manager(
-      &client(), version_info::Channel::UNKNOWN, nullptr);
+      &client(), version_info::Channel::UNKNOWN);
   FormStructure form_structure(
       test::GetFormData({.fields = {{.role = NAME_FIRST},
                                     {.role = NAME_LAST},
@@ -1744,7 +1742,7 @@
       {{switches::kAutofillUploadThrottlingPeriodInDays, "16"}});
 
   AutofillCrowdsourcingManager crowdsourcing_manager(
-      &client(), version_info::Channel::UNKNOWN, nullptr);
+      &client(), version_info::Channel::UNKNOWN);
   SubmissionSource submission_source = SubmissionSource::FORM_SUBMISSION;
 
   FormStructure form_structure(
@@ -1797,7 +1795,7 @@
   ASSERT_NE(DISABLED, GetParam());
 
   AutofillCrowdsourcingManager crowdsourcing_manager(
-      &client(), version_info::Channel::UNKNOWN, nullptr);
+      &client(), version_info::Channel::UNKNOWN);
   SubmissionSource submission_source = SubmissionSource::FORM_SUBMISSION;
 
   FormStructure form_structure(
diff --git a/components/autofill/core/browser/crowdsourcing/determine_possible_field_types.cc b/components/autofill/core/browser/crowdsourcing/determine_possible_field_types.cc
index 43b4b16..3dab59c9 100644
--- a/components/autofill/core/browser/crowdsourcing/determine_possible_field_types.cc
+++ b/components/autofill/core/browser/crowdsourcing/determine_possible_field_types.cc
@@ -12,10 +12,10 @@
 #include "components/autofill/core/browser/crowdsourcing/disambiguate_possible_field_types.h"
 #include "components/autofill/core/browser/data_model/address.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/field_type_utils.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/form_structure.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_regex_constants.h"
 #include "components/autofill/core/common/autofill_regexes.h"
diff --git a/components/autofill/core/browser/crowdsourcing/mock_autofill_crowdsourcing_manager.cc b/components/autofill/core/browser/crowdsourcing/mock_autofill_crowdsourcing_manager.cc
index 5d8b383b6..d34af8c 100644
--- a/components/autofill/core/browser/crowdsourcing/mock_autofill_crowdsourcing_manager.cc
+++ b/components/autofill/core/browser/crowdsourcing/mock_autofill_crowdsourcing_manager.cc
@@ -12,8 +12,7 @@
     AutofillClient* client,
     LogManager* log_manager)
     : AutofillCrowdsourcingManager(client,
-                                   /*api_key=*/"",
-                                   log_manager) {
+                                   /*api_key=*/"") {
   ON_CALL(*this, StartQueryRequest)
       .WillByDefault(
           [](const auto&, const auto&,
diff --git a/components/autofill/core/browser/crowdsourcing/test_votes_uploader.cc b/components/autofill/core/browser/crowdsourcing/test_votes_uploader.cc
index 159d2c0..582979f 100644
--- a/components/autofill/core/browser/crowdsourcing/test_votes_uploader.cc
+++ b/components/autofill/core/browser/crowdsourcing/test_votes_uploader.cc
@@ -20,6 +20,7 @@
     base::TimeTicks initial_interaction_timestamp,
     base::TimeTicks submission_timestamp,
     bool observed_submission,
+    const std::u16string& last_unlocked_credit_card_cvc,
     const ukm::SourceId source_id) {
   submitted_form_signature_ = submitted_form->FormSignatureAsStr();
 
@@ -50,7 +51,8 @@
 
   VotesUploader::UploadVote(std::move(submitted_form),
                             initial_interaction_timestamp, submission_timestamp,
-                            observed_submission, source_id);
+                            observed_submission, last_unlocked_credit_card_cvc,
+                            source_id);
 }
 
 bool TestVotesUploader::MaybeStartVoteUploadProcess(
@@ -58,18 +60,20 @@
     bool observed_submission,
     LanguageCode current_page_language,
     base::TimeTicks initial_interaction_timestamp,
+    const std::u16string& last_unlocked_credit_card_cvc,
     ukm::SourceId ukm_source_id) {
   if (VotesUploader::MaybeStartVoteUploadProcess(
           std::move(form), observed_submission, current_page_language,
-          initial_interaction_timestamp, ukm_source_id)) {
+          initial_interaction_timestamp, last_unlocked_credit_card_cvc,
+          ukm_source_id)) {
     // The purpose of this runloop is to ensure that the field type
     // determination finishes.
     base::RunLoop run_loop;
     // Since the `vote_upload_task_runner()` is a `base::SequencedTaskRunner`,
     // the `run_loop` is quit only after the task and reply posted by
     // MaybeStartVoteUploadProcess() is finished.
-    test_api(*this).vote_upload_task_runner().PostTaskAndReply(
-        FROM_HERE, base::DoNothing(), run_loop.QuitClosure());
+    test_api(*this).task_runner().PostTaskAndReply(FROM_HERE, base::DoNothing(),
+                                                   run_loop.QuitClosure());
     run_loop.Run();
     return true;
   }
diff --git a/components/autofill/core/browser/crowdsourcing/test_votes_uploader.h b/components/autofill/core/browser/crowdsourcing/test_votes_uploader.h
index 8bd12ec9..9bfb69b 100644
--- a/components/autofill/core/browser/crowdsourcing/test_votes_uploader.h
+++ b/components/autofill/core/browser/crowdsourcing/test_votes_uploader.h
@@ -40,12 +40,14 @@
       bool observed_submission,
       LanguageCode current_page_language,
       base::TimeTicks initial_interaction_timestamp,
+      const std::u16string& last_unlocked_credit_card_cvc,
       ukm::SourceId ukm_source_id) override;
 
   void UploadVote(std::unique_ptr<FormStructure> submitted_form,
                   base::TimeTicks initial_interaction_timestamp,
                   base::TimeTicks submission_timestamp,
                   bool observed_submission,
+                  const std::u16string& last_unlocked_credit_card_cvc,
                   const ukm::SourceId source_id) override;
 
   const std::string& submitted_form_signature() {
diff --git a/components/autofill/core/browser/crowdsourcing/votes_uploader.cc b/components/autofill/core/browser/crowdsourcing/votes_uploader.cc
index 601b7452..15322dd 100644
--- a/components/autofill/core/browser/crowdsourcing/votes_uploader.cc
+++ b/components/autofill/core/browser/crowdsourcing/votes_uploader.cc
@@ -66,7 +66,7 @@
 
 }  // namespace
 
-struct VotesUploader::QueuedVote {
+struct VotesUploader::PendingVote {
   LocalFrameToken frame_of_form;
   FormSignature form_signature;
   base::OnceClosure upload_vote;
@@ -78,24 +78,24 @@
 
 VotesUploader::~VotesUploader() = default;
 
-base::SequencedTaskRunner& VotesUploader::vote_upload_task_runner() {
-  if (!vote_upload_task_runner_) {
+base::SequencedTaskRunner& VotesUploader::task_runner() {
+  if (!task_runner_) {
     // If the priority is BEST_EFFORT, the task can be preempted, which is
     // thought to cause high memory usage (as memory is retained by the task
     // while it is preempted), https://crbug.com/974249
-    vote_upload_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
+    task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
         {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
   }
-  return *vote_upload_task_runner_;
+  return *task_runner_;
 }
 
-void VotesUploader::WipeQueuedVotesForForm(FormSignature form_signature) {
-  std::erase_if(queued_votes_, [form_signature](const QueuedVote& vote) {
+void VotesUploader::WipePendingVotesForForm(FormSignature form_signature) {
+  std::erase_if(pending_votes_, [form_signature](const PendingVote& vote) {
     return vote.form_signature == form_signature;
   });
 }
 
-void VotesUploader::FlushQueuedVotesForFrame(const LocalFrameToken& frame) {
+void VotesUploader::FlushPendingVotesForFrame(const LocalFrameToken& frame) {
   // Removes from `list` all elements that satisfy `pred` and returns them
   // in a separate list.
   auto extract_if = []<typename T>(std::list<T>& list, auto pred) {
@@ -107,19 +107,20 @@
     return removed;
   };
 
-  // We remove the callbacks from `queued_votes_` *before* invoking them.
-  // The motivation is that we don't want to loop over `queued_votes_`
+  // We remove the callbacks from `pending_votes_` *before* invoking them.
+  // The motivation is that we don't want to loop over `pending_votes_`
   // and call member functions in the loop's body for memory safety reasons.
-  auto is_from_frame = [&](const QueuedVote& vote) {
+  auto is_from_frame = [&](const PendingVote& vote) {
     return vote.frame_of_form == frame;
   };
-  size_t num_old_queued_votes = queued_votes_.size();
-  std::list<QueuedVote> votes_of_frame =
-      extract_if(queued_votes_, is_from_frame);
-  DCHECK_EQ(queued_votes_.size() + votes_of_frame.size(), num_old_queued_votes);
+  size_t num_old_queued_votes = pending_votes_.size();
+  std::list<PendingVote> votes_of_frame =
+      extract_if(pending_votes_, is_from_frame);
+  DCHECK_EQ(pending_votes_.size() + votes_of_frame.size(),
+            num_old_queued_votes);
   DCHECK(std::ranges::all_of(votes_of_frame, is_from_frame));
-  DCHECK(std::ranges::none_of(queued_votes_, is_from_frame));
-  for (QueuedVote& vote : votes_of_frame) {
+  DCHECK(std::ranges::none_of(pending_votes_, is_from_frame));
+  for (PendingVote& vote : votes_of_frame) {
     std::move(vote.upload_vote).Run();
   }
 }
@@ -142,17 +143,16 @@
     AutofillDriver& driver,
     AutofillDriver::LifecycleState old_state,
     AutofillDriver::LifecycleState new_state) {
-  // Calls FlushQueuedVotes() after the currently pending
+  // Calls FlushPendingVotes() after the currently pending
   // DeterminePossibleFieldTypesForUpload() / OnFieldTypesDetermined() tasks are
   // finished.
   auto delayed_flush_queued_votes_for_frame =
       [this](const LocalFrameToken& frame) {
-        // Since vote_upload_task_runner() is a sequenced task runner,
-        // FlushQueuedVotes() will be called after any pending tasks and their
-        // replies.
-        vote_upload_task_runner().PostTaskAndReply(
+        // Since task_runner() is a sequenced task runner, FlushPendingVotes()
+        // will be called after any pending tasks and their replies.
+        task_runner().PostTaskAndReply(
             FROM_HERE, base::DoNothing(),
-            base::BindOnce(&VotesUploader::FlushQueuedVotesForFrame,
+            base::BindOnce(&VotesUploader::FlushPendingVotesForFrame,
                            weak_ptr_factory_.GetWeakPtr(), frame));
       };
 
@@ -182,7 +182,7 @@
 
   if (old_state == kPendingReset) {
     // Case (3): The was reset.
-    FlushQueuedVotesForFrame(driver.GetFrameToken());
+    FlushPendingVotesForFrame(driver.GetFrameToken());
   }
 }
 
@@ -191,6 +191,7 @@
     bool observed_submission,
     LanguageCode current_page_language,
     base::TimeTicks initial_interaction_timestamp,
+    const std::u16string& last_unlocked_credit_card_cvc,
     ukm::SourceId ukm_source_id) {
   // Only upload server statistics and UMA metrics if at least some local data
   // is available to use as a baseline.
@@ -236,7 +237,7 @@
   // TODO(crbug.com/368306576): Bound the size of `copied_profiles` and
   // `copied_credit_cards` by `kMaxDataConsideredForPossibleTypes` and make
   // the call to DeterminePossibleFieldTypesForUpload() synchronous.
-  vote_upload_task_runner().PostTaskAndReplyWithResult(
+  task_runner().PostTaskAndReplyWithResult(
       FROM_HERE,
       base::BindOnce(
           [](const std::vector<AutofillProfile>& profiles,
@@ -250,12 +251,13 @@
             return form;
           },
           std::move(copied_profiles), std::move(copied_credit_cards),
-          last_unlocked_credit_card_cvc_, client_->GetAppLocale(),
+          last_unlocked_credit_card_cvc, client_->GetAppLocale(),
           std::move(form)),
       base::BindOnce(&VotesUploader::OnFieldTypesDetermined,
                      weak_ptr_factory_.GetWeakPtr(),
                      initial_interaction_timestamp, base::TimeTicks::Now(),
-                     observed_submission, ukm_source_id));
+                     observed_submission, last_unlocked_credit_card_cvc,
+                     ukm_source_id));
   return true;
 }
 
@@ -263,45 +265,50 @@
     base::TimeTicks initial_interaction_timestamp,
     base::TimeTicks submission_timestamp,
     bool observed_submission,
+    const std::u16string& last_unlocked_credit_card_cvc,
     ukm::SourceId ukm_source_id,
     std::unique_ptr<FormStructure> form) {
   LocalFrameToken frame = form->global_id().frame_token;
-  WipeQueuedVotesForForm(form->form_signature());
+  WipePendingVotesForForm(form->form_signature());
   if (observed_submission) {
     UploadVote(std::move(form), initial_interaction_timestamp,
-               submission_timestamp, observed_submission, ukm_source_id);
-    FlushQueuedVotesForFrame(frame);
+               submission_timestamp, observed_submission,
+               last_unlocked_credit_card_cvc, ukm_source_id);
+    FlushPendingVotesForFrame(frame);
   } else {
-    TruncateQueueIfNecessary();
-    queued_votes_.push_front(
+    FlushOldestPendingVotesIfNecessary();
+    pending_votes_.push_front(
         {.frame_of_form = frame,
          .form_signature = form->form_signature(),
          .upload_vote = base::BindOnce(
              &VotesUploader::UploadVote, weak_ptr_factory_.GetWeakPtr(),
              std::move(form), initial_interaction_timestamp,
-             submission_timestamp, observed_submission, ukm_source_id)});
+             submission_timestamp, observed_submission,
+             last_unlocked_credit_card_cvc, ukm_source_id)});
   }
 }
 
-void VotesUploader::TruncateQueueIfNecessary() {
-  // Entries in queued_votes_ are submitted after navigations or form
+void VotesUploader::FlushOldestPendingVotesIfNecessary() {
+  // Entries in pending_votes_ are submitted after navigations or form
   // submissions. To reduce the risk of collecting too much data that is not
   // send, we allow only `kMaxEntriesInQueue` entries. Anything in excess will
   // be sent when the queue becomes to long.
   constexpr int kMaxEntriesInQueue = 10;
-  while (queued_votes_.size() >= kMaxEntriesInQueue) {
+  while (pending_votes_.size() >= kMaxEntriesInQueue) {
     base::OnceCallback oldest_callback =
-        std::move(queued_votes_.back().upload_vote);
-    queued_votes_.pop_back();
+        std::move(pending_votes_.back().upload_vote);
+    pending_votes_.pop_back();
     std::move(oldest_callback).Run();
   }
 }
 
-void VotesUploader::UploadVote(std::unique_ptr<FormStructure> submitted_form,
-                               base::TimeTicks initial_interaction_timestamp,
-                               base::TimeTicks submission_timestamp,
-                               bool observed_submission,
-                               ukm::SourceId ukm_source_id) {
+void VotesUploader::UploadVote(
+    std::unique_ptr<FormStructure> submitted_form,
+    base::TimeTicks initial_interaction_timestamp,
+    base::TimeTicks submission_timestamp,
+    bool observed_submission,
+    const std::u16string& last_unlocked_credit_card_cvc,
+    ukm::SourceId ukm_source_id) {
   auto count_types = [&submitted_form](FormType type) {
     return base::ranges::count_if(
         submitted_form->fields(),
@@ -372,7 +379,7 @@
     card->GetNonEmptyTypes(client_->GetAppLocale(), &non_empty_types);
   }
   // As CVC is not stored, treat it separately.
-  if (!last_unlocked_credit_card_cvc_.empty() ||
+  if (!last_unlocked_credit_card_cvc.empty() ||
       non_empty_types.contains(CREDIT_CARD_NUMBER)) {
     non_empty_types.insert(CREDIT_CARD_VERIFICATION_CODE);
   }
diff --git a/components/autofill/core/browser/crowdsourcing/votes_uploader.h b/components/autofill/core/browser/crowdsourcing/votes_uploader.h
index 6dbb6bd3..af37466 100644
--- a/components/autofill/core/browser/crowdsourcing/votes_uploader.h
+++ b/components/autofill/core/browser/crowdsourcing/votes_uploader.h
@@ -39,7 +39,8 @@
 // VotesUploader enqueues votes that are cast before form submission are
 // enqueued. New votes for a form signature replace already-enqueued ones for
 // that signature. Enqueued votes are flushed by BrowserAutofillManager when it
-// dies or is reset.
+// dies or is reset. Therefore, votes are called "pending" while they are in the
+// queue.
 //
 //   MaybeStartVoteUploadProcess()◄─────────BrowserAutofillManager
 //       │
@@ -58,7 +59,7 @@
 //       │else                                   │
 //       │                                       │
 //       ▼                                       │
-//   Store QueuedVote, which is uploaded when    │
+//   Store PendingVote, which is uploaded when   │
 //   - a submission happens in the frame;        │
 //   - the frame becomes inactive                │
 //     kAutofillVoteWhenInactive is enabled;     │
@@ -66,7 +67,7 @@
 //   - the frame is deleted;                     │
 //   - the queue becomes too large.              │
 //                                               │
-//   QueuedVote::upload_vote                     │
+//   PendingVote::upload_vote                    │
 //       │                                       │
 //       │                                       │
 //       ▼                                       │
@@ -92,11 +93,9 @@
       bool observed_submission,
       LanguageCode current_page_language,
       base::TimeTicks initial_interaction_timestamp,
+      const std::u16string& last_unlocked_credit_card_cvc,
       ukm::SourceId ukm_source_id);
 
-  // TODO(crbug.com/374086145): Remove public member.
-  std::u16string last_unlocked_credit_card_cvc_;
-
  protected:
   // Logs quality metrics, perhaps displays an Autofill survey, and uploads the
   // vote. All these three activities depend on the determined field types.
@@ -112,27 +111,32 @@
                           base::TimeTicks initial_interaction_timestamp,
                           base::TimeTicks submission_timestamp,
                           bool observed_submission,
+                          const std::u16string& last_unlocked_credit_card_cvc,
                           ukm::SourceId ukm_source_id);
 
  private:
   friend class VotesUploaderTestApi;
 
-  struct QueuedVote;
+  struct PendingVote;
 
   // The reply of DeterminePossibleFieldTypesForUpload().
-  // Either calls UploadVote() or stores a QueuedVote.
-  void OnFieldTypesDetermined(base::TimeTicks initial_interaction_timestamp,
-                              base::TimeTicks submission_timestamp,
-                              bool observed_submission,
-                              ukm::SourceId ukm_source_id,
-                              std::unique_ptr<FormStructure> submitted_form);
+  // Either calls UploadVote() or stores a PendingVote.
+  void OnFieldTypesDetermined(
+      base::TimeTicks initial_interaction_timestamp,
+      base::TimeTicks submission_timestamp,
+      bool observed_submission,
+      const std::u16string& last_unlocked_credit_card_cvc,
+      ukm::SourceId ukm_source_id,
+      std::unique_ptr<FormStructure> submitted_form);
 
-  void FlushQueuedVotesForFrame(const LocalFrameToken& frame);
+  // Uploads all pending votes for forms from `frame`.
+  void FlushPendingVotesForFrame(const LocalFrameToken& frame);
 
   // Removes the callbacks for the given `form_signature` without calling them.
-  void WipeQueuedVotesForForm(FormSignature form_signature);
+  void WipePendingVotesForForm(FormSignature form_signature);
 
-  void TruncateQueueIfNecessary();
+  // Uploads the oldest votes if the queue of votes has become too long.
+  void FlushOldestPendingVotesIfNecessary();
 
   // AutofillDriverFactory::Observer:
   void OnAutofillDriverFactoryDestroyed(
@@ -143,32 +147,33 @@
       AutofillDriver::LifecycleState old_state,
       AutofillDriver::LifecycleState new_state) override;
 
-  base::SequencedTaskRunner& vote_upload_task_runner();
+  // Task runner for asynchronously determining possible field types.
+  base::SequencedTaskRunner& task_runner();
 
   const raw_ref<AutofillClient> client_;
 
-  // List of callbacks to be called for sending blur votes. Only one callback is
-  // stored per FormSignature. We rely on FormSignatures rather than
-  // FormGlobalId to send votes for the various signatures of a form while it
-  // evolves (when fields are added or removed). The list of callbacks is
+  // List of pending votes. These votes were cast not when a form submission
+  // happened but, for example, when a form lost focus ("blur votes").
+  //
+  // Only one callback is stored per FormSignature. We rely on FormSignatures
+  // rather than FormGlobalId to send votes for the various signatures of a form
+  // while it evolves (when fields are added or removed). The list of votes is
   // ordered by time of creation: newest elements first. If the list becomes too
-  // long, the oldest queued callbacks are just called and popped removed the
-  // list.
+  // long, the oldest votes are popped from the list and uploaded.
   //
-  // Callbacks are triggered in the following situations:
-  // - We observe a form submission.
-  // - The list becomes to large.
-  //
-  // Callbacks are wiped in the following situations:
-  // - A form is submitted.
-  // - A callback is overridden by a more recent version.
-  std::list<QueuedVote> queued_votes_;
+  // Beware that this (like the other members) must not be accessed from
+  // `task_runner_`.
+  std::list<PendingVote> pending_votes_;
 
-  // This task runner sequentializes calls to
-  // DeterminePossibleFieldTypesForUpload() to ensure that blur votes are
-  // processed before form submission votes. This is important so that a
-  // submission can trigger the upload of blur votes.
-  scoped_refptr<base::SequencedTaskRunner> vote_upload_task_runner_;
+  // Task runner for DeterminePossibleFieldTypesForUpload(). It is important
+  // that this is a *sequenced* task runner for reasons:
+  // - Form submission not only uploads the submission vote but also flushes
+  //   blur votes. For that to work, the blur votes' OnFieldTypesDetermined()
+  //   must be called before the submission vote's OnFieldTypesDetermined().
+  // - When a frame becomes inactive or is reset, pending votes should be
+  //   flushed -- but first, pending DeterminePossibleFieldTypesForUpload()
+  //   calls need to finish.
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
   base::ScopedObservation<AutofillDriverFactory,
                           AutofillDriverFactory::Observer>
diff --git a/components/autofill/core/browser/crowdsourcing/votes_uploader_test_api.cc b/components/autofill/core/browser/crowdsourcing/votes_uploader_test_api.cc
index 9b548df7..3b10d47 100644
--- a/components/autofill/core/browser/crowdsourcing/votes_uploader_test_api.cc
+++ b/components/autofill/core/browser/crowdsourcing/votes_uploader_test_api.cc
@@ -11,15 +11,15 @@
 
 testing::AssertionResult VotesUploaderTestApi::FlushPendingVotes(
     base::TimeDelta timeout) {
-  if (!votes_uploader_->vote_upload_task_runner_) {
+  if (!votes_uploader_->task_runner_) {
     return testing::AssertionFailure()
            << "The BrowserAutofillManager::vote_upload_task_runner_ is not "
               "initialized yet. Maybe you need to wait for a submission?";
   }
   base::test::ScopedRunLoopTimeout run_loop_timeout(FROM_HERE, timeout);
   base::RunLoop run_loop;
-  votes_uploader_->vote_upload_task_runner_->PostTaskAndReply(
-      FROM_HERE, base::DoNothing(), run_loop.QuitClosure());
+  votes_uploader_->task_runner_->PostTaskAndReply(FROM_HERE, base::DoNothing(),
+                                                  run_loop.QuitClosure());
   run_loop.Run();
   return run_loop.AnyQuitCalled()
              ? testing::AssertionSuccess()
diff --git a/components/autofill/core/browser/crowdsourcing/votes_uploader_test_api.h b/components/autofill/core/browser/crowdsourcing/votes_uploader_test_api.h
index eda2a9ee..3057c89 100644
--- a/components/autofill/core/browser/crowdsourcing/votes_uploader_test_api.h
+++ b/components/autofill/core/browser/crowdsourcing/votes_uploader_test_api.h
@@ -17,8 +17,8 @@
   explicit VotesUploaderTestApi(VotesUploader* votes_uploader)
       : votes_uploader_(*votes_uploader) {}
 
-  base::SequencedTaskRunner& vote_upload_task_runner() {
-    return votes_uploader_->vote_upload_task_runner();
+  base::SequencedTaskRunner& task_runner() {
+    return votes_uploader_->task_runner();
   }
 
   // Blocks until all pending votes have been emitted. This fails if either a
diff --git a/components/autofill/core/browser/data_model/address.cc b/components/autofill/core/browser/data_model/address.cc
index f6a176e8..e879403 100644
--- a/components/autofill/core/browser/data_model/address.cc
+++ b/components/autofill/core/browser/data_model/address.cc
@@ -5,6 +5,7 @@
 #include "components/autofill/core/browser/data_model/address.h"
 
 #include <stddef.h>
+
 #include <algorithm>
 #include <memory>
 
@@ -16,13 +17,13 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_field.h"
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/autofill_profile_comparator.h"
 #include "components/autofill/core/browser/data_model/autofill_structured_address_component.h"
 #include "components/autofill/core/browser/data_model/autofill_structured_address_utils.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/geo/autofill_country.h"
 #include "components/autofill/core/browser/geo/country_names.h"
diff --git a/components/autofill/core/browser/data_model/autofill_profile.cc b/components/autofill/core/browser/data_model/autofill_profile.cc
index 1d0573c3..f7eed998 100644
--- a/components/autofill/core/browser/data_model/autofill_profile.cc
+++ b/components/autofill/core/browser/data_model/autofill_profile.cc
@@ -38,6 +38,8 @@
 #include "components/autofill/core/browser/data_model/autofill_structured_address_utils.h"
 #include "components/autofill/core/browser/data_model/contact_info.h"
 #include "components/autofill/core/browser/data_model/phone_number.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/field_type_utils.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/geo/address_i18n.h"
@@ -45,8 +47,6 @@
 #include "components/autofill/core/browser/geo/phone_number_i18n.h"
 #include "components/autofill/core/browser/geo/state_names.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics.h"
-#include "components/autofill/core/browser/profile_token_quality.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/autofill/core/common/autofill_features.h"
diff --git a/components/autofill/core/browser/data_model/autofill_profile.h b/components/autofill/core/browser/data_model/autofill_profile.h
index c93ad11..2b0a41bb 100644
--- a/components/autofill/core/browser/data_model/autofill_profile.h
+++ b/components/autofill/core/browser/data_model/autofill_profile.h
@@ -24,7 +24,7 @@
 #include "components/autofill/core/browser/data_model/autofill_i18n_api.h"
 #include "components/autofill/core/browser/data_model/contact_info.h"
 #include "components/autofill/core/browser/data_model/phone_number.h"
-#include "components/autofill/core/browser/profile_token_quality.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality.h"
 
 #if BUILDFLAG(IS_ANDROID)
 #include "base/android/scoped_java_ref.h"
diff --git a/components/autofill/core/browser/data_model/autofill_profile_comparator.cc b/components/autofill/core/browser/data_model/autofill_profile_comparator.cc
index 74457d59..7a44cae 100644
--- a/components/autofill/core/browser/data_model/autofill_profile_comparator.cc
+++ b/components/autofill/core/browser/data_model/autofill_profile_comparator.cc
@@ -15,12 +15,12 @@
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversion_utils.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/data_model/autofill_structured_address_component.h"
 #include "components/autofill/core/browser/data_model/autofill_structured_address_name.h"
 #include "components/autofill/core/browser/data_model/autofill_structured_address_utils.h"
 #include "components/autofill/core/browser/data_model/borrowed_transliterator.h"
 #include "components/autofill/core/browser/data_model/contact_info.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/geo/autofill_country.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics.h"
diff --git a/components/autofill/core/browser/data_model/autofill_profile_unittest.cc b/components/autofill/core/browser/data_model/autofill_profile_unittest.cc
index 184b8c5..28eaf3ca 100644
--- a/components/autofill/core/browser/data_model/autofill_profile_unittest.cc
+++ b/components/autofill/core/browser/data_model/autofill_profile_unittest.cc
@@ -21,11 +21,11 @@
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/data_model/autofill_profile_comparator.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality_test_api.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/geo/autofill_country.h"
 #include "components/autofill/core/browser/geo/country_data.h"
-#include "components/autofill/core/browser/profile_token_quality.h"
-#include "components/autofill/core/browser/profile_token_quality_test_api.h"
 #include "components/autofill/core/browser/test_utils/test_profiles.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/autofill/core/common/autofill_features.h"
diff --git a/components/autofill/core/browser/data_model/contact_info.cc b/components/autofill/core/browser/data_model/contact_info.cc
index 2543e85..1cb5229 100644
--- a/components/autofill/core/browser/data_model/contact_info.cc
+++ b/components/autofill/core/browser/data_model/contact_info.cc
@@ -14,13 +14,13 @@
 #include "base/notreached.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/autofill_structured_address_component.h"
 #include "components/autofill/core/browser/data_model/autofill_structured_address_name.h"
 #include "components/autofill/core/browser/data_model/autofill_structured_address_utils.h"
 #include "components/autofill/core/browser/data_model/form_group.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/field_type_utils.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/common/autofill_features.h"
diff --git a/components/autofill/core/browser/data_model/credit_card.cc b/components/autofill/core/browser/data_model/credit_card.cc
index 7cdbc5a..0eaf30d 100644
--- a/components/autofill/core/browser/data_model/credit_card.cc
+++ b/components/autofill/core/browser/data_model/credit_card.cc
@@ -24,15 +24,15 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/uuid.h"
 #include "build/build_config.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_field.h"
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/data_model/data_model_utils.h"
 #include "components/autofill/core/browser/data_model/payments_metadata.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics.h"
 #include "components/autofill/core/browser/payments/constants.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/autofill/core/common/autofill_features.h"
diff --git a/components/autofill/core/browser/data_model/credit_card_unittest.cc b/components/autofill/core/browser/data_model/credit_card_unittest.cc
index 78cd533..900e62b 100644
--- a/components/autofill/core/browser/data_model/credit_card_unittest.cc
+++ b/components/autofill/core/browser/data_model/credit_card_unittest.cc
@@ -21,7 +21,7 @@
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/data_model/payments_metadata.h"
 #include "components/autofill/core/browser/data_model/test_autofill_data_model.h"
-#include "components/autofill/core/browser/validation.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/autofill/core/common/autofill_features.h"
diff --git a/components/autofill/core/browser/address_normalization_manager.cc b/components/autofill/core/browser/data_quality/addresses/address_normalization_manager.cc
similarity index 91%
rename from components/autofill/core/browser/address_normalization_manager.cc
rename to components/autofill/core/browser/data_quality/addresses/address_normalization_manager.cc
index 4fb6922..0074e2c 100644
--- a/components/autofill/core/browser/address_normalization_manager.cc
+++ b/components/autofill/core/browser/data_quality/addresses/address_normalization_manager.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/autofill/core/browser/address_normalization_manager.h"
+#include "components/autofill/core/browser/data_quality/addresses/address_normalization_manager.h"
 
 #include <utility>
 
@@ -10,9 +10,9 @@
 #include "base/functional/callback_helpers.h"
 #include "base/memory/raw_ptr.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/address_normalizer.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_quality/addresses/address_normalizer.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/field_types.h"
 
 namespace autofill {
@@ -80,12 +80,14 @@
 }
 
 void AddressNormalizationManager::MaybeRunCompletionCallback() {
-  if (accepting_requests_ || !completion_callback_)
+  if (accepting_requests_ || !completion_callback_) {
     return;
+  }
 
   for (const auto& delegate : delegates_) {
-    if (!delegate->has_completed())
+    if (!delegate->has_completed()) {
       return;
+    }
   }
 
   // We're no longer accepting requests, and all the delegates have completed.
diff --git a/components/autofill/core/browser/address_normalization_manager.h b/components/autofill/core/browser/data_quality/addresses/address_normalization_manager.h
similarity index 89%
rename from components/autofill/core/browser/address_normalization_manager.h
rename to components/autofill/core/browser/data_quality/addresses/address_normalization_manager.h
index 56b6864..ef6d7bf 100644
--- a/components/autofill/core/browser/address_normalization_manager.h
+++ b/components/autofill/core/browser/data_quality/addresses/address_normalization_manager.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZATION_MANAGER_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZATION_MANAGER_H_
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_ADDRESS_NORMALIZATION_MANAGER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_ADDRESS_NORMALIZATION_MANAGER_H_
 
 #include <memory>
 #include <string>
@@ -72,4 +72,4 @@
 
 }  // namespace autofill
 
-#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZATION_MANAGER_H_
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_ADDRESS_NORMALIZATION_MANAGER_H_
diff --git a/components/autofill/core/browser/address_normalization_manager_unittest.cc b/components/autofill/core/browser/data_quality/addresses/address_normalization_manager_unittest.cc
similarity index 90%
rename from components/autofill/core/browser/address_normalization_manager_unittest.cc
rename to components/autofill/core/browser/data_quality/addresses/address_normalization_manager_unittest.cc
index 49a15c6..254ae1b 100644
--- a/components/autofill/core/browser/address_normalization_manager_unittest.cc
+++ b/components/autofill/core/browser/data_quality/addresses/address_normalization_manager_unittest.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/autofill/core/browser/address_normalization_manager.h"
+#include "components/autofill/core/browser/data_quality/addresses/address_normalization_manager.h"
 
 #include <memory>
 
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
-#include "components/autofill/core/browser/test_address_normalizer.h"
+#include "components/autofill/core/browser/data_quality/addresses/test_address_normalizer.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace autofill {
diff --git a/components/autofill/core/browser/address_normalizer.h b/components/autofill/core/browser/data_quality/addresses/address_normalizer.h
similarity index 88%
rename from components/autofill/core/browser/address_normalizer.h
rename to components/autofill/core/browser/data_quality/addresses/address_normalizer.h
index 2aeef4b..d2de17a 100644
--- a/components/autofill/core/browser/address_normalizer.h
+++ b/components/autofill/core/browser/data_quality/addresses/address_normalizer.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZER_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZER_H_
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_ADDRESS_NORMALIZER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_ADDRESS_NORMALIZER_H_
 
 #include <string>
 
@@ -54,4 +54,4 @@
 
 }  // namespace autofill
 
-#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZER_H_
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_ADDRESS_NORMALIZER_H_
diff --git a/components/autofill/core/browser/address_normalizer_impl.cc b/components/autofill/core/browser/data_quality/addresses/address_normalizer_impl.cc
similarity index 97%
rename from components/autofill/core/browser/address_normalizer_impl.cc
rename to components/autofill/core/browser/data_quality/addresses/address_normalizer_impl.cc
index e3e07f4..e448e27 100644
--- a/components/autofill/core/browser/address_normalizer_impl.cc
+++ b/components/autofill/core/browser/data_quality/addresses/address_normalizer_impl.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/autofill/core/browser/address_normalizer_impl.h"
+#include "components/autofill/core/browser/data_quality/addresses/address_normalizer_impl.h"
 
 #include <stddef.h>
 
@@ -19,8 +19,8 @@
 #include "base/task/sequenced_task_runner.h"
 #include "base/task/thread_pool.h"
 #include "base/time/time.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/geo/address_i18n.h"
 #include "components/autofill/core/browser/geo/phone_number_i18n.h"
 #include "third_party/libaddressinput/chromium/chrome_address_validator.h"
@@ -54,8 +54,9 @@
       *i18n::CreateAddressDataFromAutofillProfile(*profile, app_locale);
 
   // Normalize the address.
-  if (!address_validator->NormalizeAddress(&address_data))
+  if (!address_validator->NormalizeAddress(&address_data)) {
     return false;
+  }
 
   profile->SetRawInfo(ADDRESS_HOME_STATE,
                       base::UTF8ToUTF16(address_data.administrative_area));
@@ -133,8 +134,9 @@
 
   void OnRulesLoaded(bool success, AddressValidator* address_validator) {
     // Check if the timeout happened before the rules were loaded.
-    if (has_responded_)
+    if (has_responded_) {
       return;
+    }
     has_responded_ = true;
 
     // The phone number formatting doesn't require the rules to have been
@@ -200,8 +202,9 @@
 
   // The |address_validator_| is initialized in a background task. It may not
   // be available yet.
-  if (!address_validator_)
+  if (!address_validator_) {
     return;
+  }
 
   address_validator_->LoadRules(region_code);
 }
@@ -341,8 +344,9 @@
       pending_normalization_, [](const auto& entry) { return entry.first; });
 
   // Load rules for regions with pending normalization requests.
-  for (const std::string& region : region_keys)
+  for (const std::string& region : region_keys) {
     LoadRulesForRegion(region);
+  }
 }
 
 void AddressNormalizerImpl::AddNormalizationRequestForRegion(
diff --git a/components/autofill/core/browser/address_normalizer_impl.h b/components/autofill/core/browser/data_quality/addresses/address_normalizer_impl.h
similarity index 89%
rename from components/autofill/core/browser/address_normalizer_impl.h
rename to components/autofill/core/browser/data_quality/addresses/address_normalizer_impl.h
index b7c0816..e65bb79 100644
--- a/components/autofill/core/browser/address_normalizer_impl.h
+++ b/components/autofill/core/browser/data_quality/addresses/address_normalizer_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZER_IMPL_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZER_IMPL_H_
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_ADDRESS_NORMALIZER_IMPL_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_ADDRESS_NORMALIZER_IMPL_H_
 
 #include <map>
 #include <memory>
@@ -12,7 +12,7 @@
 
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
-#include "components/autofill/core/browser/address_normalizer.h"
+#include "components/autofill/core/browser/data_quality/addresses/address_normalizer.h"
 
 #if BUILDFLAG(IS_ANDROID)
 #include "base/android/scoped_java_ref.h"
@@ -98,4 +98,4 @@
 
 }  // namespace autofill
 
-#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZER_IMPL_H_
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_ADDRESS_NORMALIZER_IMPL_H_
diff --git a/components/autofill/core/browser/address_normalizer_impl_unittest.cc b/components/autofill/core/browser/data_quality/addresses/address_normalizer_impl_unittest.cc
similarity index 98%
rename from components/autofill/core/browser/address_normalizer_impl_unittest.cc
rename to components/autofill/core/browser/data_quality/addresses/address_normalizer_impl_unittest.cc
index b75d035..1446339 100644
--- a/components/autofill/core/browser/address_normalizer_impl_unittest.cc
+++ b/components/autofill/core/browser/data_quality/addresses/address_normalizer_impl_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/autofill/core/browser/address_normalizer_impl.h"
+#include "components/autofill/core/browser/data_quality/addresses/address_normalizer_impl.h"
 
 #include <utility>
 
@@ -11,9 +11,9 @@
 #include "base/functional/callback_helpers.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/task_environment.h"
-#include "components/autofill/core/browser/address_normalizer.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_quality/addresses/address_normalizer.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/null_storage.h"
diff --git a/components/autofill/core/browser/profile_requirement_utils.cc b/components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.cc
similarity index 85%
rename from components/autofill/core/browser/profile_requirement_utils.cc
rename to components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.cc
index b44579e..0304a5dcc 100644
--- a/components/autofill/core/browser/profile_requirement_utils.cc
+++ b/components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/autofill/core/browser/profile_requirement_utils.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.h"
 
 #include <string_view>
 #include <vector>
@@ -42,32 +42,32 @@
   // Validates the `profile` by testing that it has information for at least one
   // of the `types`. If `required` is false, it is considered trivially valid.
   // Logs the profile's validity to UMA and autofill-internals.
-  auto ValidateAndLog =
-      [&](bool required, const std::vector<FieldType>& types,
-          AddressImportRequirement valid, AddressImportRequirement invalid) {
-        const bool is_valid =
-            !required || std::ranges::any_of(types, [&](FieldType type) {
-              return profile.HasRawInfo(type);
-            });
-        if (is_valid) {
-          address_import_requirements.push_back(valid);
-        } else {
-          address_import_requirements.push_back(invalid);
-          LOG_AF(import_log_buffer)
-              << LogMessage::kImportAddressProfileFromFormFailed
-              << "Missing required " <<
-              [&] {
-                std::vector<std::string_view> type_names;
-                for (FieldType type : types) {
-                  type_names.push_back(FieldTypeToStringView(type));
-                }
-                return base::JoinString(type_names, " or ");
-              }()
-              << "." << CTag{};
-        }
+  auto ValidateAndLog = [&](bool required, const std::vector<FieldType>& types,
+                            AddressImportRequirement valid,
+                            AddressImportRequirement invalid) {
+    const bool is_valid =
+        !required || std::ranges::any_of(types, [&](FieldType type) {
+          return profile.HasRawInfo(type);
+        });
+    if (is_valid) {
+      address_import_requirements.push_back(valid);
+    } else {
+      address_import_requirements.push_back(invalid);
+      LOG_AF(import_log_buffer)
+          << LogMessage::kImportAddressProfileFromFormFailed
+          << "Missing required " <<
+          [&] {
+            std::vector<std::string_view> type_names;
+            for (FieldType type : types) {
+              type_names.push_back(FieldTypeToStringView(type));
+            }
+            return base::JoinString(type_names, " or ");
+          }()
+          << "." << CTag{};
+    }
 
-        return is_valid;
-      };
+    return is_valid;
+  };
 
   AutofillCountry country(
       base::UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY)));
diff --git a/components/autofill/core/browser/profile_requirement_utils.h b/components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.h
similarity index 89%
rename from components/autofill/core/browser/profile_requirement_utils.h
rename to components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.h
index e775919..852526bb3 100644
--- a/components/autofill/core/browser/profile_requirement_utils.h
+++ b/components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PROFILE_REQUIREMENT_UTILS_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_PROFILE_REQUIREMENT_UTILS_H_
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_PROFILE_REQUIREMENT_UTILS_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_PROFILE_REQUIREMENT_UTILS_H_
 
 #include <vector>
 
@@ -54,4 +54,4 @@
     const AutofillProfile& profile);
 }  //  namespace autofill
 
-#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_PROFILE_REQUIREMENT_UTILS_H_
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_PROFILE_REQUIREMENT_UTILS_H_
diff --git a/components/autofill/core/browser/profile_requirement_utils_unittest.cc b/components/autofill/core/browser/data_quality/addresses/profile_requirement_utils_unittest.cc
similarity index 94%
rename from components/autofill/core/browser/profile_requirement_utils_unittest.cc
rename to components/autofill/core/browser/data_quality/addresses/profile_requirement_utils_unittest.cc
index c7b43d7..650ab2ec 100644
--- a/components/autofill/core/browser/profile_requirement_utils_unittest.cc
+++ b/components/autofill/core/browser/data_quality/addresses/profile_requirement_utils_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/autofill/core/browser/profile_requirement_utils.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.h"
 
 #include "base/test/scoped_feature_list.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
diff --git a/components/autofill/core/browser/profile_token_quality.cc b/components/autofill/core/browser/data_quality/addresses/profile_token_quality.cc
similarity index 99%
rename from components/autofill/core/browser/profile_token_quality.cc
rename to components/autofill/core/browser/data_quality/addresses/profile_token_quality.cc
index c5f785b..754d82fd 100644
--- a/components/autofill/core/browser/profile_token_quality.cc
+++ b/components/autofill/core/browser/data_quality/addresses/profile_token_quality.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/autofill/core/browser/profile_token_quality.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality.h"
 
 #include <algorithm>
 #include <set>
diff --git a/components/autofill/core/browser/profile_token_quality.h b/components/autofill/core/browser/data_quality/addresses/profile_token_quality.h
similarity index 97%
rename from components/autofill/core/browser/profile_token_quality.h
rename to components/autofill/core/browser/data_quality/addresses/profile_token_quality.h
index 9e94aa35..0e6d7ab 100644
--- a/components/autofill/core/browser/profile_token_quality.h
+++ b/components/autofill/core/browser/data_quality/addresses/profile_token_quality.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PROFILE_TOKEN_QUALITY_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_PROFILE_TOKEN_QUALITY_H_
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_PROFILE_TOKEN_QUALITY_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_PROFILE_TOKEN_QUALITY_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -257,4 +257,4 @@
 
 }  // namespace autofill
 
-#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_PROFILE_TOKEN_QUALITY_H_
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_PROFILE_TOKEN_QUALITY_H_
diff --git a/components/autofill/core/browser/profile_token_quality_test_api.cc b/components/autofill/core/browser/data_quality/addresses/profile_token_quality_test_api.cc
similarity index 88%
rename from components/autofill/core/browser/profile_token_quality_test_api.cc
rename to components/autofill/core/browser/data_quality/addresses/profile_token_quality_test_api.cc
index fff4a0d..d7a5418 100644
--- a/components/autofill/core/browser/profile_token_quality_test_api.cc
+++ b/components/autofill/core/browser/data_quality/addresses/profile_token_quality_test_api.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/autofill/core/browser/profile_token_quality_test_api.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality_test_api.h"
 
 #include <vector>
 
 #include "base/check.h"
 #include "base/types/cxx23_to_underlying.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality.h"
 #include "components/autofill/core/browser/field_type_utils.h"
 #include "components/autofill/core/browser/field_types.h"
-#include "components/autofill/core/browser/profile_token_quality.h"
 
 namespace autofill {
 
diff --git a/components/autofill/core/browser/profile_token_quality_test_api.h b/components/autofill/core/browser/data_quality/addresses/profile_token_quality_test_api.h
similarity index 74%
rename from components/autofill/core/browser/profile_token_quality_test_api.h
rename to components/autofill/core/browser/data_quality/addresses/profile_token_quality_test_api.h
index ad86a56e..5e1bde4 100644
--- a/components/autofill/core/browser/profile_token_quality_test_api.h
+++ b/components/autofill/core/browser/data_quality/addresses/profile_token_quality_test_api.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PROFILE_TOKEN_QUALITY_TEST_API_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_PROFILE_TOKEN_QUALITY_TEST_API_H_
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_PROFILE_TOKEN_QUALITY_TEST_API_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_PROFILE_TOKEN_QUALITY_TEST_API_H_
 
 #include <vector>
 
 #include "base/memory/raw_ref.h"
-#include "components/autofill/core/browser/profile_token_quality.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality.h"
 
 namespace autofill {
 
@@ -42,4 +42,4 @@
 
 }  // namespace autofill
 
-#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_PROFILE_TOKEN_QUALITY_TEST_API_H_
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_PROFILE_TOKEN_QUALITY_TEST_API_H_
diff --git a/components/autofill/core/browser/profile_token_quality_unittest.cc b/components/autofill/core/browser/data_quality/addresses/profile_token_quality_unittest.cc
similarity index 98%
rename from components/autofill/core/browser/profile_token_quality_unittest.cc
rename to components/autofill/core/browser/data_quality/addresses/profile_token_quality_unittest.cc
index 33c2a62..d0a3d2e3 100644
--- a/components/autofill/core/browser/profile_token_quality_unittest.cc
+++ b/components/autofill/core/browser/data_quality/addresses/profile_token_quality_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/autofill/core/browser/profile_token_quality.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality.h"
 
 #include <memory>
 #include <string>
@@ -19,9 +19,9 @@
 #include "components/autofill/core/browser/autofill_trigger_source.h"
 #include "components/autofill/core/browser/country_type.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality_test_api.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/form_structure.h"
-#include "components/autofill/core/browser/profile_token_quality_test_api.h"
 #include "components/autofill/core/browser/test_autofill_client.h"
 #include "components/autofill/core/browser/test_autofill_driver.h"
 #include "components/autofill/core/browser/test_browser_autofill_manager.h"
diff --git a/components/autofill/core/browser/test_address_normalizer.cc b/components/autofill/core/browser/data_quality/addresses/test_address_normalizer.cc
similarity index 92%
rename from components/autofill/core/browser/test_address_normalizer.cc
rename to components/autofill/core/browser/data_quality/addresses/test_address_normalizer.cc
index ff9069fb..734b6795 100644
--- a/components/autofill/core/browser/test_address_normalizer.cc
+++ b/components/autofill/core/browser/data_quality/addresses/test_address_normalizer.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <utility>
+#include "components/autofill/core/browser/data_quality/addresses/test_address_normalizer.h"
 
-#include "components/autofill/core/browser/test_address_normalizer.h"
+#include <utility>
 
 namespace autofill {
 
diff --git a/components/autofill/core/browser/test_address_normalizer.h b/components/autofill/core/browser/data_quality/addresses/test_address_normalizer.h
similarity index 80%
rename from components/autofill/core/browser/test_address_normalizer.h
rename to components/autofill/core/browser/data_quality/addresses/test_address_normalizer.h
index 16819ca1..f1d3fce 100644
--- a/components/autofill/core/browser/test_address_normalizer.h
+++ b/components/autofill/core/browser/data_quality/addresses/test_address_normalizer.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_ADDRESS_NORMALIZER_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_ADDRESS_NORMALIZER_H_
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_TEST_ADDRESS_NORMALIZER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_TEST_ADDRESS_NORMALIZER_H_
 
 #include <string>
 
 #include "base/functional/callback.h"
 #include "build/build_config.h"
-#include "components/autofill/core/browser/address_normalizer.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_quality/addresses/address_normalizer.h"
 
 #if BUILDFLAG(IS_ANDROID)
 #include "base/android/scoped_java_ref.h"
@@ -52,4 +52,4 @@
 
 }  // namespace autofill
 
-#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_ADDRESS_NORMALIZER_H_
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_ADDRESSES_TEST_ADDRESS_NORMALIZER_H_
diff --git a/components/autofill/core/browser/autofill_data_util.cc b/components/autofill/core/browser/data_quality/autofill_data_util.cc
similarity index 97%
rename from components/autofill/core/browser/autofill_data_util.cc
rename to components/autofill/core/browser/data_quality/autofill_data_util.cc
index 5fbf7b1..d9a9a40 100644
--- a/components/autofill/core/browser/autofill_data_util.cc
+++ b/components/autofill/core/browser/data_quality/autofill_data_util.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/autofill/core/browser/autofill_data_util.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 
 #include <array>
 #include <iterator>
@@ -133,8 +133,9 @@
 // Returns true if `set` contains `element`, modulo a final period.
 bool ContainsString(base::span<const std::string_view> set,
                     std::u16string_view element) {
-  if (!base::IsStringASCII(element))
+  if (!base::IsStringASCII(element)) {
     return false;
+  }
 
   std::u16string_view trimmed_element =
       base::TrimString(element, u".", base::TRIM_ALL);
@@ -424,8 +425,9 @@
   }
 
   // Don't assume "Ma" is a suffix in John Ma.
-  if (name_tokens.size() > 2)
+  if (name_tokens.size() > 2) {
     StripSuffixes(&name_tokens);
+  }
 
   if (name_tokens.empty()) {
     // Bad things have happened; just assume the whole thing is a given name.
@@ -472,14 +474,17 @@
                              std::u16string_view family) {
   // First Middle Last
   std::vector<std::u16string_view> full_name;
-  if (!given.empty())
+  if (!given.empty()) {
     full_name.push_back(given);
+  }
 
-  if (!middle.empty())
+  if (!middle.empty()) {
     full_name.push_back(middle);
+  }
 
-  if (!family.empty())
+  if (!family.empty()) {
     full_name.push_back(family);
+  }
 
   const char* separator = " ";
   if (IsCJKName(given) && IsCJKName(family) && middle.empty()) {
@@ -499,8 +504,9 @@
   for (const PaymentRequestData& data :
        use_new_data ? kPaymentRequestDataForNewNetworkImages
                     : kPaymentRequestData) {
-    if (issuer_network == data.issuer_network)
+    if (issuer_network == data.issuer_network) {
       return data;
+    }
   }
   return use_new_data ? kGenericPaymentRequestDataForNewNetworkImages
                       : kGenericPaymentRequestData;
@@ -535,8 +541,9 @@
 }
 
 bool IsValidCountryCode(const std::string& country_code) {
-  if (country_code.size() != 2)
+  if (country_code.size() != 2) {
     return false;
+  }
 
   static const base::NoDestructor<re2::RE2> country_code_regex("^[A-Z]{2}$");
   return re2::RE2::FullMatch(country_code, *country_code_regex.get());
@@ -550,8 +557,9 @@
                                        const std::string& app_locale) {
   std::string country_code =
       base::UTF16ToUTF8(profile.GetRawInfo(autofill::ADDRESS_HOME_COUNTRY));
-  if (!IsValidCountryCode(country_code))
+  if (!IsValidCountryCode(country_code)) {
     country_code = AutofillCountry::CountryCodeForLocale(app_locale);
+  }
   return country_code;
 }
 
diff --git a/components/autofill/core/browser/autofill_data_util.h b/components/autofill/core/browser/data_quality/autofill_data_util.h
similarity index 94%
rename from components/autofill/core/browser/autofill_data_util.h
rename to components/autofill/core/browser/data_quality/autofill_data_util.h
index b7665df4..568034d0 100644
--- a/components/autofill/core/browser/autofill_data_util.h
+++ b/components/autofill/core/browser/data_quality/autofill_data_util.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_DATA_UTIL_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_DATA_UTIL_H_
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_AUTOFILL_DATA_UTIL_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_AUTOFILL_DATA_UTIL_H_
 
 #include <string>
 #include <string_view>
@@ -127,4 +127,4 @@
 }  // namespace data_util
 }  // namespace autofill
 
-#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_DATA_UTIL_H_
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_AUTOFILL_DATA_UTIL_H_
diff --git a/components/autofill/core/browser/autofill_data_util_unittest.cc b/components/autofill/core/browser/data_quality/autofill_data_util_unittest.cc
similarity index 98%
rename from components/autofill/core/browser/autofill_data_util_unittest.cc
rename to components/autofill/core/browser/data_quality/autofill_data_util_unittest.cc
index bc2a074b..08857930 100644
--- a/components/autofill/core/browser/autofill_data_util_unittest.cc
+++ b/components/autofill/core/browser/data_quality/autofill_data_util_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/autofill/core/browser/autofill_data_util.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 
 #include "base/strings/utf_string_conversions.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
diff --git a/components/autofill/core/browser/validation.cc b/components/autofill/core/browser/data_quality/validation.cc
similarity index 97%
rename from components/autofill/core/browser/validation.cc
rename to components/autofill/core/browser/data_quality/validation.cc
index 99ac655..ccc7b7152 100644
--- a/components/autofill/core/browser/validation.cc
+++ b/components/autofill/core/browser/data_quality/validation.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/autofill/core/browser/validation.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 
 #include <stddef.h>
 
@@ -25,8 +25,9 @@
 namespace autofill {
 
 bool IsValidCreditCardExpirationDate(int year, int month, base::Time now) {
-  if (month < 1 || month > 12)
+  if (month < 1 || month > 12) {
     return false;
+  }
 
   base::Time::Exploded now_exploded;
   now.LocalExplode(&now_exploded);
@@ -97,8 +98,9 @@
   //   http://www.socialsecurity.gov/employer/stateweb.htm
   //   http://www.socialsecurity.gov/employer/ssnvhighgroup.htm
 
-  if (number_string.length() != 9 || !base::IsStringASCII(number_string))
+  if (number_string.length() != 9 || !base::IsStringASCII(number_string)) {
     return false;
+  }
 
   int area;
   if (!base::StringToInt(base::MakeStringPiece16(number_string.begin(),
diff --git a/components/autofill/core/browser/validation.h b/components/autofill/core/browser/data_quality/validation.h
similarity index 93%
rename from components/autofill/core/browser/validation.h
rename to components/autofill/core/browser/data_quality/validation.h
index e306cfa..dfa4da4 100644
--- a/components/autofill/core/browser/validation.h
+++ b/components/autofill/core/browser/data_quality/validation.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_VALIDATION_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_VALIDATION_H_
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_VALIDATION_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_VALIDATION_H_
 
 #include <string>
 #include <string_view>
@@ -82,4 +82,4 @@
 
 }  // namespace autofill
 
-#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_VALIDATION_H_
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_QUALITY_VALIDATION_H_
diff --git a/components/autofill/core/browser/validation_unittest.cc b/components/autofill/core/browser/data_quality/validation_unittest.cc
similarity index 99%
rename from components/autofill/core/browser/validation_unittest.cc
rename to components/autofill/core/browser/data_quality/validation_unittest.cc
index 7a31f78..b5d1d606 100644
--- a/components/autofill/core/browser/validation_unittest.cc
+++ b/components/autofill/core/browser/data_quality/validation_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/autofill/core/browser/validation.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 
 #include <stddef.h>
 
diff --git a/components/autofill/core/browser/filling/addresses/field_filling_address_util.cc b/components/autofill/core/browser/filling/addresses/field_filling_address_util.cc
index b480c65..67f2451 100644
--- a/components/autofill/core/browser/filling/addresses/field_filling_address_util.cc
+++ b/components/autofill/core/browser/filling/addresses/field_filling_address_util.cc
@@ -10,10 +10,10 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/address_normalizer.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/data_model_utils.h"
+#include "components/autofill/core/browser/data_quality/addresses/address_normalizer.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/field_type_utils.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/geo/country_names.h"
diff --git a/components/autofill/core/browser/filling/addresses/field_filling_address_util_unittest.cc b/components/autofill/core/browser/filling/addresses/field_filling_address_util_unittest.cc
index a64da8ff..a607508 100644
--- a/components/autofill/core/browser/filling/addresses/field_filling_address_util_unittest.cc
+++ b/components/autofill/core/browser/filling/addresses/field_filling_address_util_unittest.cc
@@ -10,12 +10,12 @@
 #include "base/path_service.h"
 #include "base/ranges/algorithm.h"
 #include "base/test/task_environment.h"
-#include "components/autofill/core/browser/address_normalizer.h"
-#include "components/autofill/core/browser/address_normalizer_impl.h"
 #include "components/autofill/core/browser/autofill_field.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_quality/addresses/address_normalizer.h"
+#include "components/autofill/core/browser/data_quality/addresses/address_normalizer_impl.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/form_parsing/regex_patterns.h"
 #include "components/autofill/core/browser/geo/alternative_state_name_map_test_utils.h"
diff --git a/components/autofill/core/browser/filling/form_filler.cc b/components/autofill/core/browser/filling/form_filler.cc
index 1f43ef54..25112b5e 100644
--- a/components/autofill/core/browser/filling/form_filler.cc
+++ b/components/autofill/core/browser/filling/form_filler.cc
@@ -16,9 +16,9 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/notreached.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/browser_autofill_manager.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/field_type_utils.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/filling/addresses/field_filling_address_util.h"
@@ -317,11 +317,14 @@
 
 FormFiller::FillingContext::~FillingContext() = default;
 
-FormFiller::FormFiller(BrowserAutofillManager& manager, LogManager* log_manager)
-    : log_manager_(log_manager), manager_(manager) {}
+FormFiller::FormFiller(BrowserAutofillManager& manager) : manager_(manager) {}
 
 FormFiller::~FormFiller() = default;
 
+LogManager* FormFiller::log_manager() {
+  return manager_->client().GetLogManager();
+}
+
 void FormFiller::Reset() {
   filling_context_.clear();
   form_autofill_history_.Reset();
@@ -378,7 +381,7 @@
     FormStructure& form_structure,
     const FormFieldData& trigger_field) {
   if (!form_autofill_history_.HasHistory(trigger_field.global_id())) {
-    LOG_AF(log_manager_)
+    LOG_AF(log_manager())
         << "Could not undo the filling operation on field "
         << trigger_field.global_id()
         << " because history was dropped upon reaching history limit of "
@@ -568,8 +571,8 @@
     const FormData& form,
     absl::variant<const AutofillProfile*, const CreditCard*>
         profile_or_credit_card,
-    FormStructure* form_structure,
-    AutofillField* autofill_trigger_field,
+    FormStructure& form_structure,
+    AutofillField& autofill_trigger_field,
     AutofillTriggerSource trigger_source,
     bool is_refill) {
   FillingProduct filling_product =
@@ -577,16 +580,13 @@
           ? FillingProduct::kCreditCard
           : FillingProduct::kAddress;
 
-  DCHECK(form_structure);
-  DCHECK(autofill_trigger_field);
-
-  LogBuffer buffer(IsLoggingActive(log_manager_));
+  LogBuffer buffer(IsLoggingActive(log_manager()));
   LOG_AF(buffer) << "action_persistence: "
                  << ActionPersistenceToString(action_persistence) << Br{};
   LOG_AF(buffer) << "filling product: "
                  << FillingProductToString(filling_product) << Br{};
   LOG_AF(buffer) << "is refill: " << is_refill << Br{};
-  LOG_AF(buffer) << *form_structure << Br{};
+  LOG_AF(buffer) << form_structure << Br{};
   LOG_AF(buffer) << Tag{"table"};
 
   // TODO(crbug/1203667#c9): Skip if the form has changed in the meantime, which
@@ -594,25 +594,25 @@
   if (action_persistence == mojom::ActionPersistence::kFill) {
     base::UmaHistogramBoolean(
         "Autofill.SkippingFormFillDueToChangedFieldCount",
-        form_structure->field_count() != form.fields().size());
+        form_structure.field_count() != form.fields().size());
   }
-  if (form_structure->field_count() != form.fields().size()) {
+  if (form_structure.field_count() != form.fields().size()) {
     LOG_AF(buffer)
         << Tr{} << "*"
         << "Skipped filling of form because the number of fields to be "
            "filled differs from the number of fields registered in the form "
            "cache."
         << CTag{"table"};
-    LOG_AF(log_manager_) << LoggingScope::kFilling
-                         << LogMessage::kSendFillingData << Br{}
-                         << std::move(buffer);
+    LOG_AF(log_manager()) << LoggingScope::kFilling
+                          << LogMessage::kSendFillingData << Br{}
+                          << std::move(buffer);
     return;
   }
 
   if (action_persistence == mojom::ActionPersistence::kFill && !is_refill) {
-    form_structure->set_last_filling_timestamp(base::TimeTicks::Now());
-    SetFillingContext(form_structure->global_id(),
-                      std::make_unique<FillingContext>(*autofill_trigger_field,
+    form_structure.set_last_filling_timestamp(base::TimeTicks::Now());
+    SetFillingContext(form_structure.global_id(),
+                      std::make_unique<FillingContext>(autofill_trigger_field,
                                                        profile_or_credit_card));
   }
 
@@ -622,20 +622,21 @@
   //  A refill has not been attempted for that form yet.
   //  This fill is not a refill attempt.
   FillingContext* filling_context =
-      GetFillingContext(form_structure->global_id());
+      GetFillingContext(form_structure.global_id());
   bool could_attempt_refill = filling_context != nullptr &&
                               !filling_context->attempted_refill && !is_refill;
 
   std::vector<FormFieldData> result_fields = form.fields();
-  CHECK_EQ(result_fields.size(), form_structure->field_count());
-  for (size_t i = 0; i < form_structure->field_count(); ++i) {
+  CHECK_EQ(result_fields.size(), form_structure.field_count());
+  // TODO(crbug.com/40266549): Remove when Undo launches on iOS.
+  for (size_t i = 0; i < form_structure.field_count(); ++i) {
     // On the renderer, the section is used regardless of the autofill status.
-    result_fields[i].set_section(form_structure->field(i)->section());
+    result_fields[i].set_section(form_structure.field(i)->section());
   }
 
   base::flat_map<FieldGlobalId, DenseSet<FieldFillingSkipReason>> skip_reasons =
       GetFieldFillingSkipReasons(
-          result_fields, *form_structure, *autofill_trigger_field,
+          result_fields, form_structure, autofill_trigger_field,
           filling_context ? filling_context->type_groups_originally_filled
                           : std::optional<DenseSet<FieldTypeGroup>>(),
           filling_product, is_refill);
@@ -645,23 +646,23 @@
   // `form_structure->fields()` remains in the browser process.
   // The fill value is determined by FillForm().
   for (size_t i = 0; i < result_fields.size(); ++i) {
-    AutofillField* autofill_field = form_structure->field(i);
+    AutofillField& autofill_field = CHECK_DEREF(form_structure.field(i));
     constexpr DenseSet<FieldFillingSkipReason> kPreUkmLoggingSkips{
         FieldFillingSkipReason::kNotInFilledSection,
         FieldFillingSkipReason::kFormChanged,
         FieldFillingSkipReason::kNotFocused};
     if (!kPreUkmLoggingSkips.contains_any(
-            skip_reasons[autofill_field->global_id()]) &&
-        !autofill_field->IsFocusable()) {
+            skip_reasons[autofill_field.global_id()]) &&
+        !autofill_field.IsFocusable()) {
       manager_->client()
           .GetFormInteractionsUkmLogger()
           .LogHiddenRepresentationalFieldSkipDecision(
-              manager_->driver().GetPageUkmSourceId(), *form_structure,
-              *autofill_field, !autofill_field->IsSelectElement());
+              manager_->driver().GetPageUkmSourceId(), form_structure,
+              autofill_field, !autofill_field.IsSelectElement());
     }
-    if (!skip_reasons[autofill_field->global_id()].empty()) {
+    if (!skip_reasons[autofill_field.global_id()].empty()) {
       const FieldFillingSkipReason skip_reason =
-          *skip_reasons[autofill_field->global_id()].begin();
+          *skip_reasons[autofill_field.global_id()].begin();
       LOG_AF(buffer) << Tr{} << base::StringPrintf("Field %zu", i)
                      << GetSkipFieldFillLogMessage(skip_reason);
       continue;
@@ -669,7 +670,7 @@
 
     if (could_attempt_refill) {
       filling_context->type_groups_originally_filled.insert(
-          autofill_field->Type().group());
+          autofill_field.Type().group());
     }
     std::string failure_to_fill;  // Reason for failing to fill.
     const std::map<FieldGlobalId, std::u16string>& forced_fill_values =
@@ -682,7 +683,7 @@
     // filled before, and also returns true in such a case; however, such fields
     // don't reach this code.
     const bool is_newly_autofilled =
-        FillField(*autofill_field, profile_or_credit_card, forced_fill_values,
+        FillField(autofill_field, profile_or_credit_card, forced_fill_values,
                   result_fields[i], action_persistence, &failure_to_fill);
     const bool autofilled_value_did_not_change =
         form.fields()[i].is_autofilled() && result_fields[i].is_autofilled() &&
@@ -690,7 +691,7 @@
     if (is_newly_autofilled && !autofilled_value_did_not_change) {
       // For credit card fields, override the autofilled field value if the
       // field is autofilled.
-      if (AllowPaymentSwapping(*autofill_trigger_field, *autofill_field,
+      if (AllowPaymentSwapping(autofill_trigger_field, autofill_field,
                                is_refill) &&
           form.fields()[i].is_autofilled() &&
           result_fields[i].is_autofilled() &&
@@ -722,7 +723,7 @@
     filling_context->filled_form->set_fields(result_fields);
   }
   auto field_types = base::MakeFlatMap<FieldGlobalId, FieldType>(
-      *form_structure, {}, [](const auto& field) {
+      form_structure, {}, [](const auto& field) {
         return std::make_pair(field->global_id(),
                               field->Type().GetStorableType());
       });
@@ -733,12 +734,12 @@
   std::erase_if(result_fields,
                 [&skip_reasons, &form_structure](const FormFieldData& field) {
                   return !skip_reasons[field.global_id()].empty() ||
-                         !form_structure->GetFieldById(field.global_id());
+                         !form_structure.GetFieldById(field.global_id());
                 });
   base::flat_set<FieldGlobalId> safe_filled_field_ids =
       manager_->driver().ApplyFormAction(
           mojom::FormActionType::kFill, action_persistence, result_fields,
-          autofill_trigger_field->origin(), field_types);
+          autofill_trigger_field.origin(), field_types);
 
   // This will hold the subset of fields of `result_fields` whose ids are in
   // `safe_filled_field_ids`
@@ -762,7 +763,7 @@
         return fields_it != result_fields.end() ? &*fields_it : nullptr;
       }());
       safe_filled_fields.cached.push_back(
-          form_structure->GetFieldById(field_id));
+          form_structure.GetFieldById(field_id));
     } else {
       auto it = base::ranges::find(form.fields(), field_id,
                                    &FormFieldData::global_id);
@@ -783,8 +784,9 @@
   }
 
   LOG_AF(buffer) << CTag{"table"};
-  LOG_AF(log_manager_) << LoggingScope::kFilling << LogMessage::kSendFillingData
-                       << Br{} << std::move(buffer);
+  LOG_AF(log_manager()) << LoggingScope::kFilling
+                        << LogMessage::kSendFillingData << Br{}
+                        << std::move(buffer);
 
   if (filling_context) {
     // When a new preview/fill starts, previously forced_fill_values should be
@@ -793,7 +795,7 @@
   }
 
   manager_->OnDidFillOrPreviewForm(
-      action_persistence, form, *form_structure, *autofill_trigger_field,
+      action_persistence, form, form_structure, autofill_trigger_field,
       safe_filled_fields.new_values, safe_filled_fields.cached,
       base::MakeFlatSet<FieldGlobalId>(result_fields, {},
                                        &FormFieldData::global_id),
@@ -904,8 +906,8 @@
   absl::visit(
       [&](const auto& profile_or_credit_card) {
         FillOrPreviewForm(mojom::ActionPersistence::kFill, form,
-                          &profile_or_credit_card, form_structure,
-                          autofill_field, trigger_source,
+                          &profile_or_credit_card, *form_structure,
+                          *autofill_field, trigger_source,
                           /*is_refill=*/true);
       },
       filling_context->profile_or_credit_card);
diff --git a/components/autofill/core/browser/filling/form_filler.h b/components/autofill/core/browser/filling/form_filler.h
index 2e735aa..cfd366d 100644
--- a/components/autofill/core/browser/filling/form_filler.h
+++ b/components/autofill/core/browser/filling/form_filler.h
@@ -54,7 +54,7 @@
 // It holds any state that is only relevant for [re]filling.
 class FormFiller {
  public:
-  FormFiller(BrowserAutofillManager& manager, LogManager* log_manager);
+  explicit FormFiller(BrowserAutofillManager& manager);
 
   FormFiller(const FormFiller&) = delete;
   FormFiller& operator=(const FormFiller&) = delete;
@@ -145,8 +145,8 @@
       const FormData& form,
       absl::variant<const AutofillProfile*, const CreditCard*>
           profile_or_credit_card,
-      FormStructure* form_structure,
-      AutofillField* autofill_field,
+      FormStructure& form_structure,
+      AutofillField& autofill_field,
       AutofillTriggerSource trigger_source,
       bool is_refill = false);
 
@@ -264,6 +264,8 @@
       mojom::ActionPersistence action_persistence,
       std::string* failure_to_fill);
 
+  LogManager* log_manager();
+
   // Container holding the history of Autofill filling operations. Used to undo
   // some of the filling operations.
   FormAutofillHistory form_autofill_history_;
@@ -277,7 +279,6 @@
   // where time cannot be mocked, to avoid flakiness.
   base::TimeDelta limit_before_refill_ = kLimitBeforeRefill;
 
-  const raw_ptr<LogManager> log_manager_;
   const raw_ref<BrowserAutofillManager> manager_;
 
   base::WeakPtrFactory<FormFiller> weak_ptr_factory_{this};
diff --git a/components/autofill/core/browser/filling/form_filler_unittest.cc b/components/autofill/core/browser/filling/form_filler_unittest.cc
index 127c1aa..6f16cc9 100644
--- a/components/autofill/core/browser/filling/form_filler_unittest.cc
+++ b/components/autofill/core/browser/filling/form_filler_unittest.cc
@@ -199,7 +199,7 @@
             DoAll(SaveArgElementsTo<2>(&filled_fields), Return(global_ids)));
     form_filler().FillOrPreviewForm(
         mojom::ActionPersistence::kFill, form, profile_or_credit_card,
-        GetFormStructure(form), GetAutofillField(form, trigger_field),
+        *GetFormStructure(form), *GetAutofillField(form, trigger_field),
         trigger_source,
         /*is_refill=*/false);
     // Copy the filled data into the form.
@@ -223,7 +223,7 @@
                          Return(std::vector<FieldGlobalId>{}))));
     form_filler().FillOrPreviewForm(
         mojom::ActionPersistence::kPreview, form, &virtual_card,
-        GetFormStructure(form), GetAutofillField(form, field),
+        *GetFormStructure(form), *GetAutofillField(form, field),
         AutofillTriggerSource::kPopup, /*is_refill=*/false);
     return filled_fields;
   }
@@ -294,11 +294,11 @@
 
   EXPECT_CALL(autofill_driver_, ApplyFormAction).Times(0);
   AutofillProfile profile = test::GetFullProfile();
-  form_filler().FillOrPreviewForm(mojom::ActionPersistence::kFill, form,
-                                  &profile, GetFormStructure(form),
-                                  GetAutofillField(form, form.fields().front()),
-                                  AutofillTriggerSource::kPopup,
-                                  /*is_refill=*/false);
+  form_filler().FillOrPreviewForm(
+      mojom::ActionPersistence::kFill, form, &profile, *GetFormStructure(form),
+      *GetAutofillField(form, form.fields().front()),
+      AutofillTriggerSource::kPopup,
+      /*is_refill=*/false);
 }
 
 TEST_F(FormFillerTest, SkipFillIfFieldIsMeaningfullyPreFilled) {
@@ -400,11 +400,11 @@
       .WillRepeatedly(Return(safe_fields));
 
   AutofillProfile profile = test::GetFullProfile();
-  form_filler().FillOrPreviewForm(mojom::ActionPersistence::kFill, form,
-                                  &profile, GetFormStructure(form),
-                                  GetAutofillField(form, form.fields().front()),
-                                  AutofillTriggerSource::kPopup,
-                                  /*is_refill=*/false);
+  form_filler().FillOrPreviewForm(
+      mojom::ActionPersistence::kFill, form, &profile, *GetFormStructure(form),
+      *GetAutofillField(form, form.fields().front()),
+      AutofillTriggerSource::kPopup,
+      /*is_refill=*/false);
   // Undo early returns if it has no filling history for the trigger field,
   // which is initially empty, therefore calling the driver is proof that data
   // was successfully stored.
diff --git a/components/autofill/core/browser/filling/payments/field_filling_payments_util.cc b/components/autofill/core/browser/filling/payments/field_filling_payments_util.cc
index ba990a7..d02158e 100644
--- a/components/autofill/core/browser/filling/payments/field_filling_payments_util.cc
+++ b/components/autofill/core/browser/filling/payments/field_filling_payments_util.cc
@@ -9,10 +9,10 @@
 #include "base/ranges/algorithm.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_field.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/autofill/core/browser/data_model/data_model_utils.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/field_type_utils.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/filling/form_filler.h"
diff --git a/components/autofill/core/browser/form_import/addresses/autofill_profile_import_process.cc b/components/autofill/core/browser/form_import/addresses/autofill_profile_import_process.cc
index 73f6788..484c7d72 100644
--- a/components/autofill/core/browser/form_import/addresses/autofill_profile_import_process.cc
+++ b/components/autofill/core/browser/form_import/addresses/autofill_profile_import_process.cc
@@ -14,10 +14,10 @@
 #include "components/autofill/core/browser/address_data_manager.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/autofill_profile_comparator.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/metrics/profile_deduplication_metrics.h"
 #include "components/autofill/core/browser/metrics/profile_import_metrics.h"
-#include "components/autofill/core/browser/profile_requirement_utils.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_features.h"
 
diff --git a/components/autofill/core/browser/form_import/form_data_importer.cc b/components/autofill/core/browser/form_import/form_data_importer.cc
index 230b648..a98d353d 100644
--- a/components/autofill/core/browser/form_import/form_data_importer.cc
+++ b/components/autofill/core/browser/form_import/form_data_importer.cc
@@ -24,7 +24,6 @@
 #include "build/build_config.h"
 #include "components/autofill/core/browser/address_data_manager.h"
 #include "components/autofill/core/browser/autofill_client.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_field.h"
 #include "components/autofill/core/browser/autofill_plus_address_delegate.h"
 #include "components/autofill/core/browser/autofill_type.h"
@@ -37,6 +36,9 @@
 #include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/autofill/core/browser/data_model/iban.h"
 #include "components/autofill/core/browser/data_model/phone_number.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/field_type_utils.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/form_import/addresses/address_profile_save_manager.h"
@@ -56,8 +58,6 @@
 #include "components/autofill/core/browser/payments/virtual_card_enrollment_manager.h"
 #include "components/autofill/core/browser/payments_data_manager.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/browser/profile_requirement_utils.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_internals/log_message.h"
 #include "components/autofill/core/common/autofill_internals/logging_scope.h"
diff --git a/components/autofill/core/browser/form_import/form_data_importer_utils.cc b/components/autofill/core/browser/form_import/form_data_importer_utils.cc
index 124f370..a522328f 100644
--- a/components/autofill/core/browser/form_import/form_data_importer_utils.cc
+++ b/components/autofill/core/browser/form_import/form_data_importer_utils.cc
@@ -7,8 +7,8 @@
 #include "base/containers/contains.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/autofill/core/browser/address_data_manager.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.h"
 #include "components/autofill/core/browser/geo/autofill_country.h"
-#include "components/autofill/core/browser/profile_requirement_utils.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_internals/log_message.h"
 
diff --git a/components/autofill/core/browser/form_parsing/email_field_parser.cc b/components/autofill/core/browser/form_parsing/email_field_parser.cc
index 22a4b85..a6ecad6 100644
--- a/components/autofill/core/browser/form_parsing/email_field_parser.cc
+++ b/components/autofill/core/browser/form_parsing/email_field_parser.cc
@@ -6,9 +6,9 @@
 
 #include "base/feature_list.h"
 #include "components/autofill/core/browser/autofill_field.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/form_parsing/autofill_scanner.h"
 #include "components/autofill/core/browser/form_parsing/regex_patterns.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_regex_constants.h"
 
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc
index c9ee3b6b..214c259 100644
--- a/components/autofill/core/browser/form_structure.cc
+++ b/components/autofill/core/browser/form_structure.cc
@@ -39,11 +39,12 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_field.h"
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/crowdsourcing/randomized_encoder.h"
 #include "components/autofill/core/browser/crowdsourcing/server_prediction_overrides.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/field_type_utils.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/form_parsing/autofill_parsing_utils.h"
@@ -60,7 +61,6 @@
 #include "components/autofill/core/browser/metrics/log_event.h"
 #include "components/autofill/core/browser/metrics/prediction_quality_metrics.h"
 #include "components/autofill/core/browser/metrics/shadow_prediction_metrics.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autocomplete_parsing_util.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/autofill/core/common/autofill_features.h"
diff --git a/components/autofill/core/browser/geo/phone_number_i18n.cc b/components/autofill/core/browser/geo/phone_number_i18n.cc
index 29e4b17..69ce2493 100644
--- a/components/autofill/core/browser/geo/phone_number_i18n.cc
+++ b/components/autofill/core/browser/geo/phone_number_i18n.cc
@@ -13,8 +13,8 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/geo/autofill_country.h"
 #include "third_party/libphonenumber/phonenumber_api.h"
 
diff --git a/components/autofill/core/browser/metrics/autofill_metrics.cc b/components/autofill/core/browser/metrics/autofill_metrics.cc
index 97dd615..fbdcb5d 100644
--- a/components/autofill/core/browser/metrics/autofill_metrics.cc
+++ b/components/autofill/core/browser/metrics/autofill_metrics.cc
@@ -16,11 +16,12 @@
 #include "base/strings/strcat.h"
 #include "base/time/time.h"
 #include "base/types/cxx23_to_underlying.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_field.h"
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/data_model/autofill_offer_data.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/field_type_utils.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/filling_product.h"
@@ -32,7 +33,6 @@
 #include "components/autofill/core/browser/payments/card_unmask_challenge_option.h"
 #include "components/autofill/core/browser/payments/payments_autofill_client.h"
 #include "components/autofill/core/browser/ui/popup_interaction.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_prefs.h"
 #include "components/autofill/core/common/form_data.h"
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
index 25c00b32..ef76053 100644
--- a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <stddef.h>
 
+#include <array>
 #include <memory>
 #include <string>
 #include <utility>
@@ -28,13 +29,13 @@
 #include "base/time/time.h"
 #include "base/types/cxx23_to_underlying.h"
 #include "build/build_config.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_external_delegate.h"
 #include "components/autofill/core/browser/autofill_form_test_utils.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/browser_autofill_manager.h"
 #include "components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/filling_product.h"
 #include "components/autofill/core/browser/form_structure.h"
@@ -2775,10 +2776,11 @@
                       /*include_masked_server_credit_card=*/true,
                       /*masked_card_is_enrolled_for_virtual_card=*/false);
 
-  const std::string kMaskedServerCardIds[] = {
+  const auto kMaskedServerCardIds = std::to_array<std::string>({
       "12340000-0000-0000-0000-000000000001",
       "12340000-0000-0000-0000-000000000002",
-      "12340000-0000-0000-0000-000000000003"};
+      "12340000-0000-0000-0000-000000000003",
+  });
 
   autofill_manager().AddSeenForm(form, field_types);
 
diff --git a/components/autofill/core/browser/metrics/form_events/address_form_event_logger.cc b/components/autofill/core/browser/metrics/form_events/address_form_event_logger.cc
index 87e399f..8a26161 100644
--- a/components/autofill/core/browser/metrics/form_events/address_form_event_logger.cc
+++ b/components/autofill/core/browser/metrics/form_events/address_form_event_logger.cc
@@ -11,8 +11,8 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_trigger_source.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/logging/log_manager.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics_utils.h"
 #include "components/autofill/core/browser/metrics/form_interactions_ukm_logger.h"
diff --git a/components/autofill/core/browser/metrics/prediction_quality_metrics.cc b/components/autofill/core/browser/metrics/prediction_quality_metrics.cc
index 606920d..804b9ea 100644
--- a/components/autofill/core/browser/metrics/prediction_quality_metrics.cc
+++ b/components/autofill/core/browser/metrics/prediction_quality_metrics.cc
@@ -11,11 +11,11 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/strings/strcat.h"
 #include "components/autofill/core/browser/autofill_field.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/form_parsing/autofill_parsing_utils.h"
 #include "components/autofill/core/browser/form_structure.h"
 #include "components/autofill/core/browser/metrics/form_interactions_ukm_logger.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/dense_set.h"
 #include "components/autofill/core/common/label_source_util.h"
 
diff --git a/components/autofill/core/browser/metrics/profile_deduplication_metrics.cc b/components/autofill/core/browser/metrics/profile_deduplication_metrics.cc
index 65a08ec..1babc68 100644
--- a/components/autofill/core/browser/metrics/profile_deduplication_metrics.cc
+++ b/components/autofill/core/browser/metrics/profile_deduplication_metrics.cc
@@ -23,10 +23,10 @@
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/autofill_profile_comparator.h"
 #include "components/autofill/core/browser/data_model/autofill_structured_address_utils.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics_utils.h"
 #include "components/autofill/core/browser/metrics/profile_token_quality_metrics.h"
-#include "components/autofill/core/browser/profile_token_quality.h"
 #include "components/autofill/core/common/autofill_features.h"
 
 namespace autofill::autofill_metrics {
diff --git a/components/autofill/core/browser/metrics/profile_deduplication_metrics_unittest.cc b/components/autofill/core/browser/metrics/profile_deduplication_metrics_unittest.cc
index 7af840e3..d32a495 100644
--- a/components/autofill/core/browser/metrics/profile_deduplication_metrics_unittest.cc
+++ b/components/autofill/core/browser/metrics/profile_deduplication_metrics_unittest.cc
@@ -8,9 +8,9 @@
 #include "base/test/task_environment.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality_test_api.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics_utils.h"
-#include "components/autofill/core/browser/profile_token_quality_test_api.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/autofill/core/browser/metrics/profile_import_metrics.cc b/components/autofill/core/browser/metrics/profile_import_metrics.cc
index c6ac67f..e9ddf40 100644
--- a/components/autofill/core/browser/metrics/profile_import_metrics.cc
+++ b/components/autofill/core/browser/metrics/profile_import_metrics.cc
@@ -8,9 +8,9 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/strings/strcat.h"
 #include "components/autofill/core/browser/address_data_cleaner.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics_utils.h"
 #include "components/autofill/core/browser/metrics/profile_deduplication_metrics.h"
-#include "components/autofill/core/browser/profile_requirement_utils.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 
 namespace autofill::autofill_metrics {
diff --git a/components/autofill/core/browser/metrics/profile_token_quality_metrics.cc b/components/autofill/core/browser/metrics/profile_token_quality_metrics.cc
index 099808e86..fc34526 100644
--- a/components/autofill/core/browser/metrics/profile_token_quality_metrics.cc
+++ b/components/autofill/core/browser/metrics/profile_token_quality_metrics.cc
@@ -14,11 +14,11 @@
 #include "components/autofill/core/browser/address_data_manager.h"
 #include "components/autofill/core/browser/autofill_field.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality.h"
 #include "components/autofill/core/browser/field_type_utils.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/form_structure.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/browser/profile_token_quality.h"
 #include "components/autofill/core/common/autofill_features.h"
 
 namespace autofill::autofill_metrics {
diff --git a/components/autofill/core/browser/metrics/profile_token_quality_metrics_unittest.cc b/components/autofill/core/browser/metrics/profile_token_quality_metrics_unittest.cc
index 15564c9..a59eacc 100644
--- a/components/autofill/core/browser/metrics/profile_token_quality_metrics_unittest.cc
+++ b/components/autofill/core/browser/metrics/profile_token_quality_metrics_unittest.cc
@@ -9,11 +9,11 @@
 #include "components/autofill/core/browser/address_data_manager.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality_test_api.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/form_structure.h"
 #include "components/autofill/core/browser/form_structure_test_api.h"
-#include "components/autofill/core/browser/profile_token_quality.h"
-#include "components/autofill/core/browser/profile_token_quality_test_api.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/form_data.h"
diff --git a/components/autofill/core/browser/metrics/quality_metrics.cc b/components/autofill/core/browser/metrics/quality_metrics.cc
index f43e30d..18eb88b 100644
--- a/components/autofill/core/browser/metrics/quality_metrics.cc
+++ b/components/autofill/core/browser/metrics/quality_metrics.cc
@@ -10,8 +10,9 @@
 #include "base/containers/contains.h"
 #include "base/containers/flat_map.h"
 #include "base/metrics/histogram_functions.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_field.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/field_type_utils.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/filling_product.h"
@@ -24,7 +25,6 @@
 #include "components/autofill/core/browser/metrics/prediction_quality_metrics.h"
 #include "components/autofill/core/browser/metrics/quality_metrics_filling.h"
 #include "components/autofill/core/browser/metrics/shadow_prediction_metrics.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/optimization_guide/machine_learning_tflite_buildflags.h"
 
diff --git a/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc b/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc
index 26def0f..3435946 100644
--- a/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc
+++ b/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc
@@ -30,6 +30,7 @@
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/metrics/form_events/form_events.h"
 #include "components/autofill/core/browser/metrics/payments/card_unmask_authentication_metrics.h"
 #include "components/autofill/core/browser/payments/full_card_request.h"
@@ -41,7 +42,6 @@
 #include "components/autofill/core/browser/test_autofill_clock.h"
 #include "components/autofill/core/browser/test_autofill_driver.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_features.h"
diff --git a/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc b/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc
index a08be1c..76de7b7 100644
--- a/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc
+++ b/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc
@@ -31,6 +31,7 @@
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/metrics/form_events/form_events.h"
 #include "components/autofill/core/browser/metrics/payments/better_auth_metrics.h"
 #include "components/autofill/core/browser/payments/payments_autofill_client.h"
@@ -45,7 +46,6 @@
 #include "components/autofill/core/browser/test_autofill_driver.h"
 #include "components/autofill/core/browser/test_payments_data_manager.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_features.h"
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager.cc b/components/autofill/core/browser/payments/credit_card_save_manager.cc
index 547f285..f6e5404 100644
--- a/components/autofill/core/browser/payments/credit_card_save_manager.cc
+++ b/components/autofill/core/browser/payments/credit_card_save_manager.cc
@@ -34,6 +34,7 @@
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/form_import/form_data_importer.h"
 #include "components/autofill/core/browser/form_structure.h"
 #include "components/autofill/core/browser/logging/log_manager.h"
@@ -49,7 +50,6 @@
 #include "components/autofill/core/browser/payments_data_manager.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/strike_databases/strike_database.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/autofill/core/common/autofill_features.h"
diff --git a/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc b/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
index 9fb239a..187bbc5 100644
--- a/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
+++ b/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
@@ -27,6 +27,7 @@
 #include "components/autofill/core/browser/crowdsourcing/test_votes_uploader.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/form_import/form_data_importer_test_api.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics.h"
 #include "components/autofill/core/browser/metrics/payments/local_card_migration_metrics.h"
@@ -44,7 +45,6 @@
 #include "components/autofill/core/browser/test_autofill_driver.h"
 #include "components/autofill/core/browser/test_browser_autofill_manager.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_payments_features.h"
diff --git a/components/autofill/core/browser/payments_data_manager.cc b/components/autofill/core/browser/payments_data_manager.cc
index cfbfea7b..edf2599 100644
--- a/components/autofill/core/browser/payments_data_manager.cc
+++ b/components/autofill/core/browser/payments_data_manager.cc
@@ -112,6 +112,27 @@
   });
 }
 
+// TODO(crbug.com/326408802): Move to payments_suggestion_generator.
+std::vector<const CreditCard*> DeduplicatedCreditCardsForSuggestions(
+    base::span<const CreditCard* const> cards_to_suggest) {
+  std::vector<const CreditCard*> deduplicated_cards;
+  for (const CreditCard* card : cards_to_suggest) {
+    // Full server cards should never be suggestions, as they exist only as a
+    // cached state post-fill.
+    CHECK_NE(card->record_type(), CreditCard::RecordType::kFullServerCard);
+    // Masked server cards are preferred over their local duplicates.
+    if (!CreditCard::IsLocalCard(card) ||
+        base::ranges::none_of(
+            cards_to_suggest, [&card](const CreditCard* other_card) {
+              return card != other_card &&
+                     card->IsLocalOrServerDuplicateOf(*other_card);
+            })) {
+      deduplicated_cards.push_back(card);
+    }
+  }
+  return deduplicated_cards;
+}
+
 }  // namespace
 
 // Helper class to abstract the switching between account and profile storage
@@ -1243,32 +1264,22 @@
     credit_cards = GetLocalCreditCards();
   }
 
-  std::list<CreditCard*> cards_to_dedupe(credit_cards.begin(),
-                                         credit_cards.end());
-
-  DedupeCreditCardToSuggest(&cards_to_dedupe);
-
-  std::vector<const CreditCard*> cards_to_suggest(
-      std::make_move_iterator(std::begin(cards_to_dedupe)),
-      std::make_move_iterator(std::end(cards_to_dedupe)));
+  std::vector<const CreditCard*> cards_to_suggest =
+      DeduplicatedCreditCardsForSuggestions(credit_cards);
 
   // Rank the cards by ranking score (see AutofillDataModel for details). All
   // expired cards should be suggested last, also by ranking score.
-  base::Time comparison_time = AutofillClock::Now();
-  if (cards_to_suggest.size() > 1) {
-    std::sort(cards_to_suggest.begin(), cards_to_suggest.end(),
-              [comparison_time, should_use_legacy_algorithm](
-                  const CreditCard* a, const CreditCard* b) {
-                const bool a_is_expired = a->IsExpired(comparison_time);
-                if (a_is_expired != b->IsExpired(comparison_time)) {
-                  return !a_is_expired;
-                }
-
-                return a->HasGreaterRankingThan(*b, comparison_time,
-                                                should_use_legacy_algorithm);
-              });
-  }
-
+  base::ranges::sort(
+      cards_to_suggest,
+      [comparison_time = base::Time::Now(), should_use_legacy_algorithm](
+          const CreditCard* a, const CreditCard* b) {
+        if (const bool a_is_expired = a->IsExpired(comparison_time);
+            a_is_expired != b->IsExpired(comparison_time)) {
+          return !a_is_expired;
+        }
+        return a->HasGreaterRankingThan(*b, comparison_time,
+                                        should_use_legacy_algorithm);
+      });
   return cards_to_suggest;
 }
 
@@ -1679,36 +1690,6 @@
   Refresh();
 }
 
-// The priority ranking for deduping a duplicate card is:
-// 1. RecordType::kMaskedServerCard
-// 2. RecordType::kLocalCard
-// static
-void PaymentsDataManager::DedupeCreditCardToSuggest(
-    std::list<CreditCard*>* cards_to_suggest) {
-  for (auto outer_it = cards_to_suggest->begin();
-       outer_it != cards_to_suggest->end(); ++outer_it) {
-    // Full server cards should never be suggestions, as they exist only as a
-    // cached state post-fill.
-    CHECK_NE((*outer_it)->record_type(),
-             CreditCard::RecordType::kFullServerCard);
-
-    for (auto inner_it = cards_to_suggest->begin();
-         inner_it != cards_to_suggest->end();) {
-      auto inner_it_copy = inner_it++;
-      if (outer_it == inner_it_copy) {
-        continue;
-      }
-      // Check if the cards are local or server duplicate of each other. If yes,
-      // then delete the duplicate if it's a local card.
-      if ((*inner_it_copy)->IsLocalOrServerDuplicateOf(**outer_it) &&
-          (*inner_it_copy)->record_type() ==
-              CreditCard::RecordType::kLocalCard) {
-        cards_to_suggest->erase(inner_it_copy);
-      }
-    }
-  }
-}
-
 scoped_refptr<AutofillWebDataService> PaymentsDataManager::GetLocalDatabase() {
   return database_helper_->GetLocalDatabase();
 }
diff --git a/components/autofill/core/browser/payments_data_manager.h b/components/autofill/core/browser/payments_data_manager.h
index 7c32d0c..98cb225 100644
--- a/components/autofill/core/browser/payments_data_manager.h
+++ b/components/autofill/core/browser/payments_data_manager.h
@@ -246,6 +246,7 @@
   // and ordered by frecency with the expired cards put at the end of the
   // vector. `should_use_legacy_algorithm` indicates if we should rank credit
   // cards using the legacy ranking algorithm.
+  // TODO(crbug.com/326408802): Move to payments_suggestion_generator.
   std::vector<const CreditCard*> GetCreditCardsToSuggest(
       bool should_use_legacy_algorithm = false) const;
 
@@ -329,13 +330,6 @@
   // database accordingly.
   virtual void RecordUseOfIban(Iban& iban);
 
-  // De-dupe credit card to suggest. Full server cards are preferred over their
-  // local duplicates, and local cards are preferred over their masked server
-  // card duplicate.
-  // TODO(crbug.com/326408802): Move to suggestion generator?
-  static void DedupeCreditCardToSuggest(
-      std::list<CreditCard*>* cards_to_suggest);
-
   // Returns the cached card art image for the |card_art_url| if it was synced
   // locally to the client. This function is called within
   // GetCreditCardArtImageForUrl(), but can also be called separately as an
diff --git a/components/autofill/core/browser/payments_data_manager_unittest.cc b/components/autofill/core/browser/payments_data_manager_unittest.cc
index 246f5d0..594b439 100644
--- a/components/autofill/core/browser/payments_data_manager_unittest.cc
+++ b/components/autofill/core/browser/payments_data_manager_unittest.cc
@@ -1240,63 +1240,58 @@
 // Tests that only the masked card is kept when deduping with a local duplicate
 // of it or vice-versa. This is checked based on the value assigned during the
 // for loop.
-TEST_F(PaymentsDataManagerTest, DedupeCreditCardToSuggest_MaskedIsKept) {
-  std::list<CreditCard*> credit_cards;
-
+TEST_F(PaymentsDataManagerTest,
+       GetCreditCardsToSuggest_Deduplication_MaskedIsKept) {
   CreditCard local_card("1141084B-72D7-4B73-90CF-3D6AC154673B",
                         test::kEmptyOrigin);
   test::SetCreditCardInfo(&local_card, "Homer Simpson",
                           "4234567890123456" /* Visa */, "01", "2999", "1");
-  credit_cards.push_back(&local_card);
+  payments_data_manager().AddCreditCard(local_card);
 
   // Create a masked server card that is a duplicate of a local card.
   CreditCard masked_card(CreditCard::RecordType::kMaskedServerCard, "a123");
   test::SetCreditCardInfo(&masked_card, "Homer Simpson", "3456" /* Visa */,
                           "01", "2999", "1");
   masked_card.SetNetworkForMaskedCard(kVisaCard);
-  credit_cards.push_back(&masked_card);
+  test_api(payments_data_manager()).AddServerCreditCard(masked_card);
+  WaitForOnPaymentsDataChanged();
 
-  PaymentsDataManager::DedupeCreditCardToSuggest(&credit_cards);
+  std::vector<const CreditCard*> credit_cards =
+      payments_data_manager().GetCreditCardsToSuggest();
   ASSERT_EQ(1U, credit_cards.size());
-
-  // Verify `masked_card` is returned after deduping `credit_cards` list.
-  EXPECT_EQ(*credit_cards.front(), masked_card);
+  EXPECT_EQ(0, credit_cards.front()->Compare(masked_card));
 }
 
 // Tests that different local and server credit cards are not deduped.
-TEST_F(PaymentsDataManagerTest, DedupeCreditCardToSuggest_DifferentCards) {
-  std::list<CreditCard*> credit_cards;
-
+TEST_F(PaymentsDataManagerTest,
+       GetCreditCardsToSuggest_Deduplication_DifferentCards) {
   CreditCard local_card("002149C1-EE28-4213-A3B9-DA243FFF021B",
                         test::kEmptyOrigin);
-  local_card.set_use_count(1);
-  local_card.set_use_date(AutofillClock::Now() - base::Days(1));
   test::SetCreditCardInfo(&local_card, "Homer Simpson",
                           "5105105105105100" /* Mastercard */, "", "", "");
-  credit_cards.push_back(&local_card);
+  payments_data_manager().AddCreditCard(local_card);
 
   // Create a masked server card that is different from the local card.
   CreditCard masked_card(CreditCard::RecordType::kMaskedServerCard, "b456");
   test::SetCreditCardInfo(&masked_card, "Homer Simpson", "0005", "12", "2999",
                           "1");
-  masked_card.set_use_count(3);
-  masked_card.set_use_date(AutofillClock::Now() - base::Days(15));
-  credit_cards.push_back(&masked_card);
+  test_api(payments_data_manager()).AddServerCreditCard(masked_card);
+  WaitForOnPaymentsDataChanged();
 
-  PaymentsDataManager::DedupeCreditCardToSuggest(&credit_cards);
+  std::vector<const CreditCard*> credit_cards =
+      payments_data_manager().GetCreditCardsToSuggest();
   EXPECT_EQ(2U, credit_cards.size());
 }
 
 // Tests case-insensitive deduping of the name field, i.e. the server card is
 // kept for duplicate cards except different name casing.
-TEST_F(PaymentsDataManagerTest, DedupeCreditCardToSuggest_CaseInsensitiveName) {
-  std::list<CreditCard*> credit_cards;
-
+TEST_F(PaymentsDataManagerTest,
+       GetCreditCardsToSuggest_Deduplication_CaseInsensitiveName) {
   CreditCard local_card("1141084B-72D7-4B73-90CF-3D6AC154673B",
                         test::kEmptyOrigin);
   test::SetCreditCardInfo(&local_card, "homer simpson",
                           "4234567890123456" /* Visa */, "01", "2999", "1");
-  credit_cards.push_back(&local_card);
+  payments_data_manager().AddCreditCard(local_card);
 
   // Create a masked server card that is a duplicate of a local card except name
   // casing.
@@ -1304,13 +1299,15 @@
   test::SetCreditCardInfo(&masked_card, "Homer Simpson", "3456" /* Visa */,
                           "01", "2999", "1");
   masked_card.SetNetworkForMaskedCard(kVisaCard);
-  credit_cards.push_back(&masked_card);
+  test_api(payments_data_manager()).AddServerCreditCard(masked_card);
+  WaitForOnPaymentsDataChanged();
 
-  PaymentsDataManager::DedupeCreditCardToSuggest(&credit_cards);
+  std::vector<const CreditCard*> credit_cards =
+      payments_data_manager().GetCreditCardsToSuggest();
   ASSERT_EQ(1U, credit_cards.size());
 
   // Verify `masked_card` is returned after deduping `credit_cards` list.
-  EXPECT_EQ(*credit_cards.front(), masked_card);
+  EXPECT_EQ(0, credit_cards.front()->Compare(masked_card));
 }
 
 TEST_F(PaymentsDataManagerTest, DeleteLocalCreditCards) {
diff --git a/components/autofill/core/browser/suggestions/addresses/address_suggestion_generator.cc b/components/autofill/core/browser/suggestions/addresses/address_suggestion_generator.cc
index 677737a..37010c9 100644
--- a/components/autofill/core/browser/suggestions/addresses/address_suggestion_generator.cc
+++ b/components/autofill/core/browser/suggestions/addresses/address_suggestion_generator.cc
@@ -24,10 +24,10 @@
 #include "components/autofill/core/browser/address_data_manager.h"
 #include "components/autofill/core/browser/autofill_browser_util.h"
 #include "components/autofill/core/browser/autofill_client.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/autofill_profile_comparator.h"
 #include "components/autofill/core/browser/data_model/borrowed_transliterator.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/field_type_utils.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/filling/addresses/field_filling_address_util.h"
diff --git a/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator.cc b/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator.cc
index 497423b8..9e4bb14 100644
--- a/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator.cc
+++ b/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator.cc
@@ -22,13 +22,13 @@
 #include "build/build_config.h"
 #include "components/autofill/core/browser/autofill_browser_util.h"
 #include "components/autofill/core/browser/autofill_client.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_experiments.h"
 #include "components/autofill/core/browser/autofill_optimization_guide.h"
 #include "components/autofill/core/browser/data_model/autofill_offer_data.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/autofill/core/browser/data_model/credit_card_benefit.h"
 #include "components/autofill/core/browser/data_model/iban.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/field_type_utils.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/form_structure.h"
diff --git a/components/autofill/core/browser/test_autofill_client.h b/components/autofill/core/browser/test_autofill_client.h
index 73da6ef..fbbfe6ae 100644
--- a/components/autofill/core/browser/test_autofill_client.h
+++ b/components/autofill/core/browser/test_autofill_client.h
@@ -29,6 +29,7 @@
 #include "components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h"
 #include "components/autofill/core/browser/crowdsourcing/mock_autofill_crowdsourcing_manager.h"
 #include "components/autofill/core/browser/crowdsourcing/test_votes_uploader.h"
+#include "components/autofill/core/browser/data_quality/addresses/test_address_normalizer.h"
 #include "components/autofill/core/browser/logging/log_manager.h"
 #include "components/autofill/core/browser/logging/log_router.h"
 #include "components/autofill/core/browser/logging/text_log_receiver.h"
@@ -43,7 +44,6 @@
 #include "components/autofill/core/browser/payments/test_payments_network_interface.h"
 #include "components/autofill/core/browser/single_field_fill_router.h"
 #include "components/autofill/core/browser/strike_databases/payments/test_strike_database.h"
-#include "components/autofill/core/browser/test_address_normalizer.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
 #include "components/autofill/core/browser/ui/mock_fast_checkout_client.h"
 #include "components/autofill/core/browser/ui/payments/card_unmask_prompt_options.h"
@@ -319,8 +319,9 @@
 
   void HideAutofillFieldIph() override { autofill_iph_showing_ = std::nullopt; }
 
-  bool IsShowingManualFallbackIph() {
-    return autofill_iph_showing_ == AutofillClient::IphFeature::kManualFallback;
+  bool IsShowingPredictionImprovementsIph() {
+    return autofill_iph_showing_ ==
+           AutofillClient::IphFeature::kPredictionImprovements;
   }
 
   void NotifyIphFeatureUsed(AutofillClient::IphFeature feature) override {
diff --git a/components/autofill/core/browser/test_browser_autofill_manager.cc b/components/autofill/core/browser/test_browser_autofill_manager.cc
index 1c5f55b..e8ea262 100644
--- a/components/autofill/core/browser/test_browser_autofill_manager.cc
+++ b/components/autofill/core/browser/test_browser_autofill_manager.cc
@@ -27,8 +27,7 @@
 
 TestBrowserAutofillManager::TestBrowserAutofillManager(AutofillDriver* driver)
     : BrowserAutofillManager(driver) {
-  test_api(*this).set_form_filler(
-      std::make_unique<TestFormFiller>(*this, log_manager()));
+  test_api(*this).set_form_filler(std::make_unique<TestFormFiller>(*this));
 }
 
 TestBrowserAutofillManager::~TestBrowserAutofillManager() = default;
diff --git a/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.cc b/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.cc
index 1d5dc31..fc1748b 100644
--- a/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.cc
+++ b/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.cc
@@ -16,9 +16,9 @@
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "components/autofill/core/browser/autofill_experiments.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics.h"
 #include "components/autofill/core/browser/ui/payments/card_unmask_prompt_view.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_payments_features.h"
diff --git a/components/autofill/core/browser/ui/suggestion.cc b/components/autofill/core/browser/ui/suggestion.cc
index 5377003b..94e19c5 100644
--- a/components/autofill/core/browser/ui/suggestion.cc
+++ b/components/autofill/core/browser/ui/suggestion.cc
@@ -169,32 +169,27 @@
 
 Suggestion::PlusAddressPayload::~PlusAddressPayload() = default;
 
-Suggestion::PredictionImprovementsPayload::PredictionImprovementsPayload() =
-    default;
+Suggestion::AutofillAiPayload::AutofillAiPayload() = default;
 
-Suggestion::PredictionImprovementsPayload::PredictionImprovementsPayload(
+Suggestion::AutofillAiPayload::AutofillAiPayload(
     const base::flat_map<FieldGlobalId, std::u16string>& values_to_fill,
     const DenseSet<FieldFillingSkipReason>& ignorable_skip_reasons)
     : values_to_fill(std::move(values_to_fill)),
       ignorable_skip_reasons(std::move(ignorable_skip_reasons)) {}
 
-Suggestion::PredictionImprovementsPayload::PredictionImprovementsPayload(
-    const PredictionImprovementsPayload&) = default;
-
-Suggestion::PredictionImprovementsPayload::PredictionImprovementsPayload(
-    PredictionImprovementsPayload&&) = default;
-
-Suggestion::PredictionImprovementsPayload&
-Suggestion::PredictionImprovementsPayload::operator=(
-    const PredictionImprovementsPayload&) = default;
-
-Suggestion::PredictionImprovementsPayload&
-Suggestion::PredictionImprovementsPayload::operator=(
-    PredictionImprovementsPayload&&) = default;
-
-Suggestion::PredictionImprovementsPayload::~PredictionImprovementsPayload() =
+Suggestion::AutofillAiPayload::AutofillAiPayload(const AutofillAiPayload&) =
     default;
 
+Suggestion::AutofillAiPayload::AutofillAiPayload(AutofillAiPayload&&) = default;
+
+Suggestion::AutofillAiPayload& Suggestion::AutofillAiPayload::operator=(
+    const AutofillAiPayload&) = default;
+
+Suggestion::AutofillAiPayload& Suggestion::AutofillAiPayload::operator=(
+    AutofillAiPayload&&) = default;
+
+Suggestion::AutofillAiPayload::~AutofillAiPayload() = default;
+
 Suggestion::AutofillProfilePayload::AutofillProfilePayload() = default;
 Suggestion::AutofillProfilePayload::AutofillProfilePayload(Guid guid)
     : AutofillProfilePayload(std::move(guid), u"") {}
diff --git a/components/autofill/core/browser/ui/suggestion.h b/components/autofill/core/browser/ui/suggestion.h
index eedee8f..541c54d 100644
--- a/components/autofill/core/browser/ui/suggestion.h
+++ b/components/autofill/core/browser/ui/suggestion.h
@@ -79,20 +79,19 @@
     bool offer_refresh = true;
   };
 
-  struct PredictionImprovementsPayload final {
-    PredictionImprovementsPayload();
-    PredictionImprovementsPayload(
+  struct AutofillAiPayload final {
+    AutofillAiPayload();
+    AutofillAiPayload(
         const base::flat_map<FieldGlobalId, std::u16string>& values_to_fill,
         const DenseSet<FieldFillingSkipReason>& ignorable_skip_reasons);
-    PredictionImprovementsPayload(const PredictionImprovementsPayload&);
-    PredictionImprovementsPayload(PredictionImprovementsPayload&&);
-    PredictionImprovementsPayload& operator=(
-        const PredictionImprovementsPayload&);
-    PredictionImprovementsPayload& operator=(PredictionImprovementsPayload&&);
-    ~PredictionImprovementsPayload();
+    AutofillAiPayload(const AutofillAiPayload&);
+    AutofillAiPayload(AutofillAiPayload&&);
+    AutofillAiPayload& operator=(const AutofillAiPayload&);
+    AutofillAiPayload& operator=(AutofillAiPayload&&);
+    ~AutofillAiPayload();
 
-    friend bool operator==(const PredictionImprovementsPayload&,
-                           const PredictionImprovementsPayload&) = default;
+    friend bool operator==(const AutofillAiPayload&,
+                           const AutofillAiPayload&) = default;
 
     // Values to be filled into fields with corresponding ids.
     base::flat_map<FieldGlobalId, std::u16string> values_to_fill;
@@ -154,7 +153,7 @@
                                 ValueToFill,
                                 PasswordSuggestionDetails,
                                 PlusAddressPayload,
-                                PredictionImprovementsPayload,
+                                AutofillAiPayload,
                                 PaymentsPayload>;
 
   // This struct is used to provide password suggestions with custom icons,
@@ -373,7 +372,7 @@
                absl::holds_alternative<InstrumentId>(payload);
       case SuggestionType::kFillAutofillAi:
         return absl::holds_alternative<ValueToFill>(payload) ||
-               absl::holds_alternative<PredictionImprovementsPayload>(payload);
+               absl::holds_alternative<AutofillAiPayload>(payload);
       case SuggestionType::kCreditCardEntry:
       case SuggestionType::kVirtualCreditCardEntry:
         // TODO(crbug.com/367434234): Use `PaymentsPayload` for all credit card
diff --git a/components/autofill/core/browser/webdata/addresses/address_autofill_table_unittest.cc b/components/autofill/core/browser/webdata/addresses/address_autofill_table_unittest.cc
index a7afe1a..f74ebcd 100644
--- a/components/autofill/core/browser/webdata/addresses/address_autofill_table_unittest.cc
+++ b/components/autofill/core/browser/webdata/addresses/address_autofill_table_unittest.cc
@@ -19,9 +19,9 @@
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/country_type.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality_test_api.h"
 #include "components/autofill/core/browser/field_types.h"
-#include "components/autofill/core/browser/profile_token_quality.h"
-#include "components/autofill/core/browser/profile_token_quality_test_api.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/webdata/common/web_database.h"
 #include "sql/statement.h"
diff --git a/components/autofill/core/browser/webdata/addresses/autofill_profile_sync_util.cc b/components/autofill/core/browser/webdata/addresses/autofill_profile_sync_util.cc
index 009aa7f..3e9f782 100644
--- a/components/autofill/core/browser/webdata/addresses/autofill_profile_sync_util.cc
+++ b/components/autofill/core/browser/webdata/addresses/autofill_profile_sync_util.cc
@@ -7,9 +7,9 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/uuid.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/autofill_structured_address_component.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/geo/country_names.h"
 #include "components/autofill/core/browser/proto/autofill_sync.pb.h"
diff --git a/components/autofill/core/browser/webdata/addresses/contact_info_local_data_batch_uploader.cc b/components/autofill/core/browser/webdata/addresses/contact_info_local_data_batch_uploader.cc
index 83e484e..8cca2f1 100644
--- a/components/autofill/core/browser/webdata/addresses/contact_info_local_data_batch_uploader.cc
+++ b/components/autofill/core/browser/webdata/addresses/contact_info_local_data_batch_uploader.cc
@@ -8,8 +8,8 @@
 #include "base/functional/callback.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/autofill/core/browser/address_data_manager.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.h"
 #include "components/autofill/core/browser/field_types.h"
-#include "components/autofill/core/browser/profile_requirement_utils.h"
 #include "components/sync/base/data_type.h"
 #include "components/sync/service/local_data_description.h"
 
diff --git a/components/autofill/core/browser/webdata/addresses/contact_info_local_data_batch_uploader_unittest.cc b/components/autofill/core/browser/webdata/addresses/contact_info_local_data_batch_uploader_unittest.cc
index c089dbb..2c7fdd53 100644
--- a/components/autofill/core/browser/webdata/addresses/contact_info_local_data_batch_uploader_unittest.cc
+++ b/components/autofill/core/browser/webdata/addresses/contact_info_local_data_batch_uploader_unittest.cc
@@ -9,7 +9,7 @@
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/autofill_profile_test_api.h"
-#include "components/autofill/core/browser/profile_requirement_utils.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.h"
 #include "components/autofill/core/browser/test_address_data_manager.h"
 #include "components/sync/service/local_data_description.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/components/autofill/core/browser/webdata/addresses/contact_info_sync_util.cc b/components/autofill/core/browser/webdata/addresses/contact_info_sync_util.cc
index 27f6ab45..43c7662 100644
--- a/components/autofill/core/browser/webdata/addresses/contact_info_sync_util.cc
+++ b/components/autofill/core/browser/webdata/addresses/contact_info_sync_util.cc
@@ -10,9 +10,9 @@
 #include "base/time/time.h"
 #include "base/uuid.h"
 #include "components/autofill/core/browser/country_type.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/geo/country_names.h"
-#include "components/autofill/core/browser/profile_token_quality.h"
 #include "components/autofill/core/common/autofill_features.h"
 
 namespace autofill {
diff --git a/components/autofill/core/browser/webdata/addresses/contact_info_sync_util_unittest.cc b/components/autofill/core/browser/webdata/addresses/contact_info_sync_util_unittest.cc
index 5acfaf7..451a78b 100644
--- a/components/autofill/core/browser/webdata/addresses/contact_info_sync_util_unittest.cc
+++ b/components/autofill/core/browser/webdata/addresses/contact_info_sync_util_unittest.cc
@@ -11,8 +11,8 @@
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/country_type.h"
 #include "components/autofill/core/browser/data_model/autofill_profile_test_api.h"
+#include "components/autofill/core/browser/data_quality/addresses/profile_token_quality_test_api.h"
 #include "components/autofill/core/browser/field_types.h"
-#include "components/autofill/core/browser/profile_token_quality_test_api.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/components/autofill/core/browser/webdata/payments/payments_sync_bridge_util.cc b/components/autofill/core/browser/webdata/payments/payments_sync_bridge_util.cc
index 25a4a14..0c0339b 100644
--- a/components/autofill/core/browser/webdata/payments/payments_sync_bridge_util.cc
+++ b/components/autofill/core/browser/webdata/payments/payments_sync_bridge_util.cc
@@ -14,7 +14,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/country_type.h"
 #include "components/autofill/core/browser/data_model/autofill_offer_data.h"
 #include "components/autofill/core/browser/data_model/autofill_wallet_usage_data.h"
@@ -23,6 +22,7 @@
 #include "components/autofill/core/browser/data_model/credit_card_cloud_token_data.h"
 #include "components/autofill/core/browser/data_model/iban.h"
 #include "components/autofill/core/browser/data_model/payment_instrument.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/payments/payments_customer_data.h"
 #include "components/autofill/core/browser/webdata/payments/payments_autofill_table.h"
 #include "components/autofill/core/common/autofill_payments_features.h"
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc
index a13a5bd6..bcb0097a 100644
--- a/components/autofill/core/common/autofill_features.cc
+++ b/components/autofill/core/common/autofill_features.cc
@@ -99,15 +99,6 @@
              "AutofillEnableAddressFieldParserNG",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-// When enabled, autofill displays an IPH informing users about using autofill
-// from the context menu. The IPH will be attached to address fields with
-// autocomplete="garbage".
-// TODO(crbug.com/313587343) Remove once manual fallback IPH feature is
-// launched.
-BASE_FEATURE(kAutofillEnableManualFallbackIPH,
-             "AutofillEnableManualFallbackIPH",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
 // Controls if the heuristic field parsing utilizes shared labels.
 // TODO(crbug.com/40741721): Remove once shared labels are launched.
 BASE_FEATURE(kAutofillEnableSupportForParsingWithSharedLabels,
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h
index ac1a1421..5c75cc0 100644
--- a/components/autofill/core/common/autofill_features.h
+++ b/components/autofill/core/common/autofill_features.h
@@ -30,8 +30,6 @@
 BASE_DECLARE_FEATURE(kAutofillEnableAccountStorageForIneligibleCountries);
 COMPONENT_EXPORT(AUTOFILL)
 BASE_DECLARE_FEATURE(kAutofillEnableAddressFieldParserNG);
-COMPONENT_EXPORT(AUTOFILL)
-BASE_DECLARE_FEATURE(kAutofillEnableManualFallbackIPH);
 COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillDisableFilling);
 COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillDisableAddressImport);
 COMPONENT_EXPORT(AUTOFILL)
diff --git a/components/autofill/ios/browser/autofill_across_iframes_unittest.mm b/components/autofill/ios/browser/autofill_across_iframes_unittest.mm
index a487d74..0f0208e9 100644
--- a/components/autofill/ios/browser/autofill_across_iframes_unittest.mm
+++ b/components/autofill/ios/browser/autofill_across_iframes_unittest.mm
@@ -639,8 +639,7 @@
     web::WebFrame* trigger_frame =
         GetFrameForFieldWithIdAttr(trigger_field.id_attribute, fields);
     ASSERT_TRUE(trigger_frame);
-    url::Origin trigger_origin =
-        url::Origin::Create(trigger_frame->GetSecurityOriginDeprecated());
+    url::Origin trigger_origin = trigger_frame->GetSecurityOrigin();
     base::flat_set<FieldGlobalId> filled_field_ids =
         GetDriverForFrame(trigger_frame)
             ->ApplyFormAction(mojom::FormActionType::kFill,
diff --git a/components/autofill/ios/browser/autofill_agent.mm b/components/autofill/ios/browser/autofill_agent.mm
index 6d53f014..6cd61a1 100644
--- a/components/autofill/ios/browser/autofill_agent.mm
+++ b/components/autofill/ios/browser/autofill_agent.mm
@@ -1230,8 +1230,8 @@
 
   // Necessary so the values can be used inside a block.
   GURL pageURL = _webState->GetLastCommittedURL();
-  GURL frameOrigin = frame ? frame->GetSecurityOriginDeprecated()
-                           : pageURL.DeprecatedGetOriginAsURL();
+  url::Origin frameOrigin =
+      frame ? frame->GetSecurityOrigin() : url::Origin::Create(pageURL);
 
   if (auto* driver = autofill::AutofillDriverIOS::FromWebStateAndWebFrame(
           _webState, frame)) {
@@ -1242,7 +1242,7 @@
       FieldDataManagerFactoryIOS::GetRetainable(frame);
   const auto callback = [](FormFetchCompletion completion, BOOL filtered,
                            const std::u16string& formName, const GURL& pageURL,
-                           const GURL& frameOrigin,
+                           const url::Origin& frameOrigin,
                            scoped_refptr<FieldDataManager> fieldDataManager,
                            const std::string& frame_id, NSString* formJSON) {
     std::optional<std::vector<FormData>> formData =
diff --git a/components/autofill/ios/browser/autofill_driver_ios.mm b/components/autofill/ios/browser/autofill_driver_ios.mm
index 1aaf275f8..c581c28 100644
--- a/components/autofill/ios/browser/autofill_driver_ios.mm
+++ b/components/autofill/ios/browser/autofill_driver_ios.mm
@@ -174,8 +174,8 @@
   // frame on the same origin as the main frame.
   if (parent_ && parent_->web_frame() && parent_->IsInAnyMainFrame() &&
       web_frame()) {
-    return parent_->web_frame()->GetSecurityOriginDeprecated() ==
-           web_frame()->GetSecurityOriginDeprecated();
+    return parent_->web_frame()->GetSecurityOrigin() ==
+           web_frame()->GetSecurityOrigin();
   }
 
   // Return false as share-autofill is not allowed.
diff --git a/components/autofill/ios/browser/autofill_java_script_feature.mm b/components/autofill/ios/browser/autofill_java_script_feature.mm
index 1756a2c..e3b5104 100644
--- a/components/autofill/ios/browser/autofill_java_script_feature.mm
+++ b/components/autofill/ios/browser/autofill_java_script_feature.mm
@@ -157,11 +157,10 @@
   const scoped_refptr<FieldDataManager> field_data_manager =
       FieldDataManagerFactoryIOS::GetRetainable(frame);
 
-  if (std::optional<autofill::FormData> form_data =
-          ExtractFormData(*form_dict, /*filtered=*/false, /*form_name=*/u"",
-                          web_state->GetLastCommittedURL(),
-                          frame->GetSecurityOriginDeprecated(),
-                          *field_data_manager, frame->GetFrameId())) {
+  if (std::optional<autofill::FormData> form_data = ExtractFormData(
+          *form_dict, /*filtered=*/false, /*form_name=*/u"",
+          web_state->GetLastCommittedURL(), frame->GetSecurityOrigin(),
+          *field_data_manager, frame->GetFrameId())) {
     driver->DidFillAutofillFormData(*std::move(form_data),
                                     base::TimeTicks::Now());
   }
diff --git a/components/autofill/ios/browser/autofill_util.h b/components/autofill/ios/browser/autofill_util.h
index f303589..1044cb98f 100644
--- a/components/autofill/ios/browser/autofill_util.h
+++ b/components/autofill/ios/browser/autofill_util.h
@@ -15,6 +15,10 @@
 
 class GURL;
 
+namespace url {
+class Origin;
+}
+
 namespace web {
 class WebFramesManager;
 class WebState;
@@ -53,7 +57,7 @@
     bool filtered,
     const std::u16string& form_name,
     const GURL& main_frame_url,
-    const GURL& frame_origin,
+    const url::Origin& frame_origin,
     const FieldDataManager& field_data_manager,
     const std::string& frame_id,
     LocalFrameToken host_frame = LocalFrameToken());
@@ -71,7 +75,7 @@
     bool filtered,
     const std::u16string& form_name,
     const GURL& main_frame_url,
-    const GURL& form_frame_origin,
+    const url::Origin& form_frame_origin,
     const FieldDataManager& field_data_manager,
     const std::string& frame_id,
     LocalFrameToken host_frame = LocalFrameToken());
diff --git a/components/autofill/ios/browser/autofill_util.mm b/components/autofill/ios/browser/autofill_util.mm
index 763650c..b6a1836 100644
--- a/components/autofill/ios/browser/autofill_util.mm
+++ b/components/autofill/ios/browser/autofill_util.mm
@@ -121,7 +121,7 @@
     bool filtered,
     const std::u16string& form_name,
     const GURL& main_frame_url,
-    const GURL& frame_origin,
+    const url::Origin& frame_origin,
     const FieldDataManager& field_data_manager,
     const std::string& frame_id,
     LocalFrameToken host_frame) {
@@ -160,7 +160,7 @@
     bool filtered,
     const std::u16string& form_name,
     const GURL& main_frame_url,
-    const GURL& form_frame_origin,
+    const url::Origin& form_frame_origin,
     const FieldDataManager& field_data_manager,
     const std::string& frame_id,
     LocalFrameToken host_frame) {
@@ -184,7 +184,7 @@
 
   // Use GURL object to verify origin of host frame URL.
   form_data.set_url(GURL(origin));
-  if (form_data.url().DeprecatedGetOriginAsURL() != form_frame_origin) {
+  if (!form_frame_origin.IsSameOriginWith(form_data.url())) {
     return std::nullopt;
   }
 
@@ -192,8 +192,7 @@
       base::FeatureList::IsEnabled(features::kAutofillAcrossIframesIos);
 
   const url::Origin frame_origin_object =
-      include_frame_metadata ? url::Origin::Create(form_frame_origin)
-                             : url::Origin();
+      include_frame_metadata ? form_frame_origin : url::Origin();
 
   // Frame ID of the frame containing this form is mandatory.
   const std::string* host_frame_param = form.FindString("host_frame");
diff --git a/components/autofill/ios/form_util/form_activity_tab_helper.mm b/components/autofill/ios/form_util/form_activity_tab_helper.mm
index 4fa25b0..60b9be61 100644
--- a/components/autofill/ios/form_util/form_activity_tab_helper.mm
+++ b/components/autofill/ios/form_util/form_activity_tab_helper.mm
@@ -130,8 +130,8 @@
     return std::nullopt;
   }
 
-  if (isolated_world_frame->GetSecurityOriginDeprecated() !=
-      page_world_frame->GetSecurityOriginDeprecated()) {
+  if (isolated_world_frame->GetSecurityOrigin() !=
+      page_world_frame->GetSecurityOrigin()) {
     return std::nullopt;
   }
 
@@ -303,9 +303,8 @@
   // `local_frame_token`.
   std::optional<std::vector<FormData>> forms = autofill::ExtractFormsData(
       base::SysUTF8ToNSString(form_data), true, base::UTF8ToUTF16(form_name),
-      web_state->GetLastCommittedURL(),
-      sender_frame->GetSecurityOriginDeprecated(), *fieldDataManager, *frame_id,
-      local_frame_token);
+      web_state->GetLastCommittedURL(), sender_frame->GetSecurityOrigin(),
+      *fieldDataManager, *frame_id, local_frame_token);
   if (!forms || forms->size() != 1) {
     return;
   }
diff --git a/components/autofill_ai/core/browser/autofill_ai_manager_unittest.cc b/components/autofill_ai/core/browser/autofill_ai_manager_unittest.cc
index 86231cb..864c7b2 100644
--- a/components/autofill_ai/core/browser/autofill_ai_manager_unittest.cc
+++ b/components/autofill_ai/core/browser/autofill_ai_manager_unittest.cc
@@ -39,7 +39,7 @@
 using ::autofill::Suggestion;
 using ::autofill::SuggestionType;
 using enum SuggestionType;
-using PredictionImprovementsPayload = Suggestion::PredictionImprovementsPayload;
+using AutofillAiPayload = Suggestion::AutofillAiPayload;
 using PredictionsByGlobalId = AutofillAiModelExecutor::PredictionsByGlobalId;
 using ::base::test::RunOnceCallback;
 using ::testing::_;
@@ -69,9 +69,9 @@
   return Field("Suggestion::type", &Suggestion::type, Eq(expected_type));
 }
 
-auto HasPredictionImprovementsPayload(auto expected_payload) {
+auto HasAutofillAiPayload(auto expected_payload) {
   return Field("Suggestion::payload", &Suggestion::payload,
-               VariantWith<PredictionImprovementsPayload>(expected_payload));
+               VariantWith<AutofillAiPayload>(expected_payload));
 }
 
 auto HasValueToFill(const std::u16string& expected_value_to_fill) {
@@ -322,8 +322,8 @@
         update_suggestions_callback,
         Run(AllOf(ElementsAre(HasType(kFillAutofillAi), HasType(kSeparator),
                               HasType(kAutofillAiFeedback)),
-                  FirstElementIs(HasPredictionImprovementsPayload(
-                      Field(&PredictionImprovementsPayload::values_to_fill,
+                  FirstElementIs(HasAutofillAiPayload(
+                      Field(&AutofillAiPayload::values_to_fill,
                             ElementsAre(Pair(filled_field.global_id(),
                                              filled_field.value()))))),
                   FirstElementIs(Field(
@@ -673,29 +673,29 @@
       ElementsAre(
           AllOf(
               HasType(kFillAutofillAi),
-              HasPredictionImprovementsPayload(Field(
-                  "PredictionImprovementsPayload::values_to_fill",
-                  &PredictionImprovementsPayload::values_to_fill,
+              HasAutofillAiPayload(Field(
+                  "AutofillAiPayload::values_to_fill",
+                  &AutofillAiPayload::values_to_fill,
                   ElementsAre(
                       Pair(form.fields()[0].global_id(), trigger_field_value),
                       Pair(form.fields()[1].global_id(), select_field_value)))),
-              Field("Suggestion::children", &Suggestion::children,
-                    ElementsAre(AllOf(HasType(kFillAutofillAi),
-                                      HasPredictionImprovementsPayload(_)),
-                                HasType(kSeparator),
-                                AllOf(HasType(kFillAutofillAi),
-                                      HasValueToFill(trigger_field_value),
-                                      HasMainText(trigger_field_value),
-                                      HasLabel(trigger_field_label)),
-                                AllOf(HasType(kFillAutofillAi),
-                                      // For <select> elements expect both value
-                                      // to fill and main text to be set to the
-                                      // option text, not the value.
-                                      HasValueToFill(select_field_option_text),
-                                      HasMainText(select_field_option_text),
-                                      HasLabel(select_field_label)),
-                                HasType(kSeparator),
-                                HasType(kEditAutofillAiData)))),
+              Field(
+                  "Suggestion::children", &Suggestion::children,
+                  ElementsAre(
+                      AllOf(HasType(kFillAutofillAi), HasAutofillAiPayload(_)),
+                      HasType(kSeparator),
+                      AllOf(HasType(kFillAutofillAi),
+                            HasValueToFill(trigger_field_value),
+                            HasMainText(trigger_field_value),
+                            HasLabel(trigger_field_label)),
+                      AllOf(HasType(kFillAutofillAi),
+                            // For <select> elements expect both value
+                            // to fill and main text to be set to the
+                            // option text, not the value.
+                            HasValueToFill(select_field_option_text),
+                            HasMainText(select_field_option_text),
+                            HasLabel(select_field_label)),
+                      HasType(kSeparator), HasType(kEditAutofillAiData)))),
           HasType(kSeparator), HasType(kAutofillAiFeedback)));
 }
 
diff --git a/components/autofill_ai/core/browser/suggestion/autofill_ai_suggestions.cc b/components/autofill_ai/core/browser/suggestion/autofill_ai_suggestions.cc
index ff600f50..5940ebcfa 100644
--- a/components/autofill_ai/core/browser/suggestion/autofill_ai_suggestions.cc
+++ b/components/autofill_ai/core/browser/suggestion/autofill_ai_suggestions.cc
@@ -82,7 +82,7 @@
 // Creates a full form filling suggestion that will be displayed first in the
 // sub popup.
 autofill::Suggestion CreateFillAllSuggestion(
-    const autofill::Suggestion::PredictionImprovementsPayload& payload) {
+    const autofill::Suggestion::AutofillAiPayload& payload) {
   autofill::Suggestion fill_all_suggestion(
       l10n_util::GetStringUTF16(
           IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_FILL_ALL_MAIN_TEXT),
@@ -270,8 +270,8 @@
       cache.at(field.global_id());
   autofill::Suggestion suggestion(prediction.value,
                                   autofill::SuggestionType::kFillAutofillAi);
-  auto payload = autofill::Suggestion::PredictionImprovementsPayload(
-      GetValuesToFill(cache), kIgnorableSkipReasons);
+  auto payload = autofill::Suggestion::AutofillAiPayload(GetValuesToFill(cache),
+                                                         kIgnorableSkipReasons);
   suggestion.payload = payload;
   suggestion.icon = autofill::Suggestion::Icon::kAutofillPredictionImprovements;
 
diff --git a/components/autofill_strings.grdp b/components/autofill_strings.grdp
index 74de212..68d639f 100644
--- a/components/autofill_strings.grdp
+++ b/components/autofill_strings.grdp
@@ -232,12 +232,6 @@
   <message name="IDS_AUTOFILL_IPH_EXTERNAL_ACCOUNT_PROFILE_SUGGESTION" desc="IPH bubble for a suggestion item with an account profile that was created somewhere outside Chrome (e.g. Google Pay)." formatter_data="android_java">
     You can now use addresses from your Google Account
   </message>
-  <message name="IDS_AUTOFILL_IPH_MANUAL_FALLBACK" desc="IPH bubble for triggering autofill from the context menu.">
-    Right click to autofill saved info, like your name or address, on any form
-  </message>
-  <message name="IDS_AUTOFILL_IPH_MANUAL_FALLBACK_SCREENREADER" is_accessibility_with_no_ui="true" desc="Screenreader text for the IPH bubble for triggering autofill from the context menu.">
-    Right click to autofill saved info, like your name or address, on any form
-  </message>
 
   <!-- Autofill suggestion label separator -->
   <message name="IDS_AUTOFILL_SUGGESTION_LABEL_SEPARATOR" desc="A separator to place between different elements of a suggestion's label. Labels sometimes have more than one type of information, such as a phone number and an email address or a street address, a phone number, and an email address. A symbol, in this case a bullet •, with a white space before it and a white space after it, is used to separate the parts of the label that appear on the same line, e.g. (877) 733-7699 • fanfeedback@redsox.com or 465 Huntington Ave • (617) 267-9300 • matthewt@mfa.org. A bullet • is preferred for separating the label parts; however, if the bullet • resembles another symbol in the language, please translate the bullet • as a symbol (A) that is not easily mistaken for a number or letter in the language and (B) that is typically used to separate elements.">
diff --git a/components/autofill_strings_grdp/IDS_AUTOFILL_IPH_MANUAL_FALLBACK.png.sha1 b/components/autofill_strings_grdp/IDS_AUTOFILL_IPH_MANUAL_FALLBACK.png.sha1
deleted file mode 100644
index 0ab7323..0000000
--- a/components/autofill_strings_grdp/IDS_AUTOFILL_IPH_MANUAL_FALLBACK.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-07c8d00708a20541d06932bd099a83ca89fd633e
\ No newline at end of file
diff --git a/components/autofill_strings_grdp/IDS_AUTOFILL_IPH_MANUAL_FALLBACK_SCREENREADER.png.sha1 b/components/autofill_strings_grdp/IDS_AUTOFILL_IPH_MANUAL_FALLBACK_SCREENREADER.png.sha1
deleted file mode 100644
index 369c4d03..0000000
--- a/components/autofill_strings_grdp/IDS_AUTOFILL_IPH_MANUAL_FALLBACK_SCREENREADER.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-4ccce16984e84862146831a050af430adf1e3490
\ No newline at end of file
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_et.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_et.xtb
index 15b84cd..46754e9 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_et.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_et.xtb
@@ -97,7 +97,7 @@
 <translation id="2490684707762498678">Haldab <ph name="APP_NAME" /></translation>
 <translation id="2498359688066513246">Abi ja tagasiside</translation>
 <translation id="2501278716633472235">Mine tagasi</translation>
-<translation id="2546283357679194313">Küpsised ja saidiandmed</translation>
+<translation id="2546283357679194313">Küpsised ja saidi andmed</translation>
 <translation id="2570922361219980984">Ka juurdepääs asukohale on selle seadme puhul välja lülitatud. Lülitage see sisse <ph name="BEGIN_LINK" />Androidi seadetes<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Laiendatud – ahendamiseks klõpsake.</translation>
 <translation id="2586657967955657006">Lõikelaud</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_sl.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_sl.xtb
index f28ec56..dee1acbf 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_sl.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_sl.xtb
@@ -30,7 +30,7 @@
 <translation id="146867109637325312">{COUNT,plural, =1{<ph name="SITE_COUNT" /> spletnem mestu}one{<ph name="SITE_COUNT" /> spletnem mestu}two{<ph name="SITE_COUNT" /> spletnih mestih}few{<ph name="SITE_COUNT" /> spletnih mestih}other{<ph name="SITE_COUNT" /> spletnih mestih}}</translation>
 <translation id="1500473259453106018">Skrij kartico z znižanji cen na zavihkih</translation>
 <translation id="1510341833810331442">Spletna mesta ne smejo shranjevati podatkov v napravi.</translation>
-<translation id="1547123415014299762">Piškotki drugih spletnih mest so dovoljeni.</translation>
+<translation id="1547123415014299762">Piškotki tretjih oseb so dovoljeni.</translation>
 <translation id="1568470248891039841">Spletna mesta, ki jih obiščete, lahko vdelajo vsebino z drugih spletnih mest, na primer slike, oglase in besedilo. Ta druga spletna mesta lahko zahtevajo dovoljenje za uporabo podatkov, ki so jih shranila o vas med brskanjem po spletnem mestu. <ph name="BEGIN_LINK" />Preberite več o vdelani vsebini<ph name="END_LINK" /></translation>
 <translation id="1593426485665524382">Nova dejanja so na voljo pri vrhu zaslona.</translation>
 <translation id="1620510694547887537">Kamera</translation>
@@ -72,7 +72,7 @@
 <translation id="2194856509914051091">Kaj morate upoštevati</translation>
 <translation id="2215727959747642672">Urejanje datotek</translation>
 <translation id="2228071138934252756">Če želite aplikaciji <ph name="APP_NAME" /> omogočiti dostop do fotoaparata, fotoaparat vklopite tudi v <ph name="BEGIN_LINK" />nastavitvah za Android<ph name="END_LINK" />.</translation>
-<translation id="2235344399760031203">Piškotki drugih spletnih mest so blokirani</translation>
+<translation id="2235344399760031203">Piškotki tretjih oseb so blokirani</translation>
 <translation id="2238944249568001759">Predlagana iskanja na podlagi zadnjega zavihka</translation>
 <translation id="2241587408274973373">Kartice strani s povezavami</translation>
 <translation id="2241634353105152135">Samo enkrat</translation>
@@ -221,7 +221,7 @@
 <translation id="4336566011000459927">Chrome bo danes znova omejil piškotke</translation>
 <translation id="4338831206024587507">Vsa spletna mesta v domeni <ph name="DOMAIN" />.</translation>
 <translation id="4402755511846832236">Preprečevanje, da bi spletna mesta vedela, kdaj aktivno uporabljate to napravo.</translation>
-<translation id="4412992751769744546">Omogočanje piškotkov drugih spletnih mest</translation>
+<translation id="4412992751769744546">Omogočanje piškotkov tretjih oseb</translation>
 <translation id="4419929467120297501">Chrome spletnim mestom onemogoči uporabo piškotkov tretjih oseb, da bi vam sledila med brskanjem. Obiščite nastavitve, če želite <ph name="BEGIN_LINK" />upravljati dostop do piškotkov tretjih oseb<ph name="END_LINK" />.</translation>
 <translation id="4434045419905280838">Pojavna okna in preusmeritve</translation>
 <translation id="443552056913301231">To dejanje bo izbrisalo vse lokalne podatke, vključno s piškotki, in ponastavilo vsa dovoljenja za <ph name="ORIGIN" /></translation>
@@ -314,7 +314,7 @@
 <translation id="5691080386278724773"><ph name="SITE" /> lahko med brskanjem uporablja vaše podatke</translation>
 <translation id="5700761515355162635">Piškotki tretjih oseb so dovoljeni</translation>
 <translation id="5706552988683188916">S tem izbrišete piškotke in druge podatke spletnega mesta za <ph name="WEBSITE" />.</translation>
-<translation id="5723967018671998714">Piškotki drugih spletnih mest so blokirani v anonimnem načinu</translation>
+<translation id="5723967018671998714">Piškotki tretjih oseb so blokirani v anonimnem načinu</translation>
 <translation id="5740126560802162366">Spletna mesta lahko shranjujejo podatke v napravi.</translation>
 <translation id="5750869797196646528">Sledenje potezam dlani</translation>
 <translation id="5771720122942595109">Blokirano: <ph name="PERMISSION_1" /></translation>
@@ -351,7 +351,7 @@
 <translation id="6192792657125177640">Izjeme</translation>
 <translation id="6194967801833346599">{DAYS,plural, =1{Chrome bo znova blokiral piškotke jutri}one{Še # dan in piškotki bodo znova blokirani}two{Še # dneva in piškotki bodo znova blokirani}few{Še # dni in piškotki bodo znova blokirani}other{Še # dni in piškotki bodo znova blokirani}}</translation>
 <translation id="6195163219142236913">Piškotki tretjih oseb so omejeni</translation>
-<translation id="6196640612572343990">Blokiraj piškotke drugih spletnih mest</translation>
+<translation id="6196640612572343990">Blokiraj piškotke tretjih oseb</translation>
 <translation id="6205314730813004066">Zasebnost pri oglaševanju</translation>
 <translation id="6207207788774442484">Izbriši podatke in ponastavi dovoljenja</translation>
 <translation id="6231752747840485235">Želite odmestiti aplikacijo »<ph name="APP_NAME" />«?</translation>
diff --git a/components/browser_ui/widget/android/java/res/layout/title_and_description_layout.xml b/components/browser_ui/widget/android/java/res/layout/title_and_description_layout.xml
index 32e4a234..b6bb9fa 100644
--- a/components/browser_ui/widget/android/java/res/layout/title_and_description_layout.xml
+++ b/components/browser_ui/widget/android/java/res/layout/title_and_description_layout.xml
@@ -48,6 +48,18 @@
         android:layout_height="match_parent"
         app:layout_constraintEnd_toEndOf="parent" />
 
+    <FrameLayout
+        android:id="@+id/before_description_container"
+        android:layout_gravity="center_vertical|start"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:layout_constraintHorizontal_bias="0.0"
+        app:layout_constraintHorizontal_chainStyle="packed"
+        app:layout_constraintTop_toBottomOf="@+id/title"
+        app:layout_constraintBottom_toBottomOf="@+id/description"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toStartOf="@+id/description" />
+
     <TextView
         android:id="@+id/description"
         android:layout_gravity="center_vertical|start"
@@ -56,10 +68,8 @@
         android:maxLines="1"
         android:ellipsize="end"
         android:textAppearance="@style/TextAppearance.TextMedium.Secondary"
-        app:layout_constraintHorizontal_bias="0.0"
-        app:layout_constraintHorizontal_chainStyle="packed"
         app:layout_constraintTop_toBottomOf="@+id/title"
-        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintStart_toEndOf="@+id/before_description_container"
         app:layout_constraintEnd_toStartOf="@+id/chip" />
 
     <!-- An optional chip view. Used for history. -->
diff --git a/components/certificate_transparency/data/log_list.json b/components/certificate_transparency/data/log_list.json
index 9095cf7..2ef13dda 100644
--- a/components/certificate_transparency/data/log_list.json
+++ b/components/certificate_transparency/data/log_list.json
@@ -1,6 +1,6 @@
 {
-  "version": "50.32",
-  "log_list_timestamp": "2024-12-08T12:55:33Z",
+  "version": "50.33",
+  "log_list_timestamp": "2024-12-09T12:55:12Z",
   "operators": [
     {
       "name": "Google",
diff --git a/components/chrome_urls_ui/mojom/chrome_urls.mojom b/components/chrome_urls_ui/mojom/chrome_urls.mojom
index d303045..5bdb84c 100644
--- a/components/chrome_urls_ui/mojom/chrome_urls.mojom
+++ b/components/chrome_urls_ui/mojom/chrome_urls.mojom
@@ -37,6 +37,11 @@
 interface PageHandler {
   // Called by the WebUI page to get the lists of URLs to display.
   GetUrls() => (ChromeUrlsData urls_data);
+
+  // Called by the WebUI page to set the kInternalDebugPagesEnabled pref to
+  // `enabled`. The handler invokes a callback to tell the page the pref was
+  // set.
+  SetDebugPagesEnabled(bool enabled) => ();
 };
 
 // WebUI-side handler for requests from the browser.
diff --git a/components/chrome_urls_ui/resources/app.html.ts b/components/chrome_urls_ui/resources/app.html.ts
index a56af3dc..d44ce17 100644
--- a/components/chrome_urls_ui/resources/app.html.ts
+++ b/components/chrome_urls_ui/resources/app.html.ts
@@ -19,10 +19,14 @@
 </ul>
 ${this.internalUrlInfos_.length ? html`
   <h2>Internal Debugging Page URLs</h2>
-  <p>
+  <p id="debug-pages-description">
     <span>Internal debugging pages are currently </span>
     <span class="bold">${this.getDebugPagesEnabledText_()}</span><span>.</span>
   </p>
+  <cr-button @click="${this.onToggleDebugPagesClick_}"
+      ?disabled="${this.debugPagesButtonDisabled_}">
+    ${this.getDebugPagesToggleButtonLabel_()}
+  </cr-button>
   <ul>
     ${this.internalUrlInfos_.map(info => html`
       ${this.isInternalUiEnabled_(info) ?
diff --git a/components/chrome_urls_ui/resources/app.ts b/components/chrome_urls_ui/resources/app.ts
index caa604ec..ad723397 100644
--- a/components/chrome_urls_ui/resources/app.ts
+++ b/components/chrome_urls_ui/resources/app.ts
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'chrome://resources/cr_elements/cr_button/cr_button.js';
+
 import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js';
 import type {Url} from 'chrome://resources/mojo/url/mojom/url.mojom-webui.js';
 
@@ -25,6 +27,7 @@
 
   static override get properties() {
     return {
+      debugPagesButtonDisabled_: {type: Boolean},
       internalUrlInfos_: {type: Array},
       webuiUrlInfos_: {type: Array},
       commandUrls_: {type: Array},
@@ -32,6 +35,7 @@
     };
   }
 
+  protected debugPagesButtonDisabled_: boolean = false;
   protected webuiUrlInfos_: WebuiUrlInfo[] = [];
   protected internalUrlInfos_: WebuiUrlInfo[] = [];
   protected commandUrls_: Url[] = [];
@@ -60,6 +64,19 @@
     return this.internalUisEnabled_ ? 'enabled' : 'disabled';
   }
 
+  protected getDebugPagesToggleButtonLabel_(): string {
+    return this.internalUisEnabled_ ? 'Disable internal debugging pages' :
+                                      'Enable internal debugging pages';
+  }
+
+  protected async onToggleDebugPagesClick_() {
+    this.debugPagesButtonDisabled_ = true;
+    const enabled = !this.internalUisEnabled_;
+    await BrowserProxyImpl.getInstance().handler.setDebugPagesEnabled(enabled);
+    this.internalUisEnabled_ = enabled;
+    this.debugPagesButtonDisabled_ = false;
+  }
+
   protected isInternalUiEnabled_(info: WebuiUrlInfo): boolean {
     return info.enabled && this.internalUisEnabled_;
   }
diff --git a/components/components_chromium_strings.grd b/components/components_chromium_strings.grd
index 733410f..87c402d 100644
--- a/components/components_chromium_strings.grd
+++ b/components/components_chromium_strings.grd
@@ -197,10 +197,10 @@
         <message name="IDS_ERRORPAGES_SUGGESTION_NETWORK_PREDICTION_BODY" desc="When a page fails to load, sometimes we suggest disabling predicting network actions.  These are details below a header for non Android devices.">
           Go to
           the Chromium menu &gt;
-          <ph name="SETTINGS_TITLE">&lt;span jscontent="settingsTitle"&gt;$1&lt;/span&gt;<ex>Settings</ex></ph>
+          <ph name="SETTINGS_TITLE">&lt;span&gt;$1&lt;/span&gt;<ex>Settings</ex></ph>
           &gt;
-          <ph name="ADVANCED_TITLE">&lt;span jscontent="advancedTitle"&gt;$2&lt;/span&gt;<ex>Under the Hood</ex></ph>
-          and deselect &quot;<ph name="NO_PREFETCH_DESCRIPTION">&lt;span jscontent="noNetworkPredictionTitle"&gt;$3&lt;/span&gt;<ex>Use a prediction service to load pages more quickly</ex></ph>.&quot;
+          <ph name="ADVANCED_TITLE">&lt;span&gt;$2&lt;/span&gt;<ex>Under the Hood</ex></ph>
+          and deselect &quot;<ph name="NO_PREFETCH_DESCRIPTION">&lt;span&gt;$3&lt;/span&gt;<ex>Use a prediction service to load pages more quickly</ex></ph>.&quot;
           If this does not resolve the issue, we recommend selecting this option
           again for improved performance.
         </message>
@@ -224,11 +224,11 @@
         <message name="IDS_ERRORPAGES_SUGGESTION_PROXY_DISABLE_PLATFORM" desc="Linux instructions for disabling use of a proxy server.">
           Go to
           the Chromium menu &gt;
-          <ph name="SETTINGS_TITLE">&lt;span jscontent="settingsTitle"&gt;$1&lt;/span&gt;<ex>Settings</ex></ph>
+          <ph name="SETTINGS_TITLE">&lt;span&gt;$1&lt;/span&gt;<ex>Settings</ex></ph>
           &gt;
-          <ph name="ADVANCED_TITLE">&lt;span jscontent="advancedTitle"&gt;$2&lt;/span&gt;<ex>Under the Hood</ex></ph>
+          <ph name="ADVANCED_TITLE">&lt;span&gt;$2&lt;/span&gt;<ex>Under the Hood</ex></ph>
           &gt;
-          <ph name="PROXIES_TITLE">&lt;span jscontent="proxyTitle"&gt;$3&lt;/span&gt;<ex>Change proxy settings...</ex></ph>
+          <ph name="PROXIES_TITLE">&lt;span&gt;$3&lt;/span&gt;<ex>Change proxy settings...</ex></ph>
           and make sure your configuration is set to &quot;no proxy&quot; or &quot;direct.&quot;
         </message>
       </if>
@@ -236,11 +236,11 @@
         <message name="IDS_ERRORPAGES_SUGGESTION_PROXY_DISABLE_PLATFORM" desc="Windows instructions for disabling use of a proxy server.">
           Go to
           the Chromium menu &gt;
-          <ph name="SETTINGS_TITLE">&lt;span jscontent="settingsTitle"&gt;$1&lt;/span&gt;<ex>Settings</ex></ph>
+          <ph name="SETTINGS_TITLE">&lt;span&gt;$1&lt;/span&gt;<ex>Settings</ex></ph>
           &gt;
-          <ph name="ADVANCED_TITLE">&lt;span jscontent="advancedTitle"&gt;$2&lt;/span&gt;<ex>Under the Hood</ex></ph>
+          <ph name="ADVANCED_TITLE">&lt;span&gt;$2&lt;/span&gt;<ex>Under the Hood</ex></ph>
           &gt;
-          <ph name="PROXIES_TITLE">&lt;span jscontent="proxyTitle"&gt;$3&lt;/span&gt;<ex>Change proxy settings...</ex></ph>
+          <ph name="PROXIES_TITLE">&lt;span&gt;$3&lt;/span&gt;<ex>Change proxy settings...</ex></ph>
           &gt;
           LAN Settings
           and deselect the &quot;Use a proxy server for your LAN&quot; checkbox.
diff --git a/components/components_google_chrome_strings.grd b/components/components_google_chrome_strings.grd
index 5f70c3e..e237c2d 100644
--- a/components/components_google_chrome_strings.grd
+++ b/components/components_google_chrome_strings.grd
@@ -197,10 +197,10 @@
         <message name="IDS_ERRORPAGES_SUGGESTION_NETWORK_PREDICTION_BODY" desc="When a page fails to load, sometimes we suggest disabling predicting network actions.  These are details below a header for non Android devices.">
           Go to
           the Chrome menu &gt;
-          <ph name="SETTINGS_TITLE">&lt;span jscontent="settingsTitle"&gt;$1&lt;/span&gt;<ex>Settings</ex></ph>
+          <ph name="SETTINGS_TITLE">&lt;span&gt;$1&lt;/span&gt;<ex>Settings</ex></ph>
           &gt;
-          <ph name="ADVANCED_TITLE">&lt;span jscontent="advancedTitle"&gt;$2&lt;/span&gt;<ex>Under the Hood</ex></ph>
-          and deselect &quot;<ph name="NO_PREFETCH_DESCRIPTION">&lt;span jscontent="noNetworkPredictionTitle"&gt;$3&lt;/span&gt;<ex>Use a prediction service to load pages more quickly</ex></ph>.&quot;
+          <ph name="ADVANCED_TITLE">&lt;span&gt;$2&lt;/span&gt;<ex>Under the Hood</ex></ph>
+          and deselect &quot;<ph name="NO_PREFETCH_DESCRIPTION">&lt;span&gt;$3&lt;/span&gt;<ex>Use a prediction service to load pages more quickly</ex></ph>.&quot;
           If this does not resolve the issue, we recommend selecting this option
           again for improved performance.
         </message>
@@ -224,11 +224,11 @@
         <message name="IDS_ERRORPAGES_SUGGESTION_PROXY_DISABLE_PLATFORM" desc="Linux instructions for disabling use of a proxy server.">
           Go to
           the Chrome menu &gt;
-          <ph name="SETTINGS_TITLE">&lt;span jscontent="settingsTitle"&gt;$1&lt;/span&gt;<ex>Settings</ex></ph>
+          <ph name="SETTINGS_TITLE">&lt;span&gt;$1&lt;/span&gt;<ex>Settings</ex></ph>
           &gt;
-          <ph name="ADVANCED_TITLE">&lt;span jscontent="advancedTitle"&gt;$2&lt;/span&gt;<ex>Under the Hood</ex></ph>
+          <ph name="ADVANCED_TITLE">&lt;span&gt;$2&lt;/span&gt;<ex>Under the Hood</ex></ph>
           &gt;
-          <ph name="PROXIES_TITLE">&lt;span jscontent="proxyTitle"&gt;$3&lt;/span&gt;<ex>Change proxy settings...</ex></ph>
+          <ph name="PROXIES_TITLE">&lt;span&gt;$3&lt;/span&gt;<ex>Change proxy settings...</ex></ph>
           and make sure your configuration is set to &quot;no proxy&quot; or &quot;direct.&quot;
         </message>
       </if>
@@ -236,11 +236,11 @@
         <message name="IDS_ERRORPAGES_SUGGESTION_PROXY_DISABLE_PLATFORM" desc="Windows instructions for disabling use of a proxy server.">
           Go to
           the Chrome menu &gt;
-          <ph name="SETTINGS_TITLE">&lt;span jscontent="settingsTitle"&gt;$1&lt;/span&gt;<ex>Settings</ex></ph>
+          <ph name="SETTINGS_TITLE">&lt;span&gt;$1&lt;/span&gt;<ex>Settings</ex></ph>
           &gt;
-          <ph name="ADVANCED_TITLE">&lt;span jscontent="advancedTitle"&gt;$2&lt;/span&gt;<ex>Under the Hood</ex></ph>
+          <ph name="ADVANCED_TITLE">&lt;span&gt;$2&lt;/span&gt;<ex>Under the Hood</ex></ph>
           &gt;
-          <ph name="PROXIES_TITLE">&lt;span jscontent="proxyTitle"&gt;$3&lt;/span&gt;<ex>Change proxy settings...</ex></ph>
+          <ph name="PROXIES_TITLE">&lt;span&gt;$3&lt;/span&gt;<ex>Change proxy settings...</ex></ph>
           &gt;
           LAN Settings
           and deselect &quot;Use a proxy server for your LAN&quot;.
diff --git a/components/error_page/common/localized_error.cc b/components/error_page/common/localized_error.cc
index 6f21deac..b2866908 100644
--- a/components/error_page/common/localized_error.cc
+++ b/components/error_page/common/localized_error.cc
@@ -633,7 +633,6 @@
 
   base::Value::Dict suggestion_list_item;
   suggestion_list_item.Set("summary", suggestion_string);
-  suggestion_list_item.Set("learnMoreUrl", learn_more_url_with_locale.spec());
   suggestions_summary_list.Append(std::move(suggestion_list_item));
 }
 
@@ -716,7 +715,6 @@
         l10n_util::GetStringFUTF16(
             IDS_ERRORPAGES_SUGGESTION_NAVIGATE_TO_ORIGIN,
             base::UTF8ToUTF16(base::EscapeForHTML(failed_origin_string))));
-    suggestion.Set("originURL", failed_origin_string);
     suggestions_summary_list.Append(std::move(suggestion));
     return;
   }
@@ -890,17 +888,6 @@
             l10n_util::GetStringUTF16(IDS_SETTINGS_SHOW_ADVANCED_SETTINGS),
             l10n_util::GetStringUTF16(
                 IDS_NETWORK_PREDICTION_ENABLED_DESCRIPTION)));
-
-    // TODO(crbug.com/378692755): Remove once backwards compatibility with
-    // jstemplate is not needed.
-    suggestions_details.back().GetDict().Set(
-        "settingsTitle", l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE));
-    suggestions_details.back().GetDict().Set(
-        "advancedTitle",
-        l10n_util::GetStringUTF16(IDS_SETTINGS_SHOW_ADVANCED_SETTINGS));
-    suggestions_details.back().GetDict().Set(
-        "noNetworkPredictionTitle",
-        l10n_util::GetStringUTF16(IDS_NETWORK_PREDICTION_ENABLED_DESCRIPTION));
   }
 
   if (suggestions & SUGGEST_FIREWALL_CONFIG) {
@@ -930,17 +917,6 @@
         l10n_util::GetStringUTF16(
             IDS_ERRORPAGES_SUGGESTION_PROXY_CONFIG_HEADER),
         inner);
-
-    // TODO(crbug.com/378692755): Remove once backwards compatibility with
-    // jstemplate is not needed.
-    suggestions_details.back().GetDict().Set(
-        "settingsTitle", l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE));
-    suggestions_details.back().GetDict().Set(
-        "advancedTitle",
-        l10n_util::GetStringUTF16(IDS_SETTINGS_SHOW_ADVANCED_SETTINGS));
-    suggestions_details.back().GetDict().Set(
-        "proxyTitle",
-        l10n_util::GetStringUTF16(IDS_OPTIONS_PROXIES_CONFIGURE_BUTTON));
   }
 #endif  //  !BUILDFLAG(IS_FUCHSIA)
 #endif
@@ -1095,7 +1071,6 @@
                                       : options.heading_resource_id;
   heading.Set("msg",
               GetStringWithPlaceholder(msg_id, host_name, failed_url_string));
-  heading.Set("hostName", host_name);
   result.strings.Set("heading", std::move(heading));
 
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
@@ -1131,9 +1106,6 @@
 
   summary.Set("msg", std::move(message));
 
-  summary.Set("failedUrl", failed_url_string);
-  summary.Set("hostName", host_name);
-
   result.strings.Set(
       "details", l10n_util::GetStringUTF16(IDS_ERRORPAGE_NET_BUTTON_DETAILS));
   result.strings.Set("hideDetails", l10n_util::GetStringUTF16(
diff --git a/components/error_page_strings.grdp b/components/error_page_strings.grdp
index 173c659..b32621b 100644
--- a/components/error_page_strings.grdp
+++ b/components/error_page_strings.grdp
@@ -98,7 +98,7 @@
     The client and server don't support a common SSL protocol version or cipher suite.
   </message>
   <message name="IDS_ERRORPAGES_SUGGESTION_NAVIGATE_TO_ORIGIN" desc="When a webpage fails to load, sometimes we suggest to the user that they might navigate to the page's origin.">
-    Try <ph name="BEGIN_LINK">&lt;a href="$1" jsvalues="href:originURL;.jstdata:$this" onmousedown="linkClicked(this.jstdata)"&gt;</ph>visiting the site's homepage<ph name="END_LINK">&lt;/a&gt;</ph>.
+    Try <ph name="BEGIN_LINK">&lt;a href="$1"&gt;</ph>visiting the site's homepage<ph name="END_LINK">&lt;/a&gt;</ph>.
   </message>
   <message name="IDS_ERRORPAGES_HEADING_NOT_AVAILABLE" desc="Heading in the error page when we can't connect to a site.">
     This site can’t be reached
@@ -128,40 +128,40 @@
     Your connection was interrupted
   </message>
   <message name="IDS_ERRORPAGES_HEADING_NOT_FOUND" desc="Heading in the error page when the server returns a 404 or 410.">
-    This <ph name="HOST_NAME">&lt;span jscontent="hostName"&gt;$1&lt;/span&gt;<ex>www.whatever.com</ex></ph> page can’t be found
+    This <ph name="HOST_NAME">&lt;span&gt;$1&lt;/span&gt;<ex>www.whatever.com</ex></ph> page can’t be found
   </message>
   <message name="IDS_ERRORPAGES_HEADING_FILE_NOT_FOUND" desc="Heading in the error page when the local file could not be accessed.">
     Your file couldn’t be accessed
   </message>
   <message name="IDS_ERRORPAGES_HEADING_BLOCKED" desc="Heading of the error page when a request is blocked by the administrator policy, extension or the browser itself.">
-    <ph name="HOST_NAME">&lt;span jscontent="hostName"&gt;$1&lt;/span&gt;<ex>www.example.com</ex></ph> is blocked
+    <ph name="HOST_NAME">&lt;span&gt;$1&lt;/span&gt;<ex>www.example.com</ex></ph> is blocked
   </message>
   <message name="IDS_ERRORPAGES_HEADING_BLOCKED_SCHEME" desc="Heading of the error page when a URL Scheme is blocked by the administrator policy, extension or the browser itself.">
-    “<ph name="HOST_NAME">&lt;span jscontent="hostName"&gt;$1&lt;/span&gt;<ex>mailto</ex></ph>” links are blocked
+    “<ph name="HOST_NAME">&lt;span&gt;$1&lt;/span&gt;<ex>mailto</ex></ph>” links are blocked
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_NOT_AVAILABLE" desc="Summary in the error page when we can't connect to a site.">
-    The webpage at <ph name="URL">&lt;strong jscontent="failedUrl"&gt;$1&lt;/strong&gt;</ph> might be temporarily down or it may have moved permanently to a new web address.
+    The webpage at <ph name="URL">&lt;strong&gt;$1&lt;/strong&gt;</ph> might be temporarily down or it may have moved permanently to a new web address.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_TIMED_OUT" desc="Summary in the error page when a page takes too long to load.">
-    <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> took too long to respond.
+    <ph name="HOST_NAME">&lt;strong&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> took too long to respond.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_CONNECTION_RESET" desc="Summary in the error page when the connection was reset.">
     The connection was reset.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_CONNECTION_CLOSED" desc="Summary in the error page when the connection was closed.">
-    <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> unexpectedly closed the connection.
+    <ph name="HOST_NAME">&lt;strong&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> unexpectedly closed the connection.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_CONNECTION_FAILED" desc="Summary in the error page when the connection failed or unreachable.">
-    <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> is currently unreachable.
+    <ph name="HOST_NAME">&lt;strong&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> is currently unreachable.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_NETWORK_CHANGED" desc="Summary in the error page when the connection failed because the network has changed.">
     A network change was detected.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_CONNECTION_REFUSED" desc="Summary in the error page when we try and connect to a server, but the server doesn't let us.">
-    <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> refused to connect.
+    <ph name="HOST_NAME">&lt;strong&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> refused to connect.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_NAME_NOT_RESOLVED" desc="Summary in the error page when a dns look up fails.">
-    <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph>’s server IP address could not be found.
+    <ph name="HOST_NAME">&lt;strong&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph>’s server IP address could not be found.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_ICANN_NAME_COLLISION" desc="Summary in the error page when a dns look up fails due to having contained 127.0.53.53.">
     This site on the company, organization or school intranet has the same URL as an external website.
@@ -169,10 +169,10 @@
     Try contacting your system administrator.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_ADDRESS_UNREACHABLE" desc="Summary in the error page when we can't reach a site.  This is slightly more specific than just being unable to connect, as it means we can't find a route to the server.">
-    <ph name="URL">&lt;strong jscontent="failedUrl"&gt;$1&lt;/strong&gt;<ex>http://www.google.com/</ex></ph> is unreachable.
+    <ph name="URL">&lt;strong&gt;$1&lt;/strong&gt;<ex>http://www.google.com/</ex></ph> is unreachable.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_FILE_ACCESS_DENIED" desc="Summary in the error page when we can't open a file.">
-    The file at <ph name="URL">&lt;strong jscontent="failedUrl"&gt;$1&lt;/strong&gt;<ex>http://www.google.com/</ex></ph> is not readable.  It may have been removed, moved, or file permissions may be preventing access.
+    The file at <ph name="URL">&lt;strong&gt;$1&lt;/strong&gt;<ex>http://www.google.com/</ex></ph> is not readable.  It may have been removed, moved, or file permissions may be preventing access.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_NETWORK_ACCESS_DENIED" desc="Summary in the error page when we're not being allowed to access the network.">
     Firewall or antivirus software may have blocked the connection.
@@ -194,26 +194,26 @@
     </message>
   </if>
   <message name="IDS_ERRORPAGES_SUMMARY_NOT_FOUND" desc="Summary in the error page when the server returns a 404.">
-    No webpage was found for the web address: <ph name="URL">&lt;strong jscontent="failedUrl"&gt;$1&lt;/strong&gt;</ph>
+    No webpage was found for the web address: <ph name="URL">&lt;strong&gt;$1&lt;/strong&gt;</ph>
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_FILE_NOT_FOUND" desc="Summary in the error page when a local file could not be accessed.">
     It may have been moved, edited, or deleted.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_TOO_MANY_REDIRECTS" desc="Summary in the error page when there are too many URL redirects.">
-    <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> redirected you too many times.
+    <ph name="HOST_NAME">&lt;strong&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> redirected you too many times.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_EMPTY_RESPONSE" desc="Summary in the error page when no data is received.">
-    <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> didn’t send any data.
+    <ph name="HOST_NAME">&lt;strong&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> didn’t send any data.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_INVALID_RESPONSE" desc="Summary in the error page when a response from the server contains duplicate headers.">
-    <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> sent an invalid response.
+    <ph name="HOST_NAME">&lt;strong&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> sent an invalid response.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_DNS_PROBE_RUNNING" desc="Summary in the error page when DNS resolution failed and we are running a probe to figure out why. The 'abbr' tag is used to indicate that 'DNS address' is an abbreviation.">
-    <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph>’s &lt;abbr id="dnsDefinition"&gt;DNS address&lt;/abbr&gt; could not be found. Diagnosing the problem.
+    <ph name="HOST_NAME">&lt;strong&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph>’s &lt;abbr id="dnsDefinition"&gt;DNS address&lt;/abbr&gt; could not be found. Diagnosing the problem.
   </message>
 
   <message name="IDS_ERRORPAGES_HEADING_ACCESS_DENIED" desc="Heading in the error page when a server returns a 403.  Also suitable for similar error codes.">
-    Access to <ph name="HOST_NAME">&lt;span jscontent="hostName"&gt;$1&lt;/span&gt;<ex>www.whatever.com</ex></ph> was denied
+    Access to <ph name="HOST_NAME">&lt;span&gt;$1&lt;/span&gt;<ex>www.whatever.com</ex></ph> was denied
   </message>
   <message name="IDS_ERRORPAGES_HEADING_FILE_ACCESS_DENIED" desc="Heading in the error page when a file is denied access.">
     Access to the file was denied
@@ -232,26 +232,26 @@
     If the problem continues, contact the site owner.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_WEBSITE_CANNOT_HANDLE_REQUEST" desc="Summary in the error page when the server returns a 501 or 505.">
-    <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> is currently unable to handle this request.
+    <ph name="HOST_NAME">&lt;strong&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> is currently unable to handle this request.
   </message>
 
   <message name="IDS_ERRORPAGES_SUMMARY_GATEWAY_TIMEOUT" desc="Summary in the error page when the server returns a 504.">
-    <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> took too long to respond.
+    <ph name="HOST_NAME">&lt;strong&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> took too long to respond.
   </message>
 
   <message name="IDS_ERRORPAGES_SUMMARY_SSL_SECURITY_ERROR" desc="Summary in the error page for SSL security errors.">
-    <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> doesn't adhere to security standards.
+    <ph name="HOST_NAME">&lt;strong&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> doesn't adhere to security standards.
   </message>
 
   <message name="IDS_ERRORPAGES_SUMMARY_SSL_VERSION_OR_CIPHER_MISMATCH" desc="Summary in the error page for SSL cipher and version errors.">
-    <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> uses an unsupported protocol.
+    <ph name="HOST_NAME">&lt;strong&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> uses an unsupported protocol.
   </message>
 
   <message name="IDS_ERRORPAGES_HEADING_INSECURE_CONNECTION" desc="Heading in the error page for insecure connections.">
     This site can’t provide a secure connection
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_BAD_SSL_CLIENT_AUTH_CERT" desc="Summary in the error page when the server rejected the connection due to a SSL client certificate authentication failure.">
-    <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> didn’t accept your login certificate, or one may not have been provided.
+    <ph name="HOST_NAME">&lt;strong&gt;$1&lt;/strong&gt;<ex>www.whatever.com</ex></ph> didn’t accept your login certificate, or one may not have been provided.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_SSL_CLIENT_AUTH_SIGNATURE_FAILED" desc="Summary in the error page when authenticating with the user's SSL client certificate failed.">
     There was a problem using your login certificate.
@@ -319,13 +319,13 @@
     Try contacting the system admin.
   </message>
   <message name="IDS_ERRORPAGES_SUGGESTION_LEARNMORE_SUMMARY" desc="The message displayed in a list of suggestions when a webpage fails to load. A link provided to the help center to learn more about the failure. The suggestions list is prefixed with 'Try:'.">
-    <ph name="BEGIN_LINK">&lt;a href="$1" jsvalues="href:learnMoreUrl"&gt;</ph>Learning more<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph> about this problem.
+    <ph name="BEGIN_LINK">&lt;a href="$1"&gt;</ph>Learning more<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph> about this problem.
   </message>
   <message name="IDS_ERRORPAGES_SUGGESTION_LEARNMORE_SUMMARY_STANDALONE" desc="When a webpage fails to load, we provide a link to the help center to learn more about the failure.">
-    <ph name="BEGIN_LINK">&lt;a href="$1" jsvalues="href:learnMoreUrl"&gt;</ph>Learn more<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph> about this problem.
+    <ph name="BEGIN_LINK">&lt;a href="$1"&gt;</ph>Learn more<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph> about this problem.
   </message>
   <message name="IDS_ERRORPAGES_SUGGESTION_DELETE_COOKIES_SUMMARY" desc="The message displayed following a network error suggesting the user could try deleting their cookies. We also provide a link to the help center to learn more about the failure.">
-    <ph name="BEGIN_LINK">&lt;a href="$1" jsvalues="href:learnMoreUrl"&gt;</ph>Try deleting your cookies<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex>.</ph>
+    <ph name="BEGIN_LINK">&lt;a href="$1"&gt;</ph>Try deleting your cookies<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex>.</ph>
   </message>
   <if expr="is_ios or is_android">
     <message name="IDS_ERRORPAGES_SUGGESTION_TURN_OFF_AIRPLANE_SUMMARY" desc="When a page fails to load and the device is offline, we provide a suggestion that the user try turning off airplane mode. The suggestions list is prefixed with 'Try:'.">
@@ -348,7 +348,7 @@
     Try disabling your extensions.
   </message>
   <message name="IDS_ERRORPAGES_CHECK_TYPO_SUMMARY" desc="When a page fails to load, we provide a suggestion to the user to check for spelling errors">
-    Check if there is a typo in <ph name="HOST_NAME">&lt;span jscontent="hostName"&gt;$1&lt;/span&gt;<ex>www.whatever.com</ex></ph>.
+    Check if there is a typo in <ph name="HOST_NAME">&lt;span&gt;$1&lt;/span&gt;<ex>www.whatever.com</ex></ph>.
   </message>
 
   <if expr="is_macosx">
diff --git a/components/feature_engagement/public/feature_configurations.cc b/components/feature_engagement/public/feature_configurations.cc
index 8e60b69..10f4280 100644
--- a/components/feature_engagement/public/feature_configurations.cc
+++ b/components/feature_engagement/public/feature_configurations.cc
@@ -1708,24 +1708,6 @@
     return config;
   }
 
-  if (kIPHAutofillManualFallbackFeature.name == feature->name) {
-    // Autofill Manual Fallback IPH is shown if all of the following are true:
-    // * it has not been shown before in the last 90 days;
-    // * the user has never used the autofill manual fallback.
-    std::optional<FeatureConfig> config = FeatureConfig();
-    config->valid = true;
-    config->availability = Comparator(ANY, 0);
-    config->session_rate = Comparator(ANY, 0);
-    config->session_rate_impact.type = SessionRateImpact::Type::NONE;
-    config->trigger = EventConfig("autofill_manual_fallback_trigger",
-                                  Comparator(LESS_THAN, 1), 90, 360);
-    config->used =
-        EventConfig("autofill_manual_fallback_accepted", Comparator(EQUAL, 0),
-                    feature_engagement::kMaxStoragePeriod,
-                    feature_engagement::kMaxStoragePeriod);
-    return config;
-  }
-
   if (kIPHAutofillVirtualCardSuggestionFeature.name == feature->name) {
     // A config that allows the virtual card credit card suggestion IPH to be
     // shown when:
diff --git a/components/feature_engagement/public/feature_constants.cc b/components/feature_engagement/public/feature_constants.cc
index f415f56..7b41f21 100644
--- a/components/feature_engagement/public/feature_constants.cc
+++ b/components/feature_engagement/public/feature_constants.cc
@@ -663,9 +663,6 @@
 BASE_FEATURE(kIPHAutofillExternalAccountProfileSuggestionFeature,
              "IPH_AutofillExternalAccountProfileSuggestion",
              base::FEATURE_ENABLED_BY_DEFAULT);
-BASE_FEATURE(kIPHAutofillManualFallbackFeature,
-             "IPH_AutofillManualFallback",
-             base::FEATURE_ENABLED_BY_DEFAULT);
 BASE_FEATURE(kIPHAutofillPredictionImprovementsFeature,
              "IPH_AutofillPredictionImprovements",
              base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/components/feature_engagement/public/feature_constants.h b/components/feature_engagement/public/feature_constants.h
index 8e29d28..115c556c 100644
--- a/components/feature_engagement/public/feature_constants.h
+++ b/components/feature_engagement/public/feature_constants.h
@@ -295,7 +295,6 @@
     kIPHAutofillDisabledVirtualCardSuggestionFeature);
 FEATURE_CONSTANTS_DECLARE_FEATURE(
     kIPHAutofillExternalAccountProfileSuggestionFeature);
-FEATURE_CONSTANTS_DECLARE_FEATURE(kIPHAutofillManualFallbackFeature);
 FEATURE_CONSTANTS_DECLARE_FEATURE(kIPHAutofillPredictionImprovementsFeature);
 FEATURE_CONSTANTS_DECLARE_FEATURE(
     kIPHAutofillPredictionImprovementsBootstrappingFeature);
diff --git a/components/feature_engagement/public/feature_list.cc b/components/feature_engagement/public/feature_list.cc
index 5459fb9..e25cb77 100644
--- a/components/feature_engagement/public/feature_list.cc
+++ b/components/feature_engagement/public/feature_list.cc
@@ -239,7 +239,6 @@
     &kIPHAutofillCreditCardBenefitFeature,
     &kIPHAutofillDisabledVirtualCardSuggestionFeature,
     &kIPHAutofillExternalAccountProfileSuggestionFeature,
-    &kIPHAutofillManualFallbackFeature,
     &kIPHAutofillPredictionImprovementsFeature,
     &kIPHAutofillPredictionImprovementsBootstrappingFeature,
     &kIPHAutofillVirtualCardCVCSuggestionFeature,
diff --git a/components/feature_engagement/public/feature_list.h b/components/feature_engagement/public/feature_list.h
index a2a1c8dc..58b4463 100644
--- a/components/feature_engagement/public/feature_list.h
+++ b/components/feature_engagement/public/feature_list.h
@@ -401,8 +401,6 @@
                        "IPH_AutofillDisabledVirtualCardSuggestion");
 DEFINE_VARIATION_PARAM(kIPHAutofillExternalAccountProfileSuggestionFeature,
                        "IPH_AutofillExternalAccountProfileSuggestion");
-DEFINE_VARIATION_PARAM(kIPHAutofillManualFallbackFeature,
-                       "IPH_AutofillManualFallback");
 DEFINE_VARIATION_PARAM(kIPHAutofillPredictionImprovementsFeature,
                        "IPH_AutofillPredictionImprovements");
 DEFINE_VARIATION_PARAM(kIPHAutofillVirtualCardCVCSuggestionFeature,
@@ -713,7 +711,6 @@
         VARIATION_ENTRY(kIPHAutofillCardInfoRetrievalSuggestionFeature),
         VARIATION_ENTRY(kIPHAutofillDisabledVirtualCardSuggestionFeature),
         VARIATION_ENTRY(kIPHAutofillExternalAccountProfileSuggestionFeature),
-        VARIATION_ENTRY(kIPHAutofillManualFallbackFeature),
         VARIATION_ENTRY(kIPHAutofillPredictionImprovementsFeature),
         VARIATION_ENTRY(kIPHAutofillVirtualCardCVCSuggestionFeature),
         VARIATION_ENTRY(kIPHAutofillVirtualCardSuggestionFeature),
diff --git a/components/fingerprinting_protection_filter/interventions/browser/BUILD.gn b/components/fingerprinting_protection_filter/interventions/browser/BUILD.gn
new file mode 100644
index 0000000..7011a01
--- /dev/null
+++ b/components/fingerprinting_protection_filter/interventions/browser/BUILD.gn
@@ -0,0 +1,35 @@
+# Copyright 2024 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/features.gni")
+
+# For this component iOS is explicitly not supported.
+if (use_blink) {
+  source_set("browser") {
+    sources = [
+      "interventions_web_contents_helper.cc",
+      "interventions_web_contents_helper.h",
+    ]
+    public_deps = [ "//content/public/browser" ]
+    deps = [
+      "//base",
+      "//components/fingerprinting_protection_filter/interventions/common:features",
+    ]
+  }
+
+  source_set("unit_tests") {
+    testonly = true
+    sources = [ "interventions_web_contents_helper_unittest.cc" ]
+    public_deps = [ "//content/public/browser" ]
+    deps = [
+      ":browser",
+      "//base",
+      "//components/fingerprinting_protection_filter/interventions/common:features",
+      "//content/test:test_support",
+      "//testing/gtest",
+      "//third_party/blink/public/common",
+      "//url",
+    ]
+  }
+}
diff --git a/components/fingerprinting_protection_filter/interventions/browser/DEPS b/components/fingerprinting_protection_filter/interventions/browser/DEPS
new file mode 100644
index 0000000..4b81354
--- /dev/null
+++ b/components/fingerprinting_protection_filter/interventions/browser/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+  "+content/public/browser",
+  "+content/public/test",
+  "+third_party/blink/public/common",
+  "+components/fingerprinting_protection_filter/interventions/common",
+]
diff --git a/components/fingerprinting_protection_filter/interventions/browser/interventions_web_contents_helper.cc b/components/fingerprinting_protection_filter/interventions/browser/interventions_web_contents_helper.cc
new file mode 100644
index 0000000..45a6f7af
--- /dev/null
+++ b/components/fingerprinting_protection_filter/interventions/browser/interventions_web_contents_helper.cc
@@ -0,0 +1,63 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/fingerprinting_protection_filter/interventions/browser/interventions_web_contents_helper.h"
+
+#include "base/feature_list.h"
+#include "components/fingerprinting_protection_filter/interventions/common/interventions_features.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace content {
+class NavigationHandle;
+class WebContents;
+}  // namespace content
+
+namespace fingerprinting_protection_interventions {
+
+// static
+void InterventionsWebContentsHelper::CreateForWebContents(
+    content::WebContents* web_contents) {
+  // Do nothing if a InterventionsWebContentsHelper
+  // already exists for the current WebContents.
+  if (FromWebContents(web_contents)) {
+    return;
+  }
+
+  content::WebContentsUserData<
+      InterventionsWebContentsHelper>::CreateForWebContents(web_contents);
+}
+
+// private
+InterventionsWebContentsHelper::InterventionsWebContentsHelper(
+    content::WebContents* web_contents)
+    : content::WebContentsUserData<InterventionsWebContentsHelper>(
+          *web_contents),
+      content::WebContentsObserver(web_contents) {}
+
+InterventionsWebContentsHelper::~InterventionsWebContentsHelper() = default;
+
+void InterventionsWebContentsHelper::ReadyToCommitNavigation(
+    content::NavigationHandle* navigation_handle) {
+  // TODO(crbug.com/380461005): Add URL-level exceptions.
+  // At the moment, this is just a sanity check to ensure the state of the
+  // CanvasInterventions feature is the same in both blink and the browser.
+  // Other factors, including URL-level exceptions can alter the state of the
+  // CanvasInterventions feature.
+  auto& mutable_runtime_feature_state =
+      navigation_handle->GetMutableRuntimeFeatureStateContext();
+  bool canvas_base_feature_enabled =
+      features::IsCanvasInterventionsFeatureEnabled();
+
+  if (mutable_runtime_feature_state.IsCanvasInterventionsEnabled() !=
+      canvas_base_feature_enabled) {
+    mutable_runtime_feature_state.SetCanvasInterventionsEnabled(
+        canvas_base_feature_enabled);
+  }
+}
+
+WEB_CONTENTS_USER_DATA_KEY_IMPL(InterventionsWebContentsHelper);
+
+}  // namespace fingerprinting_protection_interventions
diff --git a/components/fingerprinting_protection_filter/interventions/browser/interventions_web_contents_helper.h b/components/fingerprinting_protection_filter/interventions/browser/interventions_web_contents_helper.h
new file mode 100644
index 0000000..5207f13
--- /dev/null
+++ b/components/fingerprinting_protection_filter/interventions/browser/interventions_web_contents_helper.h
@@ -0,0 +1,54 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_FINGERPRINTING_PROTECTION_FILTER_INTERVENTIONS_BROWSER_INTERVENTIONS_WEB_CONTENTS_HELPER_H_
+#define COMPONENTS_FINGERPRINTING_PROTECTION_FILTER_INTERVENTIONS_BROWSER_INTERVENTIONS_WEB_CONTENTS_HELPER_H_
+
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace content {
+class NavigationHandle;
+class WebContents;
+}  // namespace content
+
+namespace fingerprinting_protection_interventions {
+
+// The InterventionsWebContentsHelper facilitates browser-side decisions such as
+// propagating and determining blink::RuntimeFeature enabled state overrides to
+// subsequent navigations. This is used primarily to ensure Navigations receive
+// the correct enablement state of the RuntimeFeature, with regard to other
+// factors such as URL-level exceptions and incognito.
+class InterventionsWebContentsHelper
+    : public content::WebContentsUserData<InterventionsWebContentsHelper>,
+      public content::WebContentsObserver {
+ public:
+  // TODO(https://crbug.com/380458351): Add incognito bool upon creation of this
+  // WebContentsHelper.
+  static void CreateForWebContents(content::WebContents* web_contents);
+
+  InterventionsWebContentsHelper(const InterventionsWebContentsHelper&) =
+      delete;
+  InterventionsWebContentsHelper& operator=(
+      const InterventionsWebContentsHelper&) = delete;
+
+  ~InterventionsWebContentsHelper() override;
+
+ protected:
+  explicit InterventionsWebContentsHelper(content::WebContents* web_contents);
+
+  // content::WebContentsObserver:
+  void ReadyToCommitNavigation(
+      content::NavigationHandle* navigation_handle) override;
+
+ private:
+  friend class content::WebContentsUserData<InterventionsWebContentsHelper>;
+
+  WEB_CONTENTS_USER_DATA_KEY_DECL();
+};
+
+}  // namespace fingerprinting_protection_interventions
+
+#endif  // COMPONENTS_FINGERPRINTING_PROTECTION_FILTER_INTERVENTIONS_BROWSER_INTERVENTIONS_WEB_CONTENTS_HELPER_H_
diff --git a/components/fingerprinting_protection_filter/interventions/browser/interventions_web_contents_helper_unittest.cc b/components/fingerprinting_protection_filter/interventions/browser/interventions_web_contents_helper_unittest.cc
new file mode 100644
index 0000000..e34a93aa
--- /dev/null
+++ b/components/fingerprinting_protection_filter/interventions/browser/interventions_web_contents_helper_unittest.cc
@@ -0,0 +1,136 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/fingerprinting_protection_filter/interventions/browser/interventions_web_contents_helper.h"
+
+#include <string_view>
+
+#include "base/test/scoped_feature_list.h"
+#include "components/fingerprinting_protection_filter/interventions/common/interventions_features.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_user_data.h"
+#include "content/public/test/navigation_simulator.h"
+#include "content/public/test/test_renderer_host.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
+
+namespace content {
+class WebContents;
+}  // namespace content
+
+namespace fingerprinting_protection_interventions {
+namespace {
+
+using ::content::RenderViewHostTestHarness;
+using ::content::WebContents;
+
+static constexpr std::string_view kGoogleUrl = "https://google.com/";
+
+class CanvasInterventionsWebContentsHelperTest
+    : public RenderViewHostTestHarness {
+ public:
+  CanvasInterventionsWebContentsHelperTest() = default;
+
+  void SetUp() override { RenderViewHostTestHarness::SetUp(); }
+
+  void TearDown() override {
+    RenderViewHostTestHarness::TearDown();
+    ResetFeatureState();
+  }
+
+  void ResetFeatureState() { scoped_feature_list_.Reset(); }
+
+  void SetFeatureFlag(bool is_canvas_interventions_feature_enabled) {
+    if (is_canvas_interventions_feature_enabled) {
+      scoped_feature_list_.InitWithFeatures(
+          /*enabled_features=*/
+          {blink::features::kCanvasInterventions},
+          /*disabled_features=*/{});
+    } else {
+      scoped_feature_list_.InitWithFeatures(
+          /*enabled_features=*/{},
+          /*disabled_features=*/{blink::features::kCanvasInterventions});
+    }
+  }
+
+  // Same as above, but will modify the blink::RuntimeFeature value for the
+  // given NavigationHandle instead of the base::Feature value.
+  void SetRuntimeFeatureFlag(bool is_canvas_interventions_feature_enabled,
+                             content::NavigationHandle* navigation_handle) {
+    navigation_handle->GetMutableRuntimeFeatureStateContext()
+        .SetCanvasInterventionsEnabled(is_canvas_interventions_feature_enabled);
+  }
+
+  bool GetRuntimeFeatureFlagValue(
+      content::NavigationHandle* navigation_handle) {
+    auto feature_overrides =
+        navigation_handle->GetMutableRuntimeFeatureStateContext();
+    return feature_overrides.IsCanvasInterventionsEnabled();
+  }
+
+ protected:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+TEST_F(CanvasInterventionsWebContentsHelperTest, CreateForWebContents) {
+  InterventionsWebContentsHelper::CreateForWebContents(
+      RenderViewHostTestHarness::web_contents());
+  EXPECT_NE(nullptr, InterventionsWebContentsHelper::FromWebContents(
+                         RenderViewHostTestHarness::web_contents()));
+}
+
+TEST_F(CanvasInterventionsWebContentsHelperTest,
+       InterventionsNavigationPropagtesCanvasInterventionsFeature) {
+  WebContents* web_contents = RenderViewHostTestHarness::web_contents();
+  InterventionsWebContentsHelper::CreateForWebContents(web_contents);
+  SetFeatureFlag(/*is_canvas_interventions_feature_enabled=*/true);
+
+  std::unique_ptr<content::NavigationSimulator> nav_sim_handle =
+      content::NavigationSimulator::CreateBrowserInitiated(GURL(kGoogleUrl),
+                                                           web_contents);
+  nav_sim_handle->Start();
+  auto* nav_handle = nav_sim_handle->GetNavigationHandle();
+
+  // RuntimeFeature is not updated on the NavigationRequest yet.
+  EXPECT_FALSE(
+      GetRuntimeFeatureFlagValue(nav_sim_handle->GetNavigationHandle()));
+
+  // RuntimeFeature should now be updated after ReadyToCommit.
+  nav_sim_handle->ReadyToCommit();
+
+  EXPECT_TRUE(
+      GetRuntimeFeatureFlagValue(nav_sim_handle->GetNavigationHandle()));
+  EXPECT_EQ(fingerprinting_protection_interventions::features::
+                IsCanvasInterventionsFeatureEnabled(),
+            GetRuntimeFeatureFlagValue(nav_sim_handle->GetNavigationHandle()));
+
+  nav_sim_handle->Commit();
+
+  // Reload navigation with the same web contents.
+  nav_sim_handle = content::NavigationSimulator::CreateBrowserInitiated(
+      GURL(kGoogleUrl), web_contents);
+  nav_sim_handle->Start();
+  nav_handle = nav_sim_handle->GetNavigationHandle();
+
+  // RuntimeFeature is not updated on the NavigationRequest yet.
+  SetRuntimeFeatureFlag(/*is_canvas_interventions_feature_enabled=*/true,
+                        nav_handle);
+  EXPECT_TRUE(GetRuntimeFeatureFlagValue(nav_handle));
+
+  // Now set the browser-wide feature flag to false.
+  ResetFeatureState();
+  SetFeatureFlag(/*is_canvas_interventions_feature_enabled=*/false);
+
+  // RuntimeFeature should now be updated after ReadyToCommit.
+  nav_sim_handle->ReadyToCommit();
+
+  EXPECT_FALSE(GetRuntimeFeatureFlagValue(nav_handle));
+  EXPECT_EQ(fingerprinting_protection_interventions::features::
+                IsCanvasInterventionsFeatureEnabled(),
+            GetRuntimeFeatureFlagValue(nav_handle));
+}
+
+}  // namespace
+}  // namespace fingerprinting_protection_interventions
diff --git a/components/fingerprinting_protection_filter/interventions/common/BUILD.gn b/components/fingerprinting_protection_filter/interventions/common/BUILD.gn
new file mode 100644
index 0000000..c389309
--- /dev/null
+++ b/components/fingerprinting_protection_filter/interventions/common/BUILD.gn
@@ -0,0 +1,20 @@
+# Copyright 2024 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/features.gni")
+
+if (use_blink) {
+  component("features") {
+    output_name = "fingerprinting_protection_interventions_features"
+    defines = [ "IS_FINGERPRINTING_PROTECTION_INTERVENTIONS_FEATURES_IMPL" ]
+    sources = [
+      "interventions_features.cc",
+      "interventions_features.h",
+    ]
+    deps = [
+      "//base",
+      "//third_party/blink/public/common",
+    ]
+  }
+}
diff --git a/components/fingerprinting_protection_filter/interventions/common/DEPS b/components/fingerprinting_protection_filter/interventions/common/DEPS
new file mode 100644
index 0000000..b22fea80
--- /dev/null
+++ b/components/fingerprinting_protection_filter/interventions/common/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+third_party/blink/public/common/features.h",
+]
diff --git a/components/fingerprinting_protection_filter/interventions/common/interventions_features.cc b/components/fingerprinting_protection_filter/interventions/common/interventions_features.cc
new file mode 100644
index 0000000..240de7b
--- /dev/null
+++ b/components/fingerprinting_protection_filter/interventions/common/interventions_features.cc
@@ -0,0 +1,19 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/fingerprinting_protection_filter/interventions/common/interventions_features.h"
+
+#include "base/feature_list.h"
+#include "third_party/blink/public/common/features.h"
+
+namespace fingerprinting_protection_interventions::features {
+
+bool IsCanvasInterventionsFeatureEnabled() {
+  return base::FeatureList::IsEnabled(blink::features::kCanvasInterventions);
+}
+
+// TODO(crbug.com/380458351): Add incognito-specific feature enabled accessor.
+// TODO(crbug.com/380463018): Add base::FeatureParams for signatures.
+
+}  // namespace fingerprinting_protection_interventions::features
diff --git a/components/fingerprinting_protection_filter/interventions/common/interventions_features.h b/components/fingerprinting_protection_filter/interventions/common/interventions_features.h
new file mode 100644
index 0000000..b67d029d
--- /dev/null
+++ b/components/fingerprinting_protection_filter/interventions/common/interventions_features.h
@@ -0,0 +1,23 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_FINGERPRINTING_PROTECTION_FILTER_INTERVENTIONS_COMMON_INTERVENTIONS_FEATURES_H_
+#define COMPONENTS_FINGERPRINTING_PROTECTION_FILTER_INTERVENTIONS_COMMON_INTERVENTIONS_FEATURES_H_
+
+#include "base/component_export.h"
+#include "base/feature_list.h"
+
+namespace fingerprinting_protection_interventions::features {
+
+// Returns true if the global feature flag state of CanvasInterventions
+// blink::RuntimeFeature flag is enabled.
+COMPONENT_EXPORT(FINGERPRINTING_PROTECTION_INTERVENTIONS_FEATURES)
+bool IsCanvasInterventionsFeatureEnabled();
+
+// TODO(crbug.com/380458351): Add incognito-specific feature enabled accessor.
+// TODO(crbug.com/380463018): Add base::FeatureParams for signatures.
+
+}  // namespace fingerprinting_protection_interventions::features
+
+#endif  // COMPONENTS_FINGERPRINTING_PROTECTION_FILTER_INTERVENTIONS_COMMON_INTERVENTIONS_FEATURES_H_
diff --git a/components/history_embeddings/BUILD.gn b/components/history_embeddings/BUILD.gn
index 05f6238..a3cb3bc0c 100644
--- a/components/history_embeddings/BUILD.gn
+++ b/components/history_embeddings/BUILD.gn
@@ -2,8 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/chromeos/ui_mode.gni")
-
 static_library("history_embeddings") {
   sources = [
     "answerer.cc",
@@ -53,10 +51,6 @@
     "//third_party/zlib/google:compression_utils",
     "//url",
   ]
-
-  if (is_chromeos) {
-    deps += [ "//chromeos/constants:constants" ]
-  }
 }
 
 source_set("test_support") {
@@ -107,9 +101,5 @@
     deps += [ "//components/test:history_embeddings_test_bundle_data" ]
   }
 
-  if (is_chromeos) {
-    deps += [ "//chromeos/constants:constants" ]
-  }
-
   data = [ "//components/test/data/history_embeddings/" ]
 }
diff --git a/components/history_embeddings/DEPS b/components/history_embeddings/DEPS
index 1bd500f..6ada97f 100644
--- a/components/history_embeddings/DEPS
+++ b/components/history_embeddings/DEPS
@@ -1,5 +1,4 @@
 include_rules = [
-  "+chromeos/constants/chromeos_features.h",
   "+components/history/core",
   "+components/keyed_service/core",
   "+components/optimization_guide/core",
diff --git a/components/history_embeddings/history_embeddings_features.cc b/components/history_embeddings/history_embeddings_features.cc
index a7b4ec1..36d3728 100644
--- a/components/history_embeddings/history_embeddings_features.cc
+++ b/components/history_embeddings/history_embeddings_features.cc
@@ -8,10 +8,6 @@
 #include "base/metrics/field_trial_params.h"
 #include "build/build_config.h"
 
-#if BUILDFLAG(IS_CHROMEOS)
-#include "chromeos/constants/chromeos_features.h"
-#endif
-
 namespace history_embeddings {
 
 namespace {
@@ -23,12 +19,26 @@
 
 }  // namespace
 
-// Please use `IsFeatureManagementHistoryEmbeddingEnabled()` instead
-// of using `kHistoryEmbeddings` directly.
+// These are the kill switches for the launched history embeddings features.
+BASE_FEATURE(kLaunchedHistoryEmbeddings,
+             "LaunchedHistoryEmbeddings",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+BASE_FEATURE(kLaunchedHistoryEmbeddingsAnswers,
+             "LaunchedHistoryEmbeddingsAnswers",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
+// This is the main feature switch for history embeddings search, and when it is
+// disabled, answering functionality will not be available either. This feature
+// is client-side launched on desktop platforms in US only, so it remains
+// disabled by default for other regions.
 BASE_FEATURE(kHistoryEmbeddings,
              "HistoryEmbeddings",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+// This feature specifies whether to answer queries using an answerer; it can be
+// considered a toggle for v2 answering functionality. Parameters are all kept
+// under the primary kHistoryEmbeddings feature. The kHistoryEmbeddingsAnswers
+// feature state is not applicable if kHistoryEmbeddings is disabled.
 // Note: This feature has no parameters. Since it entirely depends on the
 // above kHistoryEmbeddings feature, all parameters are owned by that
 // feature to avoid confusion about which feature owns which parameters.
@@ -36,6 +46,8 @@
              "HistoryEmbeddingsAnswers",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+////////////////////////////////////////////////////////////////////////////////
+
 const base::FeatureParam<bool> kShowSourcePassages(&kHistoryEmbeddings,
                                                    "ShowSourcePassages",
                                                    false);
@@ -105,7 +117,7 @@
 
 const base::FeatureParam<bool> kUseMlAnswerer(&kHistoryEmbeddings,
                                               "UseMlAnswerer",
-                                              false);
+                                              true);
 
 const base::FeatureParam<double> kMlAnswererMinScore(&kHistoryEmbeddings,
                                                      "MlAnswererMinScore",
@@ -139,7 +151,7 @@
 
 const base::FeatureParam<bool> kAnswersInOmniboxScoped(&kHistoryEmbeddings,
                                                        "AnswersInOmniboxScoped",
-                                                       false);
+                                                       true);
 
 const base::FeatureParam<int> kScheduledEmbeddingsMax(&kHistoryEmbeddings,
                                                       "ScheduledEmbeddingsMax",
@@ -147,10 +159,10 @@
 
 const base::FeatureParam<bool> kSendQualityLog(&kHistoryEmbeddings,
                                                "SendQualityLog",
-                                               false);
+                                               true);
 const base::FeatureParam<bool> kSendQualityLogV2(&kHistoryEmbeddings,
                                                  "SendQualityLogV2",
-                                                 false);
+                                                 true);
 
 const base::FeatureParam<int> kMaxPassagesPerPage(&kHistoryEmbeddings,
                                                   "MaxPassagesPerPage",
@@ -174,11 +186,11 @@
 
 const base::FeatureParam<bool> kEnableSidePanel(&kHistoryEmbeddings,
                                                 "EnableSidePanel",
-                                                false);
+                                                true);
 
 const base::FeatureParam<bool> kTrimAfterHostInResults(&kHistoryEmbeddings,
                                                        "TrimAfterHostInResults",
-                                                       false);
+                                                       true);
 
 const base::FeatureParam<int> kMaxAnswererContextUrlCount(
     &kHistoryEmbeddings,
@@ -188,11 +200,11 @@
 const base::FeatureParam<double> kWordMatchMinEmbeddingScore(
     &kHistoryEmbeddings,
     "WordMatchMinEmbeddingScore",
-    1.0);
+    0.7);
 
 const base::FeatureParam<int> kWordMatchMinTermLength(&kHistoryEmbeddings,
                                                       "WordMatchMinTermLength",
-                                                      3);
+                                                      0);
 
 const base::FeatureParam<double> kWordMatchScoreBoostFactor(
     &kHistoryEmbeddings,
@@ -206,11 +218,11 @@
 const base::FeatureParam<int> kWordMatchSmoothingFactor(
     &kHistoryEmbeddings,
     "WordMatchSmoothingFactor",
-    1);
+    0);
 
 const base::FeatureParam<int> kWordMatchMaxTermCount(&kHistoryEmbeddings,
                                                      "WordMatchMaxTermCount",
-                                                     3);
+                                                     10);
 
 const base::FeatureParam<double> kWordMatchRequiredTermRatio(
     &kHistoryEmbeddings,
@@ -226,20 +238,6 @@
     "EraseNonAsciiCharacters",
     false);
 
-bool IsHistoryEmbeddingsEnabled() {
-#if BUILDFLAG(IS_CHROMEOS)
-  return chromeos::features::IsFeatureManagementHistoryEmbeddingEnabled() &&
-         base::FeatureList::IsEnabled(kHistoryEmbeddings);
-#else
-  return base::FeatureList::IsEnabled(kHistoryEmbeddings);
-#endif
-}
-
-bool IsHistoryEmbeddingsAnswersEnabled() {
-  return IsHistoryEmbeddingsEnabled() &&
-         base::FeatureList::IsEnabled(kHistoryEmbeddingsAnswers);
-}
-
 FeatureParameters::FeatureParameters(bool load_finch) {
   if (!load_finch) {
     return;
diff --git a/components/history_embeddings/history_embeddings_features.h b/components/history_embeddings/history_embeddings_features.h
index 272e0e6..88e3ff3 100644
--- a/components/history_embeddings/history_embeddings_features.h
+++ b/components/history_embeddings/history_embeddings_features.h
@@ -11,26 +11,16 @@
 
 namespace history_embeddings {
 
-// This is the main feature switch for history embeddings search, and when it is
-// disabled, answering functionality will not be available either.
+// Please use `IsHistoryEmbeddingsFeatureEnabled()` instead of using any of
+// these features directly.
+// See chrome/browser/history_embeddings/history_embeddings_utils.h
+BASE_DECLARE_FEATURE(kLaunchedHistoryEmbeddings);
+BASE_DECLARE_FEATURE(kLaunchedHistoryEmbeddingsAnswers);
 BASE_DECLARE_FEATURE(kHistoryEmbeddings);
-
-// This feature specifies whether to answer queries using an answerer; it can be
-// considered a toggle for v2 answering functionality. Parameters are all kept
-// under the primary kHistoryEmbeddings feature. The kHistoryEmbeddingsAnswers
-// feature state is not applicable if kHistoryEmbeddings is disabled.
 BASE_DECLARE_FEATURE(kHistoryEmbeddingsAnswers);
 
-// Whether the history embeddings feature is enabled. This only checks if the
-// feature flags are enabled and does not check the user's opt-in preference.
-// See chrome/browser/history_embeddings/history_embeddings_utils.h.
-bool IsHistoryEmbeddingsEnabled();
-
-// Whether the history answers feature is enabled.
-bool IsHistoryEmbeddingsAnswersEnabled();
-
 // Contains feature configuration state. Can be set using Finch or overridden
-// for testing. Prefer to use this struct instead of above feature parameters
+// for testing. Prefer to use this struct instead of feature parameters
 // directly so as to reduce dependency on Finch.
 struct FeatureParameters {
   explicit FeatureParameters(bool load_finch);
@@ -96,7 +86,7 @@
   int mock_intent_classifier_delay_ms = 0;
 
   // Specifies whether to use the ML Answerer (if false, the mock is used).
-  bool use_ml_answerer = false;
+  bool use_ml_answerer = true;
 
   // Specifies the min score for generated answer from the ML answerer.
   double ml_answerer_min_score = 0.5;
@@ -128,15 +118,15 @@
 
   // Whether history embedding answers should be shown in the omnibox when in
   // the '@history' scope. No-op if `kOmniboxScoped` is false.
-  bool answers_in_omnibox_scoped = false;
+  bool answers_in_omnibox_scoped = true;
 
   // The maximum number of embeddings to submit to the primary (ML) embedder
   // in a single batch via the scheduling embedder.
   int scheduled_embeddings_max = 1;
 
   // Whether quality logging data should be sent.
-  bool send_quality_log = false;
-  bool send_quality_log_v2 = false;
+  bool send_quality_log = true;
+  bool send_quality_log_v2 = true;
 
   // The max number of passages that can be extracted from a page. Passages over
   // this limit will be dropped by passage extraction.
@@ -163,23 +153,23 @@
 
   // Specifies whether the history clusters side panel UI also searches and
   // shows history embeddings.
-  bool enable_side_panel = false;
+  bool enable_side_panel = true;
 
   // Specifies whether history embedding results should show just the hostname
   // of the result's URL.
-  bool trim_after_host_in_results = false;
+  bool trim_after_host_in_results = true;
 
   // The maximum number of URLs to use when building context for answerer.
   int max_answerer_context_url_count = 1;
 
   // These control score boosting from passage text word matching.
   // See comments for `SearchParams` struct for more details about each value.
-  double word_match_min_embedding_score = 1.0;
-  int word_match_min_term_length = 3;
+  double word_match_min_embedding_score = 0.7;
+  int word_match_min_term_length = 0;
   double word_match_score_boost_factor = 0.2;
   int word_match_limit = 5;
-  int word_match_smoothing_factor = 1;
-  int word_match_max_term_count = 3;
+  int word_match_smoothing_factor = 0;
+  int word_match_max_term_count = 10;
   double word_match_required_term_ratio = 1.0;
 
   // Whether to include scroll to text fragment directives with answer
diff --git a/components/history_embeddings/history_embeddings_service.cc b/components/history_embeddings/history_embeddings_service.cc
index 3de2ab7..f8fe726 100644
--- a/components/history_embeddings/history_embeddings_service.cc
+++ b/components/history_embeddings/history_embeddings_service.cc
@@ -237,19 +237,15 @@
       query_id_(0u),
       query_id_weak_ptr_factory_(&query_id_),
       weak_ptr_factory_(this) {
-  if (!history_embeddings::IsHistoryEmbeddingsEnabled()) {
-    // If the feature flag is disabled, skip initialization. Note we don't also
-    // check the pref here, because the pref can change at runtime.
-    return;
-  }
-
   // The history service is never nullptr; even unit tests should provide it.
   CHECK(history_service_);
   storage_ = base::SequenceBound<Storage>(
       base::ThreadPool::CreateSequencedTaskRunner(
           {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
            base::TaskShutdownBehavior::BLOCK_SHUTDOWN}),
-      history_service_->history_dir());
+      history_service_->history_dir(),
+      GetFeatureParameters().erase_non_ascii_characters,
+      GetFeatureParameters().delete_embeddings);
   history_service_observation_.Observe(history_service_);
 
   // Notify page content annotations service that we will need the content
@@ -665,8 +661,11 @@
   passages_stored_callback_for_tests_ = std::move(callback);
 }
 
-HistoryEmbeddingsService::Storage::Storage(const base::FilePath& storage_dir)
-    : sql_database(storage_dir) {}
+HistoryEmbeddingsService::Storage::Storage(const base::FilePath& storage_dir,
+                                           bool erase_non_ascii_characters,
+                                           bool delete_embeddings)
+    : sql_database(storage_dir, erase_non_ascii_characters, delete_embeddings) {
+}
 
 void HistoryEmbeddingsService::Storage::SetEmbedderMetadata(
     passage_embeddings::EmbedderMetadata metadata,
diff --git a/components/history_embeddings/history_embeddings_service.h b/components/history_embeddings/history_embeddings_service.h
index 511e341..f23a19b 100644
--- a/components/history_embeddings/history_embeddings_service.h
+++ b/components/history_embeddings/history_embeddings_service.h
@@ -244,7 +244,9 @@
   // A utility container to wrap anything that should be accessed on
   // the separate storage worker sequence.
   struct Storage {
-    explicit Storage(const base::FilePath& storage_dir);
+    Storage(const base::FilePath& storage_dir,
+            bool erase_non_ascii_characters,
+            bool delete_embeddings);
 
     // Associate the given metadata with this Storage instance. The storage is
     // not considered initialized until this metadata is supplied.
diff --git a/components/history_embeddings/history_embeddings_service_unittest.cc b/components/history_embeddings/history_embeddings_service_unittest.cc
index 2ed0fd8..51c13a2 100644
--- a/components/history_embeddings/history_embeddings_service_unittest.cc
+++ b/components/history_embeddings/history_embeddings_service_unittest.cc
@@ -38,10 +38,6 @@
 #include "components/page_content_annotations/core/test_page_content_annotator.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if BUILDFLAG(IS_CHROMEOS)
-#include "chromeos/constants/chromeos_features.h"
-#endif  // BUILDFLAG(IS_CHROMEOS)
-
 namespace history_embeddings {
 
 using passage_embeddings::ComputeEmbeddingsStatus;
@@ -100,9 +96,6 @@
     feature_list_.InitWithFeaturesAndParameters(
         {{kHistoryEmbeddings, {}},
          {kHistoryEmbeddingsAnswers, {}},
-#if BUILDFLAG(IS_CHROMEOS)
-         {chromeos::features::kFeatureManagementHistoryEmbedding, {{}}}
-#endif  // BUILDFLAG(IS_CHROMEOS)
         },
         /*disabled_features=*/{});
 
@@ -718,10 +711,13 @@
     EXPECT_LT(std::ranges::max(row.scores), row.scored_url.score);
   }
   {
+    // Default configuration allows ten terms in query before switching off
+    // word match boosting.
     base::test::TestFuture<SearchResult> future;
-    service_->Search(/*previous_search_result=*/nullptr,
-                     "this very long test query isn't boosted", {}, 1,
-                     future.GetRepeatingCallback());
+    service_->Search(
+        /*previous_search_result=*/nullptr,
+        "this very very very very very long test query isn't boosted", {}, 1,
+        future.GetRepeatingCallback());
     SearchResult result = future.Take();
     EXPECT_EQ(result.scored_url_rows.size(), 1u);
     const ScoredUrlRow& row = result.scored_url_rows[0];
diff --git a/components/history_embeddings/mock_history_embeddings_service.cc b/components/history_embeddings/mock_history_embeddings_service.cc
index a261ad80..c3f92c2b 100644
--- a/components/history_embeddings/mock_history_embeddings_service.cc
+++ b/components/history_embeddings/mock_history_embeddings_service.cc
@@ -4,17 +4,20 @@
 
 #include "components/history_embeddings/mock_history_embeddings_service.h"
 
+#include "components/history_embeddings/mock_embedder.h"
+
 namespace history_embeddings {
 
 MockHistoryEmbeddingsService::MockHistoryEmbeddingsService(
+    os_crypt_async::OSCryptAsync* os_crypt_async,
     history::HistoryService* history_service)
-    : HistoryEmbeddingsService(nullptr,
+    : HistoryEmbeddingsService(/*os_crypt_async=*/os_crypt_async,
                                history_service,
                                nullptr,
                                nullptr,
-                               nullptr,
-                               nullptr,
-                               nullptr) {}
+                               /*embedder=*/std::make_unique<MockEmbedder>(),
+                               /*answerer=*/nullptr,
+                               /*intent_classifier=*/nullptr) {}
 
 MockHistoryEmbeddingsService::~MockHistoryEmbeddingsService() = default;
 
diff --git a/components/history_embeddings/mock_history_embeddings_service.h b/components/history_embeddings/mock_history_embeddings_service.h
index ae764cf9..09de6297 100644
--- a/components/history_embeddings/mock_history_embeddings_service.h
+++ b/components/history_embeddings/mock_history_embeddings_service.h
@@ -13,6 +13,10 @@
 #include "components/history_embeddings/history_embeddings_service.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
+namespace os_crypt_async {
+class OSCryptAsync;
+}  // namespace os_crypt_async
+
 namespace history_embeddings {
 
 class MockHistoryEmbeddingsService : public HistoryEmbeddingsService {
@@ -26,6 +30,7 @@
                SearchResultCallback callback),
               (override));
   explicit MockHistoryEmbeddingsService(
+      os_crypt_async::OSCryptAsync* os_crypt_async,
       history::HistoryService* history_service);
   ~MockHistoryEmbeddingsService() override;
 };
diff --git a/components/history_embeddings/sql_database.cc b/components/history_embeddings/sql_database.cc
index 5f48ef4..d0f2523 100644
--- a/components/history_embeddings/sql_database.cc
+++ b/components/history_embeddings/sql_database.cc
@@ -90,8 +90,12 @@
 
 }  // namespace
 
-SqlDatabase::SqlDatabase(const base::FilePath& storage_dir)
+SqlDatabase::SqlDatabase(const base::FilePath& storage_dir,
+                         bool erase_non_ascii_characters,
+                         bool delete_embeddings)
     : storage_dir_(storage_dir),
+      erase_non_ascii_characters_(erase_non_ascii_characters),
+      delete_embeddings_(delete_embeddings),
       db_(/*tag=*/"HistoryEmbeddings"),
       weak_ptr_factory_(this) {}
 
@@ -190,11 +194,11 @@
 
     bool delete_embeddings =
         model_version != embedder_metadata_->model_version ||
-        GetFeatureParameters().delete_embeddings;
+        delete_embeddings_;
 
     // TODO(crbug.com/375502129): Remove this guard and the related guard below
     //  for more complete data version handling.
-    if (GetFeatureParameters().erase_non_ascii_characters) {
+    if (erase_non_ascii_characters_) {
       int embeddings_data_version = 0;
       meta_table.GetValue(kKeyEmbeddingsDataVersion, &embeddings_data_version);
       delete_embeddings |= embeddings_data_version != kEmbeddingsDataVersion;
@@ -213,7 +217,7 @@
       // doing so will result in the embeddings being rebuilt with the
       // non-ASCII character changes.
       // TODO(crbug.com/375502129): See above TODO comment; remove this guard.
-      if (GetFeatureParameters().erase_non_ascii_characters &&
+      if (erase_non_ascii_characters_ &&
           !meta_table.SetValue(kKeyEmbeddingsDataVersion,
                                kEmbeddingsDataVersion)) {
         return sql::InitStatus::INIT_FAILURE;
diff --git a/components/history_embeddings/sql_database.h b/components/history_embeddings/sql_database.h
index 091ddd47..c823ece 100644
--- a/components/history_embeddings/sql_database.h
+++ b/components/history_embeddings/sql_database.h
@@ -33,7 +33,9 @@
 class SqlDatabase : public VectorDatabase {
  public:
   // `storage_dir` will generally be the Profile directory.
-  explicit SqlDatabase(const base::FilePath& storage_dir);
+  SqlDatabase(const base::FilePath& storage_dir,
+              bool erase_non_ascii_characters,
+              bool delete_embeddings);
   SqlDatabase(const SqlDatabase&) = delete;
   SqlDatabase& operator=(const SqlDatabase&) = delete;
   ~SqlDatabase() override;
@@ -120,6 +122,18 @@
   // The directory storing the database.
   const base::FilePath storage_dir_;
 
+  // This holds a snapshot of
+  // `GetFeatureParameters().erase_non_ascii_characters` to affect database
+  // initialization without racing for global state. Parameters are immutable in
+  // production but mutable in tests, so this avoids access off main thread.
+  const bool erase_non_ascii_characters_;
+
+  // This holds a snapshot of
+  // `GetFeatureParameters().delete_embeddings` to affect database
+  // initialization without racing for global state. Parameters are immutable in
+  // production but mutable in tests, so this avoids access off main thread.
+  const bool delete_embeddings_;
+
   // Metadata of the embeddings model.
   std::optional<passage_embeddings::EmbedderMetadata> embedder_metadata_;
 
diff --git a/components/history_embeddings/sql_database_unittest.cc b/components/history_embeddings/sql_database_unittest.cc
index 6fbf3ed..4b026b1e 100644
--- a/components/history_embeddings/sql_database_unittest.cc
+++ b/components/history_embeddings/sql_database_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_future.h"
+#include "components/history_embeddings/history_embeddings_features.h"
 #include "components/history_embeddings/proto/history_embeddings.pb.h"
 #include "components/os_crypt/async/browser/test_utils.h"
 #include "components/os_crypt/async/common/encryptor.h"
@@ -45,6 +46,13 @@
     CHECK(history_dir_.Delete());
   }
 
+  std::unique_ptr<SqlDatabase> MakeDatabase() {
+    return std::make_unique<SqlDatabase>(
+        history_dir_.GetPath(),
+        GetFeatureParameters().erase_non_ascii_characters,
+        GetFeatureParameters().delete_embeddings);
+  }
+
   // Adds mock data for url_id = 1 tied to visit_id = 10, and url_id = 2 tied to
   // visit_id = 11.
   void AddBasicMockData(SqlDatabase* sql_database) {
@@ -100,7 +108,7 @@
 };
 
 TEST_F(HistoryEmbeddingsSqlDatabaseTest, WriteCloseAndThenReadPassages) {
-  auto sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath());
+  auto sql_database = MakeDatabase();
   sql_database->SetEmbedderMetadata({kEmbeddingsVersion, kEmbeddingsSize},
                                     GetEncryptorInstance());
 
@@ -114,7 +122,7 @@
 
   // Reset and reload.
   sql_database.reset();
-  sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath());
+  sql_database = MakeDatabase();
   sql_database->SetEmbedderMetadata({kEmbeddingsVersion, kEmbeddingsSize},
                                     GetEncryptorInstance());
 
@@ -132,7 +140,7 @@
 }
 
 TEST_F(HistoryEmbeddingsSqlDatabaseTest, WriteCloseAndThenReadUrlData) {
-  auto sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath());
+  auto sql_database = MakeDatabase();
   sql_database->SetEmbedderMetadata({kEmbeddingsVersion, kEmbeddingsSize},
                                     GetEncryptorInstance());
 
@@ -152,7 +160,7 @@
 
   // Reset and reload.
   sql_database.reset();
-  sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath());
+  sql_database = MakeDatabase();
   sql_database->SetEmbedderMetadata({kEmbeddingsVersion, kEmbeddingsSize},
                                     GetEncryptorInstance());
 
@@ -177,7 +185,7 @@
 }
 
 TEST_F(HistoryEmbeddingsSqlDatabaseTest, TimeRangeNarrowsSearchResult) {
-  auto sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath());
+  auto sql_database = MakeDatabase();
   sql_database->SetEmbedderMetadata({kEmbeddingsVersion, kEmbeddingsSize},
                                     GetEncryptorInstance());
 
@@ -248,7 +256,7 @@
 }
 
 TEST_F(HistoryEmbeddingsSqlDatabaseTest, InsertOrReplacePassages) {
-  auto sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath());
+  auto sql_database = MakeDatabase();
   sql_database->SetEmbedderMetadata({kEmbeddingsVersion, kEmbeddingsSize},
                                     GetEncryptorInstance());
 
@@ -275,7 +283,7 @@
 }
 
 TEST_F(HistoryEmbeddingsSqlDatabaseTest, IteratorMaySafelyOutliveDatabase) {
-  auto sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath());
+  auto sql_database = MakeDatabase();
   sql_database->SetEmbedderMetadata({kEmbeddingsVersion, kEmbeddingsSize},
                                     GetEncryptorInstance());
   AddBasicMockData(sql_database.get());
@@ -303,7 +311,7 @@
 }
 
 TEST_F(HistoryEmbeddingsSqlDatabaseTest, DeleteDataForUrlId) {
-  auto sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath());
+  auto sql_database = MakeDatabase();
   sql_database->SetEmbedderMetadata({kEmbeddingsVersion, kEmbeddingsSize},
                                     GetEncryptorInstance());
   AddBasicMockData(sql_database.get());
@@ -323,7 +331,7 @@
 }
 
 TEST_F(HistoryEmbeddingsSqlDatabaseTest, DeleteDataForVisitId) {
-  auto sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath());
+  auto sql_database = MakeDatabase();
   sql_database->SetEmbedderMetadata({kEmbeddingsVersion, kEmbeddingsSize},
                                     GetEncryptorInstance());
   AddBasicMockData(sql_database.get());
@@ -343,7 +351,7 @@
 }
 
 TEST_F(HistoryEmbeddingsSqlDatabaseTest, DeleteAllData) {
-  auto sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath());
+  auto sql_database = MakeDatabase();
   sql_database->SetEmbedderMetadata({kEmbeddingsVersion, kEmbeddingsSize},
                                     GetEncryptorInstance());
   AddBasicMockData(sql_database.get());
@@ -360,7 +368,7 @@
   url_data.embeddings.emplace_back(std::vector<float>(kEmbeddingsSize, 1.0f));
 
   {
-    auto sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath());
+    auto sql_database = MakeDatabase();
 
     // Adding data is expected to fail because the database can't initialize
     // fully without embedder metadata.
@@ -377,7 +385,7 @@
   {
     // Initialize database again, to see that we can still get it only when
     // metadata is provided.
-    auto sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath());
+    auto sql_database = MakeDatabase();
     EXPECT_FALSE(sql_database->GetPassages(1));
     sql_database->SetEmbedderMetadata({kEmbeddingsVersion, kEmbeddingsSize},
                                       GetEncryptorInstance());
@@ -387,7 +395,7 @@
   }
   {
     // Initialize database again, with no embedder metadata.
-    auto sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath());
+    auto sql_database = MakeDatabase();
     EXPECT_FALSE(sql_database->GetPassages(1));
 
     // Deletion succeeds even with no metadata provided.
@@ -402,7 +410,7 @@
 }
 
 TEST_F(HistoryEmbeddingsSqlDatabaseTest, GetUrlData) {
-  auto sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath());
+  auto sql_database = MakeDatabase();
   sql_database->SetEmbedderMetadata({kEmbeddingsVersion, kEmbeddingsSize},
                                     GetEncryptorInstance());
   {
@@ -446,7 +454,7 @@
 }
 
 TEST_F(HistoryEmbeddingsSqlDatabaseTest, IterationSkipsAndReportsMismatches) {
-  auto sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath());
+  auto sql_database = MakeDatabase();
   sql_database->SetEmbedderMetadata({kEmbeddingsVersion, kEmbeddingsSize},
                                     GetEncryptorInstance());
 
@@ -485,7 +493,7 @@
 }
 
 TEST_F(HistoryEmbeddingsSqlDatabaseTest, OldVisitsAreExpired) {
-  auto sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath());
+  auto sql_database = MakeDatabase();
   sql_database->SetEmbedderMetadata({kEmbeddingsVersion, kEmbeddingsSize},
                                     GetEncryptorInstance());
 
@@ -504,7 +512,7 @@
 
   // Reset and reload.
   sql_database.reset();
-  sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath());
+  sql_database = MakeDatabase();
   sql_database->SetEmbedderMetadata({kEmbeddingsVersion, kEmbeddingsSize},
                                     GetEncryptorInstance());
 
diff --git a/components/history_embeddings/vector_database.cc b/components/history_embeddings/vector_database.cc
index e873565..3c85a68 100644
--- a/components/history_embeddings/vector_database.cc
+++ b/components/history_embeddings/vector_database.cc
@@ -441,6 +441,9 @@
     const std::unordered_set<uint32_t>& stop_words_hashes,
     std::string_view raw_query,
     size_t min_term_length) {
+  // Configuration may permit zero-length terms, but empty strings
+  // are never useful in search so the effective minimum then is one.
+  min_term_length = min_term_length > 0 ? min_term_length : 1;
   std::string query = base::ToLowerASCII(raw_query);
   std::string_view query_view(query);
   std::vector<std::string> query_terms;
diff --git a/components/input/render_input_router.cc b/components/input/render_input_router.cc
index 643335f..fdd90f36 100644
--- a/components/input/render_input_router.cc
+++ b/components/input/render_input_router.cc
@@ -147,6 +147,11 @@
   input_router_->SetDeviceScaleFactor(device_scale_factor);
 }
 
+void RenderInputRouter::SetFlingScheduler(
+    std::unique_ptr<FlingSchedulerBase> fling_scheduler) {
+  fling_scheduler_ = std::move(fling_scheduler);
+}
+
 void RenderInputRouter::BindRenderInputRouterInterfaces(
     mojo::PendingRemote<blink::mojom::RenderInputRouterClient> remote) {
   client_remote_.reset();
diff --git a/components/input/render_input_router.h b/components/input/render_input_router.h
index 739d1f12..469148c 100644
--- a/components/input/render_input_router.h
+++ b/components/input/render_input_router.h
@@ -59,6 +59,7 @@
                     scoped_refptr<base::SingleThreadTaskRunner> task_runner);
 
   void SetupInputRouter(float device_scale_factor);
+  void SetFlingScheduler(std::unique_ptr<FlingSchedulerBase> fling_scheduler);
 
   void BindRenderInputRouterInterfaces(
       mojo::PendingRemote<blink::mojom::RenderInputRouterClient> remote);
@@ -196,6 +197,9 @@
 
   void SetInputTargetClientForTesting(
       mojo::Remote<viz::mojom::InputTargetClient> input_target_client);
+  FlingSchedulerBase* GetFlingSchedulerForTesting() {
+    return fling_scheduler_.get();
+  }
 
  private:
   friend content::MockRenderInputRouter;
diff --git a/components/language_detection/content/renderer/DEPS b/components/language_detection/content/renderer/DEPS
index 2cb9bd89..f4d7029 100644
--- a/components/language_detection/content/renderer/DEPS
+++ b/components/language_detection/content/renderer/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
   "+content/public/renderer",
   "+third_party/blink/public/platform",
+  "+third_party/blink/renderer/platform",
   "+components/translate/content/common/language_detection.mojom.h",
   "+components/language_detection/core/language_detection_model.h",
 ]
diff --git a/components/media_router/common/discovery/media_sink_internal.h b/components/media_router/common/discovery/media_sink_internal.h
index c4e212f..f48e5dd 100644
--- a/components/media_router/common/discovery/media_sink_internal.h
+++ b/components/media_router/common/discovery/media_sink_internal.h
@@ -48,8 +48,6 @@
 struct CastSinkExtraData {
   net::IPEndPoint ip_endpoint;
 
-  int port = 0;
-
   // Model name of the sink.
   std::string model_name;
 
diff --git a/components/neterror/resources/neterror.css b/components/neterror/resources/neterror.css
index 5889319..dbdbeac 100644
--- a/components/neterror/resources/neterror.css
+++ b/components/neterror/resources/neterror.css
@@ -97,11 +97,6 @@
 </if>
 }
 
-[jscontent=hostName],
-[jscontent=failedUrl] {
-  overflow-wrap: break-word;
-}
-
 .secondary-button {
   background: #d9d9d9;
   color: #696969;
diff --git a/components/neterror/resources/neterror.ts b/components/neterror/resources/neterror.ts
index 3cab681..2c3701f 100644
--- a/components/neterror/resources/neterror.ts
+++ b/components/neterror/resources/neterror.ts
@@ -33,7 +33,6 @@
   // Properties that exist in both error pages and chrome://dino.
   errorCode: string;
   heading: {
-    hostName: string,
     msg: string,
   };
   iconClass: string;
@@ -47,8 +46,6 @@
   suggestionsSummaryListHeader?: string;
 
   summary?: {
-    failedUrl: string,
-    hostName: string,
     msg: string,
   };
 
diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn
index a429fa7..ad1e0a22 100644
--- a/components/omnibox/browser/BUILD.gn
+++ b/components/omnibox/browser/BUILD.gn
@@ -884,6 +884,7 @@
     "//components/optimization_guide/core",
     "//components/optimization_guide/core:test_support",
     "//components/optimization_guide/proto:optimization_guide_proto",
+    "//components/os_crypt/async/browser",
     "//components/prefs:test_support",
     "//components/query_parser:query_parser",
     "//components/safe_browsing/core/common:common",
diff --git a/components/omnibox/browser/DEPS b/components/omnibox/browser/DEPS
index 8152a67a..af44756 100644
--- a/components/omnibox/browser/DEPS
+++ b/components/omnibox/browser/DEPS
@@ -26,6 +26,7 @@
   "+components/optimization_guide",
   "+components/optimization_guide/core",
   "+components/optimization_guide/proto",
+  "+components/os_crypt/async/browser",
   "+components/pref_registry",
   "+components/prefs",
   "+components/query_parser",
diff --git a/components/omnibox/browser/history_embeddings_provider_unittest.cc b/components/omnibox/browser/history_embeddings_provider_unittest.cc
index 0aadf73..9f23ac67 100644
--- a/components/omnibox/browser/history_embeddings_provider_unittest.cc
+++ b/components/omnibox/browser/history_embeddings_provider_unittest.cc
@@ -32,6 +32,8 @@
 #include "components/omnibox/browser/omnibox_triggered_feature_service.h"
 #include "components/omnibox/browser/test_scheme_classifier.h"
 #include "components/optimization_guide/proto/features/history_answer.pb.h"
+#include "components/os_crypt/async/browser/os_crypt_async.h"
+#include "components/os_crypt/async/browser/test_utils.h"
 #include "components/search_engines/template_url.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/metrics_proto/omnibox_event.pb.h"
@@ -107,6 +109,13 @@
   void SetUp() override {
     testing::Test::SetUp();
 
+    os_crypt_ = os_crypt_async::GetTestOSCryptAsyncForTesting(
+        /*is_sync_for_unittests=*/true);
+
+    auto feature_parameters = history_embeddings::GetFeatureParameters();
+    feature_parameters.use_ml_answerer = false;
+    history_embeddings::SetFeatureParametersForTesting(feature_parameters);
+
     CHECK(history_dir_.CreateUniqueTempDir());
     client_ = std::make_unique<FakeAutocompleteProviderClient>();
     client_->set_history_service(
@@ -114,7 +123,7 @@
     client_->set_history_embeddings_service(
         std::make_unique<testing::NiceMock<
             history_embeddings::MockHistoryEmbeddingsService>>(
-            client_->GetHistoryService()));
+            os_crypt_.get(), client_->GetHistoryService()));
     history_embeddings_service_ = static_cast<
         testing::NiceMock<history_embeddings::MockHistoryEmbeddingsService>*>(
         client_->GetHistoryEmbeddingsService());
@@ -148,6 +157,7 @@
   }
 
   base::ScopedTempDir history_dir_;
+  std::unique_ptr<os_crypt_async::OSCryptAsync> os_crypt_;
   base::test::TaskEnvironment task_environment_;
   std::unique_ptr<FakeAutocompleteProviderClient> client_;
   raw_ptr<testing::NiceMock<history_embeddings::MockHistoryEmbeddingsService>>
diff --git a/components/omnibox/resources/translations/omnibox_pedal_synonyms_sl.xtb b/components/omnibox/resources/translations/omnibox_pedal_synonyms_sl.xtb
index c9ed8d8..6e5a670 100644
--- a/components/omnibox/resources/translations/omnibox_pedal_synonyms_sl.xtb
+++ b/components/omnibox/resources/translations/omnibox_pedal_synonyms_sl.xtb
@@ -8,7 +8,7 @@
 <translation id="1938436187879863297">ustvarjanje zapiska v googlu keep, ustvarjanje zapiska v googlu, ustvarjanje novega zapiska v googlu keep, nov zapisek v googlu, začetek zapiska v googlu</translation>
 <translation id="2003251155164817216">prilagajanje videza chroma, upravljanje tem za chrome</translation>
 <translation id="2757458512261408467">ustvari povabilo za google koledar, ustvari dogodek v google koledarju, ustvari novo povabilo za koledar, nov dogodek v koledarju, novo povabilo za google koledar</translation>
-<translation id="2903767089701932453">nastavitve piškotkov za chrome, uporaba piškotkov, onemogočanje vseh piškotkov drugih mest, upravljanje nastavitev piškotkov, upravljanje piškotkov</translation>
+<translation id="2903767089701932453">nastavitve piškotkov za chrome, uporaba piškotkov, onemogočanje vseh piškotkov tretjih oseb, upravljanje nastavitev piškotkov, upravljanje piškotkov</translation>
 <translation id="2941773220794601465">prevajanje te strani, prevajanje spletne strani</translation>
 <translation id="2973110773361184993">prilagajanje dovoljenj za spletno mesto, spreminjanje dovoljenj, nadziranje nastavitev spletnega mesta, upravljanje nastavitev spletnega mesta, nastavitve spletnih mest v chromu</translation>
 <translation id="3371457011763794419">posodobitev chroma, nadgradnja brskalnika</translation>
diff --git a/components/optimization_guide/content/browser/page_content_proto_util.cc b/components/optimization_guide/content/browser/page_content_proto_util.cc
index 532d335e..81e8090a 100644
--- a/components/optimization_guide/content/browser/page_content_proto_util.cc
+++ b/components/optimization_guide/content/browser/page_content_proto_util.cc
@@ -34,6 +34,11 @@
     case blink::mojom::AIPageContentAttributeType::kFigure:
       // TODO(khushalsagar): Add this type to the proto.
       return optimization_guide::proto::CONTENT_ATTRIBUTE_UNKNOWN;
+    case blink::mojom::AIPageContentAttributeType::kTable:
+      return optimization_guide::proto::CONTENT_ATTRIBUTE_TABLE;
+    case blink::mojom::AIPageContentAttributeType::kTableCell:
+      // TODO(abigailbklein): Add this type to the proto.
+      return optimization_guide::proto::CONTENT_ATTRIBUTE_UNKNOWN;
   }
 
   NOTREACHED();
diff --git a/components/optimization_guide/internal b/components/optimization_guide/internal
index a60bdae..fe7e9f2 160000
--- a/components/optimization_guide/internal
+++ b/components/optimization_guide/internal
@@ -1 +1 @@
-Subproject commit a60bdae9e30c3d6090711ab3d76e79fb3652fa0c
+Subproject commit fe7e9f241e165bb9fada55d320b6646e6ffa4a5f
diff --git a/components/os_crypt/async/browser/BUILD.gn b/components/os_crypt/async/browser/BUILD.gn
index 3aeae64..2c47265 100644
--- a/components/os_crypt/async/browser/BUILD.gn
+++ b/components/os_crypt/async/browser/BUILD.gn
@@ -27,7 +27,10 @@
     "test_utils.h",
   ]
   deps = [ "//crypto" ]
-  public_deps = [ ":browser" ]
+  public_deps = [
+    ":browser",
+    "//components/os_crypt/async/common:test_support",
+  ]
 }
 
 source_set("key_provider_interface") {
diff --git a/components/os_crypt/async/browser/os_crypt_async_unittest.cc b/components/os_crypt/async/browser/os_crypt_async_unittest.cc
index 1135ef8..3aba630 100644
--- a/components/os_crypt/async/browser/os_crypt_async_unittest.cc
+++ b/components/os_crypt/async/browser/os_crypt_async_unittest.cc
@@ -459,6 +459,24 @@
   EXPECT_EQ(*decrypted, "testsecrets");
 }
 
+TEST_F(OSCryptAsyncTest, TestEncryptorIsEncryptionAvailable) {
+  auto encryptor = GetTestEncryptorForTesting();
+
+  EXPECT_TRUE(encryptor.IsDecryptionAvailable());
+  encryptor.set_decryption_available_for_testing(false);
+  EXPECT_FALSE(encryptor.IsDecryptionAvailable());
+
+  encryptor.set_decryption_available_for_testing(std::nullopt);
+  EXPECT_TRUE(encryptor.IsDecryptionAvailable());
+
+  EXPECT_TRUE(encryptor.IsEncryptionAvailable());
+  encryptor.set_encryption_available_for_testing(false);
+  EXPECT_FALSE(encryptor.IsEncryptionAvailable());
+
+  encryptor.set_encryption_available_for_testing(std::nullopt);
+  EXPECT_TRUE(encryptor.IsEncryptionAvailable());
+}
+
 class FailingKeyProvider : public TestKeyProvider {
  private:
   void GetKey(KeyCallback callback) override {
diff --git a/components/os_crypt/async/browser/test_utils.cc b/components/os_crypt/async/browser/test_utils.cc
index af8e47f..7ee595e5 100644
--- a/components/os_crypt/async/browser/test_utils.cc
+++ b/components/os_crypt/async/browser/test_utils.cc
@@ -43,7 +43,7 @@
     return base::CallbackListSubscription();
   }
 
-  static Encryptor GetTestEncryptorForTesting() {
+  static TestEncryptor GetTestEncryptorForTesting() {
     Encryptor::KeyRing keys;
     keys.emplace(kDefaultTestKeyPrefix,
                  Encryptor::Key(crypto::RandBytesAsVector(
@@ -58,16 +58,16 @@
     // testing of key upgrade scenarios.
     key.is_os_crypt_sync_compatible_ = true;
     keys.emplace(kOsCryptSyncCompatibleTestKeyPrefix, std::move(key));
-    Encryptor encryptor(std::move(keys), kDefaultTestKeyPrefix);
+    TestEncryptor encryptor(std::move(keys), kDefaultTestKeyPrefix);
     return encryptor;
   }
 
-  static Encryptor CloneEncryptorForTesting(Encryptor::Option option) {
+  static TestEncryptor CloneEncryptorForTesting(Encryptor::Option option) {
     return GetTestEncryptorForTesting().Clone(option);
   }
 
  private:
-  Encryptor encryptor_;
+  TestEncryptor encryptor_;
   const bool is_sync_for_unittests_;
 };
 
@@ -76,7 +76,7 @@
   return std::make_unique<TestOSCryptAsync>(is_sync_for_unittests);
 }
 
-Encryptor GetTestEncryptorForTesting(Encryptor::Option option) {
+TestEncryptor GetTestEncryptorForTesting(Encryptor::Option option) {
   return TestOSCryptAsync::CloneEncryptorForTesting(option);
 }
 
diff --git a/components/os_crypt/async/browser/test_utils.h b/components/os_crypt/async/browser/test_utils.h
index ea4af281..4ff058e 100644
--- a/components/os_crypt/async/browser/test_utils.h
+++ b/components/os_crypt/async/browser/test_utils.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "components/os_crypt/async/browser/os_crypt_async.h"
+#include "components/os_crypt/async/common/test_encryptor.h"
 
 namespace os_crypt_async {
 
@@ -27,7 +28,7 @@
 // is called, and different from the ones vended from the test OSCryptAsync
 // above. An `option` can be specified in the same way as calling `GetInstance`
 // on `OSCryptAsync`.
-Encryptor GetTestEncryptorForTesting(
+TestEncryptor GetTestEncryptorForTesting(
     Encryptor::Option option = Encryptor::Option::kNone);
 
 }  // namespace os_crypt_async
diff --git a/components/os_crypt/async/common/BUILD.gn b/components/os_crypt/async/common/BUILD.gn
index 941b88c8..2d66dec 100644
--- a/components/os_crypt/async/common/BUILD.gn
+++ b/components/os_crypt/async/common/BUILD.gn
@@ -76,6 +76,23 @@
   defines = [ "IS_OS_CRYPT_ASYNC_IMPL" ]
 }
 
+source_set("test_support") {
+  testonly = true
+
+  # Access this class via browser/test_utils.h.
+  visibility = [ "//components/os_crypt/async/browser:test_support" ]
+
+  sources = [
+    "test_encryptor.cc",
+    "test_encryptor.h",
+  ]
+
+  deps = [
+    ":common",
+    "//base",
+  ]
+}
+
 # Mojo typemaps do not support adding a library dependency directly, so this
 # allows the dependency on crypt32.lib to be forwarded to both :common and
 # :common_mojom which might be in different modules in a component-build.
diff --git a/components/os_crypt/async/common/encryptor.h b/components/os_crypt/async/common/encryptor.h
index de2ad79..ffd939a1 100644
--- a/components/os_crypt/async/common/encryptor.h
+++ b/components/os_crypt/async/common/encryptor.h
@@ -116,7 +116,7 @@
   // Mojo uses this public constructor for serialization.
   explicit Encryptor(mojo::DefaultConstruct::Tag);
 
-  ~Encryptor();
+  virtual ~Encryptor();
 
   // Moveable, not copyable.
   Encryptor(Encryptor&& other);
@@ -153,19 +153,28 @@
   // Returns true if there is at least one key contained within the encryptor
   // that could be used for encryption, otherwise, it will return the value of
   // OSCrypt::IsEncryptionAvailable.
-  bool IsEncryptionAvailable() const;
+  virtual bool IsEncryptionAvailable() const;
 
   // Returns true if there is at least one key contained within the encryptor
   // that might be able to decrypt data, otherwise it will return the value of
   // OSCrypt::IsEncryptionAvailable. Note that if this function returns true
   // then there is no guarantee that arbitrary data can be decrypted, as the
   // correct key to decrypt the data might not be available.
-  bool IsDecryptionAvailable() const;
+  virtual bool IsDecryptionAvailable() const;
+
+ protected:
+  // Create an encryptor with a set of `keys`. The `provider_for_encryption`
+  // specifies which provider is used for encryption, and must have a
+  // corresponding key in `keys`.
+  Encryptor(KeyRing keys, const std::string& provider_for_encryption);
+
+  // Clone is used internally by the factory to vend instances.
+  Encryptor Clone(Option option) const;
 
  private:
-  friend class TestOSCryptAsync;
   friend class EncryptorTestBase;
   friend class OSCryptAsync;
+  friend class TestEncryptor;
   friend struct mojo::StructTraits<os_crypt_async::mojom::EncryptorDataView,
                                    os_crypt_async::Encryptor>;
 
@@ -176,14 +185,6 @@
   // encryption operations will be delegated to OSCrypt.
   Encryptor();
 
-  // Create an encryptor with a set of `keys`. The `provider_for_encryption`
-  // specifies which provider is used for encryption, and must have a
-  // corresponding key in `keys`.
-  Encryptor(KeyRing keys, const std::string& provider_for_encryption);
-
-  // Clone is used internally by the factory to vend instances.
-  Encryptor Clone(Option option) const;
-
   // A KeyRing consists of a set of provider names and Key values. Encrypted
   // data is always tagged with the provider name and this is used to look up
   // the correct key to use for decryption.
diff --git a/components/os_crypt/async/common/test_encryptor.cc b/components/os_crypt/async/common/test_encryptor.cc
new file mode 100644
index 0000000..ddf400d4
--- /dev/null
+++ b/components/os_crypt/async/common/test_encryptor.cc
@@ -0,0 +1,29 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/os_crypt/async/common/test_encryptor.h"
+
+#include "components/os_crypt/async/common/encryptor.h"
+
+namespace os_crypt_async {
+
+TestEncryptor::TestEncryptor(KeyRing keys,
+                             const std::string& provider_for_encryption)
+    : Encryptor(std::move(keys), provider_for_encryption) {}
+
+TestEncryptor TestEncryptor::Clone(Option option) const {
+  auto cloned = Encryptor::Clone(option);
+  return TestEncryptor(std::move(cloned.keys_),
+                       cloned.provider_for_encryption_);
+}
+
+bool TestEncryptor::IsEncryptionAvailable() const {
+  return is_encryption_available_.value_or(Encryptor::IsEncryptionAvailable());
+}
+
+bool TestEncryptor::IsDecryptionAvailable() const {
+  return is_decryption_available_.value_or(Encryptor::IsDecryptionAvailable());
+}
+
+}  // namespace os_crypt_async
diff --git a/components/os_crypt/async/common/test_encryptor.h b/components/os_crypt/async/common/test_encryptor.h
new file mode 100644
index 0000000..85d7dcdc
--- /dev/null
+++ b/components/os_crypt/async/common/test_encryptor.h
@@ -0,0 +1,50 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_OS_CRYPT_ASYNC_COMMON_TEST_ENCRYPTOR_H_
+#define COMPONENTS_OS_CRYPT_ASYNC_COMMON_TEST_ENCRYPTOR_H_
+
+#include <optional>
+
+#include "components/os_crypt/async/common/encryptor.h"
+
+namespace os_crypt_async {
+
+// An instance of this class can be obtained by calling
+// GetTestEncryptorForTesting. It can be used to provide control over whether or
+// not encryption services are available to higher level tests.
+class TestEncryptor : public Encryptor {
+ public:
+  TestEncryptor() = delete;
+
+  // Encryptor overrides.
+  bool IsEncryptionAvailable() const override;
+  bool IsDecryptionAvailable() const override;
+
+  // Override whether `IsEncryptionAvailable` returns true or false for the use
+  // of this Encryptor in the current process.
+  void set_encryption_available_for_testing(std::optional<bool> available) {
+    is_encryption_available_ = available;
+  }
+
+  // Override whether `IsDecryptionAvailable` returns true or false for the use
+  // of this Encryptor in the current process.
+  void set_decryption_available_for_testing(std::optional<bool> available) {
+    is_decryption_available_ = available;
+  }
+
+ private:
+  friend class TestOSCryptAsync;
+
+  TestEncryptor(KeyRing keys, const std::string& provider_for_encryption);
+
+  TestEncryptor Clone(Option option) const;
+
+  std::optional<bool> is_encryption_available_;
+  std::optional<bool> is_decryption_available_;
+};
+
+}  // namespace os_crypt_async
+
+#endif  // COMPONENTS_OS_CRYPT_ASYNC_COMMON_TEST_ENCRYPTOR_H_
diff --git a/components/page_info/core/merchant_trust_service.cc b/components/page_info/core/merchant_trust_service.cc
index 43a1dd86..43bbb80d 100644
--- a/components/page_info/core/merchant_trust_service.cc
+++ b/components/page_info/core/merchant_trust_service.cc
@@ -79,9 +79,11 @@
     // the proto.
     std::optional<commerce::MerchantTrustSignalsV2> merchant_trust_metadata =
         metadata.ParsedMetadata<commerce::MerchantTrustSignalsV2>();
-    std::move(callback).Run(url,
-                            GetMerchantDataFromProto(merchant_trust_metadata));
-    return;
+    if (merchant_trust_metadata.has_value()) {
+      std::move(callback).Run(
+          url, GetMerchantDataFromProto(merchant_trust_metadata));
+      return;
+    }
   }
 
   if (kMerchantTrustEnabledWithSampleData.Get()) {
diff --git a/components/password_manager/core/browser/features/password_features.cc b/components/password_manager/core/browser/features/password_features.cc
index d37391b2..efabf693 100644
--- a/components/password_manager/core/browser/features/password_features.cc
+++ b/components/password_manager/core/browser/features/password_features.cc
@@ -18,11 +18,10 @@
 BASE_FEATURE(kAutofillPasswordUserPerceptionSurvey,
              "AutofillPasswordUserPerceptionSurvey",
              base::FEATURE_DISABLED_BY_DEFAULT);
-// Default enabled in M131. Remove in or after M134 and after
-// PasswordManualFallbackAvailable feature is cleaned up.
+// Disabled by default.
 BASE_FEATURE(kWebAuthnUsePasskeyFromAnotherDeviceInContextMenu,
              "WebAuthnUsePasskeyFromAnotherDeviceInContextMenu",
-             base::FEATURE_ENABLED_BY_DEFAULT);
+             base::FEATURE_DISABLED_BY_DEFAULT);
 #endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
 
 BASE_FEATURE(kBiometricTouchToFill,
diff --git a/components/password_manager/core/browser/features/password_features.h b/components/password_manager/core/browser/features/password_features.h
index b733e1cd..da920ff8 100644
--- a/components/password_manager/core/browser/features/password_features.h
+++ b/components/password_manager/core/browser/features/password_features.h
@@ -30,7 +30,8 @@
 // across quarters.
 BASE_DECLARE_FEATURE(kAutofillPasswordUserPerceptionSurvey);
 // Moves the "Use a passkey / Use a different passkey" to the context menu from
-// the autofill dropdown.
+// the autofill dropdown. This is now decoupled from
+// "PasswordManualFallbackAvailable" flag.
 BASE_DECLARE_FEATURE(kWebAuthnUsePasskeyFromAnotherDeviceInContextMenu);
 #endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
 
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc
index 1f050eb..6519572e 100644
--- a/components/password_manager/core/browser/password_form_manager.cc
+++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -953,12 +953,8 @@
     WebAuthnCredentialsDelegate* delegate =
         client_->GetWebAuthnCredentialsDelegateForDriver(driver_.get());
 #if !BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_ANDROID)
-    const bool passkey_from_another_device_in_context_menu =
-        (base::FeatureList::IsEnabled(
-             features::kPasswordManualFallbackAvailable) &&
-         base::FeatureList::IsEnabled(
-             features::kWebAuthnUsePasskeyFromAnotherDeviceInContextMenu));
-    if (passkey_from_another_device_in_context_menu) {
+    if (base::FeatureList::IsEnabled(
+            features::kWebAuthnUsePasskeyFromAnotherDeviceInContextMenu)) {
       return delegate && delegate->GetPasskeys().has_value() &&
              !delegate->GetPasskeys()->empty();
     }
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc
index 6673128..ecfe3c2b 100644
--- a/components/password_manager/core/browser/password_form_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -5378,6 +5378,12 @@
 
 class PasswordFormManagerWebAuthnCredentialsTest : public testing::Test {
  protected:
+  PasswordFormManagerWebAuthnCredentialsTest() {
+#if !BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_ANDROID)
+    features_.InitAndDisableFeature(
+        features::kWebAuthnUsePasskeyFromAnotherDeviceInContextMenu);
+#endif  //! BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_ANDROID)
+  }
   void SetUp() override {
     PasswordFormManager::set_wait_for_server_predictions_for_filling(false);
 #if BUILDFLAG(IS_ANDROID)
@@ -5407,6 +5413,7 @@
   PasswordFormManager& form_manager() { return *form_manager_.get(); }
 
  private:
+  base::test::ScopedFeatureList features_;
   MockPasswordManagerClient client_;
   MockPasswordManagerDriver driver_;
   MockWebAuthnCredentialsDelegate webauthn_credentials_delegate_;
@@ -5443,11 +5450,8 @@
 TEST_F(
     PasswordFormManagerWebAuthnCredentialsTest,
     NoPasskeysFromConditionalRequest_WhenUseAnotherDeviceInContextMenu_ThenNoWebauthnCredentials) {
-  base::test::ScopedFeatureList features;
-  features.InitWithFeatures(
-      {features::kWebAuthnUsePasskeyFromAnotherDeviceInContextMenu,
-       features::kPasswordManualFallbackAvailable},
-      {});
+  base::test::ScopedFeatureList features(
+      features::kWebAuthnUsePasskeyFromAnotherDeviceInContextMenu);
   ON_CALL(webauthn_credentials_delegate(), GetPasskeys)
       .WillByDefault(ReturnRef(kNoPasskeys));
 
@@ -5457,10 +5461,6 @@
 TEST_F(
     PasswordFormManagerWebAuthnCredentialsTest,
     NoPasskeysFromConditionalRequest_WhenUseAnotherDeviceInAutofillPopup_ThenWebauthnCredentials) {
-  base::test::ScopedFeatureList features;
-  features.InitWithFeatures(
-      {features::kPasswordManualFallbackAvailable},
-      {features::kWebAuthnUsePasskeyFromAnotherDeviceInContextMenu});
   ON_CALL(webauthn_credentials_delegate(), GetPasskeys)
       .WillByDefault(ReturnRef(kNoPasskeys));
 
diff --git a/components/password_manager/core/browser/password_manager_util_unittest.cc b/components/password_manager/core/browser/password_manager_util_unittest.cc
index f303356..8b6858c 100644
--- a/components/password_manager/core/browser/password_manager_util_unittest.cc
+++ b/components/password_manager/core/browser/password_manager_util_unittest.cc
@@ -676,17 +676,17 @@
       autofill::AutofillClient::PopupOpenArgs(), /*delegate=*/nullptr);
   test_autofill_client.ShowAutofillFieldIphForFeature(
       autofill::FormFieldData(),
-      autofill::AutofillClient::IphFeature::kManualFallback);
+      autofill::AutofillClient::IphFeature::kPredictionImprovements);
 
   ASSERT_TRUE(test_autofill_client.IsShowingAutofillPopup());
-  ASSERT_TRUE(test_autofill_client.IsShowingManualFallbackIph());
+  ASSERT_TRUE(test_autofill_client.IsShowingPredictionImprovementsIph());
 
   UserTriggeredManualGenerationFromContextMenu(&stub_password_client,
                                                &test_autofill_client);
   EXPECT_EQ(test_autofill_client.popup_hiding_reason(),
             autofill::SuggestionHidingReason::
                 kOverlappingWithPasswordGenerationPopup);
-  EXPECT_FALSE(test_autofill_client.IsShowingManualFallbackIph());
+  EXPECT_FALSE(test_autofill_client.IsShowingPredictionImprovementsIph());
 }
 
 TEST(PasswordManagerUtil, StripAuthAndParams) {
diff --git a/components/password_manager/core/browser/password_save_manager_impl.cc b/components/password_manager/core/browser/password_save_manager_impl.cc
index 5770df4..817b70c 100644
--- a/components/password_manager/core/browser/password_save_manager_impl.cc
+++ b/components/password_manager/core/browser/password_save_manager_impl.cc
@@ -17,7 +17,7 @@
 #include "base/ranges/algorithm.h"
 #include "base/strings/string_number_conversions.h"
 #include "build/build_config.h"
-#include "components/autofill/core/browser/validation.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/common/credit_card_number_validation.h"
 #include "components/autofill/core/common/signatures.h"
 #include "components/password_manager/core/browser/form_fetcher.h"
diff --git a/components/password_manager/core/browser/password_suggestion_generator.cc b/components/password_manager/core/browser/password_suggestion_generator.cc
index 949de29d..d9d4453 100644
--- a/components/password_manager/core/browser/password_suggestion_generator.cc
+++ b/components/password_manager/core/browser/password_suggestion_generator.cc
@@ -354,9 +354,7 @@
 #if !BUILDFLAG(IS_IOS)
     const bool passkey_from_another_device_in_autofill =
         !(base::FeatureList::IsEnabled(
-              features::kPasswordManualFallbackAvailable) &&
-          base::FeatureList::IsEnabled(
-              features::kWebAuthnUsePasskeyFromAnotherDeviceInContextMenu));
+            features::kWebAuthnUsePasskeyFromAnotherDeviceInContextMenu));
 #else
     const bool passkey_from_another_device_in_autofill = true;
 #endif  //! BUILDFLAG(IS_IOS)
diff --git a/components/password_manager/ios/ios_password_manager_driver.h b/components/password_manager/ios/ios_password_manager_driver.h
index ec82844..726acef 100644
--- a/components/password_manager/ios/ios_password_manager_driver.h
+++ b/components/password_manager/ios/ios_password_manager_driver.h
@@ -9,12 +9,13 @@
 
 #import "base/memory/raw_ptr.h"
 #import "base/memory/weak_ptr.h"
-#include "components/autofill/core/common/aliases.h"
+#import "components/autofill/core/common/aliases.h"
 #import "components/autofill/core/common/field_data_manager.h"
 #import "components/password_manager/core/browser/password_generation_frame_helper.h"
 #import "components/password_manager/core/browser/password_manager_driver.h"
 #import "components/password_manager/ios/password_manager_driver_bridge.h"
 #import "url/gurl.h"
+#import "url/origin.h"
 
 namespace autofill {
 struct PasswordFormFillData;
@@ -79,7 +80,7 @@
   const GURL& GetLastCommittedURL() const override;
   base::WeakPtr<PasswordManagerDriver> AsWeakPtr() override;
   const std::string& web_frame_id() const { return frame_id_; }
-  const GURL& security_origin() const { return security_origin_; }
+  const url::Origin& security_origin() const { return security_origin_; }
   autofill::FieldDataManager& field_data_manager() {
     return *field_data_manager_;
   }
@@ -129,7 +130,7 @@
 
   bool is_in_main_frame_;
   // The security origin associated with |web_frame_|.
-  GURL security_origin_;
+  url::Origin security_origin_;
 
   // True when the conditions are met to display the proactive password
   // generation bottom sheet, the sheet that is automatically triggered when you
diff --git a/components/password_manager/ios/ios_password_manager_driver.mm b/components/password_manager/ios/ios_password_manager_driver.mm
index 9b4a487..c9ff1ad 100644
--- a/components/password_manager/ios/ios_password_manager_driver.mm
+++ b/components/password_manager/ios/ios_password_manager_driver.mm
@@ -42,7 +42,7 @@
 
   // Cache these values early, so that it can be accessed after frame deletion.
   is_in_main_frame_ = web_frame->IsMainFrame();
-  security_origin_ = web_frame->GetSecurityOriginDeprecated();
+  security_origin_ = web_frame->GetSecurityOrigin();
 }
 
 IOSPasswordManagerDriver::~IOSPasswordManagerDriver() = default;
diff --git a/components/password_manager/ios/password_form_helper.mm b/components/password_manager/ios/password_form_helper.mm
index 77a35dbb..ed575cd 100644
--- a/components/password_manager/ios/password_form_helper.mm
+++ b/components/password_manager/ios/password_form_helper.mm
@@ -132,8 +132,7 @@
                           inFrame:(web::WebFrame*)frame {
   DCHECK_EQ(_webState, webState);
   GURL pageURL = webState->GetLastCommittedURL();
-  if (pageURL.DeprecatedGetOriginAsURL() !=
-      frame->GetSecurityOriginDeprecated()) {
+  if (!frame->GetSecurityOrigin().IsSameOriginWith(pageURL)) {
     // Passwords is only supported on main frame and iframes with the same
     // origin.
     return;
@@ -154,10 +153,9 @@
   autofill::FieldDataManager* fieldDataManager =
       autofill::FieldDataManagerFactoryIOS::FromWebFrame(frame);
 
-  std::optional<std::vector<FormData>> formsData =
-      autofill::ExtractFormsData(JSONString, false, std::u16string(), pageURL,
-                                 frame->GetSecurityOriginDeprecated(),
-                                 *fieldDataManager, frame->GetFrameId());
+  std::optional<std::vector<FormData>> formsData = autofill::ExtractFormsData(
+      JSONString, false, std::u16string(), pageURL, frame->GetSecurityOrigin(),
+      *fieldDataManager, frame->GetFrameId());
   if (!formsData) {
     return;
   }
@@ -343,6 +341,8 @@
     return;
   }
 
+  url::Origin frame_origin = frame->GetSecurityOrigin();
+
   const scoped_refptr<autofill::FieldDataManager> fieldDataManager =
       autofill::FieldDataManagerFactoryIOS::GetRetainable(frame);
 
@@ -350,8 +350,9 @@
   password_manager::PasswordManagerJavaScriptFeature::GetInstance()
       ->ExtractForm(
           frame, formIdentifier, base::BindOnce(^(NSString* jsonString) {
-            if (std::optional<FormData> formData = JsonStringToFormData(
-                    jsonString, *pageURL, *fieldDataManager, frame_id)) {
+            if (std::optional<FormData> formData =
+                    JsonStringToFormData(jsonString, *pageURL, frame_origin,
+                                         *fieldDataManager, frame_id)) {
               completionHandler(YES, *formData);
               return;
             }
@@ -410,10 +411,9 @@
   autofill::FieldDataManager* fieldDataManager =
       autofill::FieldDataManagerFactoryIOS::FromWebFrame(frame);
 
-  if (std::optional<FormData> form =
-          autofill::ExtractFormData(dict, false, std::u16string(), *pageURL,
-                                    pageURL->DeprecatedGetOriginAsURL(),
-                                    *fieldDataManager, *host_frame)) {
+  if (std::optional<FormData> form = autofill::ExtractFormData(
+          dict, false, std::u16string(), *pageURL,
+          url::Origin::Create(*pageURL), *fieldDataManager, *host_frame)) {
     [self.delegate formHelper:self didSubmitForm:*form inFrame:frame];
 
     return HandleSubmittedFormStatus::kHandled;
diff --git a/components/password_manager/ios/password_manager_driver_bridge.h b/components/password_manager/ios/password_manager_driver_bridge.h
index 9491777..4227c3c 100644
--- a/components/password_manager/ios/password_manager_driver_bridge.h
+++ b/components/password_manager/ios/password_manager_driver_bridge.h
@@ -25,7 +25,7 @@
             (const autofill::PasswordFormFillData&)formData
                          forFrameId:(const std::string&)frameId
                         isMainFrame:(BOOL)isMainFrame
-                  forSecurityOrigin:(const GURL&)origin;
+                  forSecurityOrigin:(const url::Origin&)origin;
 
 // Informs delegate that there are no saved credentials for the current page.
 // The frame is used to get the AccountSelectFillData and reset the credentials
diff --git a/components/password_manager/ios/password_manager_ios_util.h b/components/password_manager/ios/password_manager_ios_util.h
index b9a8493..1ff4c92 100644
--- a/components/password_manager/ios/password_manager_ios_util.h
+++ b/components/password_manager/ios/password_manager_ios_util.h
@@ -9,7 +9,8 @@
 
 #import <optional>
 
-#include "url/gurl.h"
+#import "url/gurl.h"
+#import "url/origin.h"
 
 namespace web {
 class WebState;
@@ -30,17 +31,14 @@
 std::optional<autofill::FormData> JsonStringToFormData(
     NSString* json_string,
     const GURL& page_url,
+    const url::Origin& frame_origin,
     const autofill::FieldDataManager& field_data_manager,
     const std::string& frame_id);
 
-// Whether the |origin| matches the last committed URl in the |web_state|.
-bool OriginMatchesLastCommittedURLOrigin(web::WebState* web_state,
-                                         const GURL& origin);
-
 // Returns whether an iframe is cross-origin.
 bool IsCrossOriginIframe(web::WebState* web_state,
                          bool frame_is_main_frame,
-                         const GURL& frame_security_origin);
+                         const url::Origin& frame_security_origin);
 
 }  // namespace password_manager
 
diff --git a/components/password_manager/ios/password_manager_ios_util.mm b/components/password_manager/ios/password_manager_ios_util.mm
index 24e8991..bd8de7f 100644
--- a/components/password_manager/ios/password_manager_ios_util.mm
+++ b/components/password_manager/ios/password_manager_ios_util.mm
@@ -45,6 +45,7 @@
 std::optional<autofill::FormData> JsonStringToFormData(
     NSString* json_string,
     const GURL& page_url,
+    const url::Origin& frame_origin,
     const autofill::FieldDataManager& field_data_manager,
     const std::string& frame_id) {
   std::unique_ptr<base::Value> formValue = autofill::ParseJson(json_string);
@@ -58,13 +59,12 @@
   }
 
   return autofill::ExtractFormData(*dict, false, std::u16string(), page_url,
-                                   page_url.DeprecatedGetOriginAsURL(),
-                                   field_data_manager, frame_id);
+                                   frame_origin, field_data_manager, frame_id);
 }
 
 bool IsCrossOriginIframe(web::WebState* web_state,
                          bool frame_is_main_frame,
-                         const GURL& frame_security_origin) {
+                         const url::Origin& frame_security_origin) {
   return !frame_is_main_frame &&
          !url::Origin::Create(web_state->GetLastCommittedURL())
               .IsSameOriginWith(frame_security_origin);
diff --git a/components/password_manager/ios/password_suggestion_helper.h b/components/password_manager/ios/password_suggestion_helper.h
index 1ff9320e..0445c8c3 100644
--- a/components/password_manager/ios/password_suggestion_helper.h
+++ b/components/password_manager/ios/password_suggestion_helper.h
@@ -6,11 +6,12 @@
 #define COMPONENTS_PASSWORD_MANAGER_IOS_PASSWORD_SUGGESTION_HELPER_H_
 
 #import <Foundation/Foundation.h>
-#include <memory>
 
-#include "components/autofill/core/common/unique_ids.h"
+#import <memory>
+
+#import "components/autofill/core/common/unique_ids.h"
 #import "components/autofill/ios/browser/form_suggestion_provider.h"
-#include "url/gurl.h"
+#import "url/origin.h"
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -102,7 +103,7 @@
             (const autofill::PasswordFormFillData&)formData
                              forFrameId:(const std::string&)frameId
                             isMainFrame:(BOOL)isMainFrame
-                      forSecurityOrigin:(const GURL&)origin;
+                      forSecurityOrigin:(const url::Origin&)origin;
 
 // Processes the case in which no saved credentials are available when
 // extracting forms in the renderer. Will complete the pending check query
diff --git a/components/password_manager/ios/password_suggestion_helper.mm b/components/password_manager/ios/password_suggestion_helper.mm
index 45a109f..ae4ccbd 100644
--- a/components/password_manager/ios/password_suggestion_helper.mm
+++ b/components/password_manager/ios/password_suggestion_helper.mm
@@ -312,7 +312,7 @@
 - (void)processWithPasswordFormFillData:(const PasswordFormFillData&)formData
                              forFrameId:(const std::string&)frameId
                             isMainFrame:(BOOL)isMainFrame
-                      forSecurityOrigin:(const GURL&)origin {
+                      forSecurityOrigin:(const url::Origin&)origin {
   DCHECK(_webState.get());
   [self fillDataForFrameId:frameId]->Add(
       formData, [self shouldAlwaysPopulateRealmForFrame:frameId
@@ -402,7 +402,7 @@
 // is not specified.
 - (bool)shouldAlwaysPopulateRealmForFrame:(const std::string&)frameId
                               isMainFrame:(BOOL)isMainFrame
-                        forSecurityOrigin:(const GURL&)origin {
+                        forSecurityOrigin:(const url::Origin&)origin {
   CHECK(_webState.get());
   if (IsCrossOriginIframe(_webState.get(), isMainFrame, origin)) {
     return true;
diff --git a/components/password_manager/ios/password_suggestion_helper_unittest.mm b/components/password_manager/ios/password_suggestion_helper_unittest.mm
index e6f3713..28ee020 100644
--- a/components/password_manager/ios/password_suggestion_helper_unittest.mm
+++ b/components/password_manager/ios/password_suggestion_helper_unittest.mm
@@ -157,8 +157,7 @@
   [helper_ processWithPasswordFormFillData:form_fill_data
                                 forFrameId:main_frame_->GetFrameId()
                                isMainFrame:main_frame_->IsMainFrame()
-                         forSecurityOrigin:main_frame_
-                                               ->GetSecurityOriginDeprecated()];
+                         forSecurityOrigin:main_frame_->GetSecurityOrigin()];
 
   __block BOOL retrieved_suggestions = NO;
   __block BOOL completion_called = NO;
@@ -196,8 +195,7 @@
   [helper_ processWithPasswordFormFillData:form_fill_data
                                 forFrameId:main_frame_->GetFrameId()
                                isMainFrame:main_frame_->IsMainFrame()
-                         forSecurityOrigin:main_frame_
-                                               ->GetSecurityOriginDeprecated()];
+                         forSecurityOrigin:main_frame_->GetSecurityOrigin()];
 
   __block BOOL retrieved_suggestions = NO;
   __block BOOL completion_called = NO;
@@ -294,8 +292,7 @@
   [helper_ processWithPasswordFormFillData:form_fill_data
                                 forFrameId:main_frame_->GetFrameId()
                                isMainFrame:main_frame_->IsMainFrame()
-                         forSecurityOrigin:main_frame_
-                                               ->GetSecurityOriginDeprecated()];
+                         forSecurityOrigin:main_frame_->GetSecurityOrigin()];
 
   // Now the completion should be called since the triggered forms extraction
   // was done.
@@ -375,8 +372,7 @@
   [helper_ processWithPasswordFormFillData:form_fill_data
                                 forFrameId:main_frame_->GetFrameId()
                                isMainFrame:main_frame_->IsMainFrame()
-                         forSecurityOrigin:main_frame_
-                                               ->GetSecurityOriginDeprecated()];
+                         forSecurityOrigin:main_frame_->GetSecurityOrigin()];
 
   // Now the queued completion blocks should be called since the triggered forms
   // extraction was done.
@@ -491,12 +487,10 @@
   {
     PasswordFormFillData form_fill_data = CreatePasswordFillData(
         form1_renderer_id, username1_renderer_id, password1_renderer_id);
-    [helper_
-        processWithPasswordFormFillData:form_fill_data
-                             forFrameId:main_frame_->GetFrameId()
-                            isMainFrame:main_frame_->IsMainFrame()
-                      forSecurityOrigin:main_frame_
-                                            ->GetSecurityOriginDeprecated()];
+    [helper_ processWithPasswordFormFillData:form_fill_data
+                                  forFrameId:main_frame_->GetFrameId()
+                                 isMainFrame:main_frame_->IsMainFrame()
+                           forSecurityOrigin:main_frame_->GetSecurityOrigin()];
   }
   // Queries for the forms in main frame should be completed after processing
   // the fill data for that frame.
@@ -511,12 +505,10 @@
   {
     PasswordFormFillData form_fill_data = CreatePasswordFillData(
         form1_renderer_id, username1_renderer_id, password1_renderer_id);
-    [helper_
-        processWithPasswordFormFillData:form_fill_data
-                             forFrameId:frame1_ptr->GetFrameId()
-                            isMainFrame:frame1_ptr->IsMainFrame()
-                      forSecurityOrigin:frame1_ptr
-                                            ->GetSecurityOriginDeprecated()];
+    [helper_ processWithPasswordFormFillData:form_fill_data
+                                  forFrameId:frame1_ptr->GetFrameId()
+                                 isMainFrame:frame1_ptr->IsMainFrame()
+                           forSecurityOrigin:main_frame_->GetSecurityOrigin()];
   }
   // Queries for the forms in first subframe should be completed after
   // processing the fill data for that frame.
@@ -529,12 +521,10 @@
   {
     PasswordFormFillData form_fill_data = CreatePasswordFillData(
         form1_renderer_id, username1_renderer_id, password1_renderer_id);
-    [helper_
-        processWithPasswordFormFillData:form_fill_data
-                             forFrameId:frame2_ptr->GetFrameId()
-                            isMainFrame:frame2_ptr->IsMainFrame()
-                      forSecurityOrigin:frame2_ptr
-                                            ->GetSecurityOriginDeprecated()];
+    [helper_ processWithPasswordFormFillData:form_fill_data
+                                  forFrameId:frame2_ptr->GetFrameId()
+                                 isMainFrame:frame2_ptr->IsMainFrame()
+                           forSecurityOrigin:main_frame_->GetSecurityOrigin()];
   }
   // Queries for the forms in second subframe should be completed after
   // processing the fill data for that frame.
@@ -606,12 +596,10 @@
   {
     PasswordFormFillData form_fill_data = CreatePasswordFillData(
         form_renderer_id, username_renderer_id, password_renderer_id);
-    [helper_
-        processWithPasswordFormFillData:form_fill_data
-                             forFrameId:main_frame_->GetFrameId()
-                            isMainFrame:main_frame_->IsMainFrame()
-                      forSecurityOrigin:main_frame_
-                                            ->GetSecurityOriginDeprecated()];
+    [helper_ processWithPasswordFormFillData:form_fill_data
+                                  forFrameId:main_frame_->GetFrameId()
+                                 isMainFrame:main_frame_->IsMainFrame()
+                           forSecurityOrigin:main_frame_->GetSecurityOrigin()];
   }
   // Process the fill data a second time to verify that all the queries for
   // the main frame were popped out of the queue in which case the query
@@ -619,12 +607,10 @@
   {
     PasswordFormFillData form_fill_data = CreatePasswordFillData(
         form_renderer_id, username_renderer_id, password_renderer_id);
-    [helper_
-        processWithPasswordFormFillData:form_fill_data
-                             forFrameId:main_frame_->GetFrameId()
-                            isMainFrame:main_frame_->IsMainFrame()
-                      forSecurityOrigin:main_frame_
-                                            ->GetSecurityOriginDeprecated()];
+    [helper_ processWithPasswordFormFillData:form_fill_data
+                                  forFrameId:main_frame_->GetFrameId()
+                                 isMainFrame:main_frame_->IsMainFrame()
+                           forSecurityOrigin:main_frame_->GetSecurityOrigin()];
   }
 
   // Process fill data for the first subframe.
@@ -634,12 +620,10 @@
   {
     PasswordFormFillData form_fill_data = CreatePasswordFillData(
         form_renderer_id, username_renderer_id, password_renderer_id);
-    [helper_
-        processWithPasswordFormFillData:form_fill_data
-                             forFrameId:frame1_ptr->GetFrameId()
-                            isMainFrame:frame1_ptr->IsMainFrame()
-                      forSecurityOrigin:frame1_ptr
-                                            ->GetSecurityOriginDeprecated()];
+    [helper_ processWithPasswordFormFillData:form_fill_data
+                                  forFrameId:frame1_ptr->GetFrameId()
+                                 isMainFrame:frame1_ptr->IsMainFrame()
+                           forSecurityOrigin:main_frame_->GetSecurityOrigin()];
   }
   // Process the fill data a second time to verify that all the queries for
   // the first subframe were popped out of the queue in which case the query
@@ -647,12 +631,10 @@
   {
     PasswordFormFillData form_fill_data = CreatePasswordFillData(
         form_renderer_id, username_renderer_id, password_renderer_id);
-    [helper_
-        processWithPasswordFormFillData:form_fill_data
-                             forFrameId:frame1_ptr->GetFrameId()
-                            isMainFrame:frame1_ptr->IsMainFrame()
-                      forSecurityOrigin:frame1_ptr
-                                            ->GetSecurityOriginDeprecated()];
+    [helper_ processWithPasswordFormFillData:form_fill_data
+                                  forFrameId:frame1_ptr->GetFrameId()
+                                 isMainFrame:frame1_ptr->IsMainFrame()
+                           forSecurityOrigin:main_frame_->GetSecurityOrigin()];
   }
 
   // Process fill data  for the second subframe.
@@ -662,12 +644,10 @@
   {
     PasswordFormFillData form_fill_data = CreatePasswordFillData(
         form_renderer_id, username_renderer_id, password_renderer_id);
-    [helper_
-        processWithPasswordFormFillData:form_fill_data
-                             forFrameId:frame2_ptr->GetFrameId()
-                            isMainFrame:frame2_ptr->IsMainFrame()
-                      forSecurityOrigin:frame2_ptr
-                                            ->GetSecurityOriginDeprecated()];
+    [helper_ processWithPasswordFormFillData:form_fill_data
+                                  forFrameId:frame2_ptr->GetFrameId()
+                                 isMainFrame:frame2_ptr->IsMainFrame()
+                           forSecurityOrigin:main_frame_->GetSecurityOrigin()];
   }
   // Process the fill data a second time to verify that all the queries for
   // the second subframe were popped out of the queue in which case the query
@@ -675,12 +655,10 @@
   {
     PasswordFormFillData form_fill_data = CreatePasswordFillData(
         form_renderer_id, username_renderer_id, password_renderer_id);
-    [helper_
-        processWithPasswordFormFillData:form_fill_data
-                             forFrameId:frame2_ptr->GetFrameId()
-                            isMainFrame:frame2_ptr->IsMainFrame()
-                      forSecurityOrigin:frame2_ptr
-                                            ->GetSecurityOriginDeprecated()];
+    [helper_ processWithPasswordFormFillData:form_fill_data
+                                  forFrameId:frame2_ptr->GetFrameId()
+                                 isMainFrame:frame2_ptr->IsMainFrame()
+                           forSecurityOrigin:main_frame_->GetSecurityOrigin()];
   }
 
   // Reaching this line means the no CHECK were triggered and that the queued
@@ -700,8 +678,7 @@
   [helper_ processWithPasswordFormFillData:form_fill_data
                                 forFrameId:main_frame_->GetFrameId()
                                isMainFrame:main_frame_->IsMainFrame()
-                         forSecurityOrigin:main_frame_
-                                               ->GetSecurityOriginDeprecated()];
+                         forSecurityOrigin:main_frame_->GetSecurityOrigin()];
 
   NSArray<FormSuggestion*>* suggestions =
       [helper_ retrieveSuggestionsWithForm:query];
@@ -727,8 +704,7 @@
   [helper_ processWithPasswordFormFillData:form_fill_data
                                 forFrameId:main_frame_->GetFrameId()
                                isMainFrame:main_frame_->IsMainFrame()
-                         forSecurityOrigin:main_frame_
-                                               ->GetSecurityOriginDeprecated()];
+                         forSecurityOrigin:main_frame_->GetSecurityOrigin()];
 
   NSArray<FormSuggestion*>* suggestions =
       [helper_ retrieveSuggestionsWithForm:query];
@@ -755,8 +731,7 @@
   [helper_ processWithPasswordFormFillData:form_fill_data
                                 forFrameId:main_frame_->GetFrameId()
                                isMainFrame:main_frame_->IsMainFrame()
-                         forSecurityOrigin:main_frame_
-                                               ->GetSecurityOriginDeprecated()];
+                         forSecurityOrigin:main_frame_->GetSecurityOrigin()];
 
   NSArray<FormSuggestion*>* suggestions =
       [helper_ retrieveSuggestionsWithForm:query];
@@ -786,8 +761,7 @@
   [helper_ processWithPasswordFormFillData:form_fill_data
                                 forFrameId:main_frame_->GetFrameId()
                                isMainFrame:main_frame_->IsMainFrame()
-                         forSecurityOrigin:main_frame_
-                                               ->GetSecurityOriginDeprecated()];
+                         forSecurityOrigin:main_frame_->GetSecurityOrigin()];
 
   // Try to get suggestions for form1 which doesn't have fill data.
   NSArray<FormSuggestion*>* suggestions =
@@ -809,8 +783,7 @@
   [helper_ processWithPasswordFormFillData:form_fill_data
                                 forFrameId:main_frame_->GetFrameId()
                                isMainFrame:main_frame_->IsMainFrame()
-                         forSecurityOrigin:main_frame_
-                                               ->GetSecurityOriginDeprecated()];
+                         forSecurityOrigin:main_frame_->GetSecurityOrigin()];
 
   // Get suggestions first before getting the fill data for the selected
   // suggestion because this is a mandatory step.
@@ -865,8 +838,7 @@
   [helper_ processWithPasswordFormFillData:form_fill_data
                                 forFrameId:main_frame_->GetFrameId()
                                isMainFrame:main_frame_->IsMainFrame()
-                         forSecurityOrigin:main_frame_
-                                               ->GetSecurityOriginDeprecated()];
+                         forSecurityOrigin:main_frame_->GetSecurityOrigin()];
 
   {
     // Get suggestions and fill data for main frame when there is still fill
diff --git a/components/password_manager/ios/shared_password_controller.mm b/components/password_manager/ios/shared_password_controller.mm
index bf511f9..9a31465 100644
--- a/components/password_manager/ios/shared_password_controller.mm
+++ b/components/password_manager/ios/shared_password_controller.mm
@@ -87,7 +87,6 @@
 using l10n_util::GetNSStringF;
 using password_manager::AccountSelectFillData;
 using password_manager::FillData;
-using password_manager::JsonStringToFormData;
 using password_manager::PasswordFormManagerForUI;
 using password_manager::PasswordGenerationFrameHelper;
 using password_manager::PasswordManagerClient;
@@ -756,7 +755,7 @@
             (const autofill::PasswordFormFillData&)formData
                          forFrameId:(const std::string&)frameId
                         isMainFrame:(BOOL)isMainFrame
-                  forSecurityOrigin:(const GURL&)origin {
+                  forSecurityOrigin:(const url::Origin&)origin {
   // Biometric auth is always enabled on iOS so wait_for_username is
   // specifically set to prevent filling without user confirmation.
   DCHECK(formData.wait_for_username);
diff --git a/components/password_manager/ios/shared_password_controller_unittest.mm b/components/password_manager/ios/shared_password_controller_unittest.mm
index 24c5432..82aac2e 100644
--- a/components/password_manager/ios/shared_password_controller_unittest.mm
+++ b/components/password_manager/ios/shared_password_controller_unittest.mm
@@ -99,10 +99,11 @@
 // form.
 FormData CreateFormDataForRenderFrameHost(
     web::WebFrame* frame,
+    const GURL& url,
     LocalFrameToken host_frame_token,
     std::vector<autofill::FormFieldData> fields) {
   FormData form;
-  form.set_url(frame->GetSecurityOriginDeprecated());
+  form.set_url(url);
   form.set_action(form.url());
   form.set_host_frame(host_frame_token);
   form.set_renderer_id(autofill::test::MakeFormRendererId());
@@ -311,20 +312,22 @@
   const LocalFrameToken child_frame_local_token(MakeLocalFrameToken());
   const RemoteFrameToken child_frame_remote_token(MakeRemoteFrameToken());
 
+  GURL url(kTestURL);
+
   auto main_frame =
       web::FakeWebFrame::Create(main_frame_local_frame_token.ToString(),
-                                /*is_main_frame=*/true, GURL(kTestURL));
+                                /*is_main_frame=*/true, url);
   web::WebFrame* main_frame_ptr = main_frame.get();
   AddWebFrame(std::move(main_frame));
 
   auto child_frame =
       web::FakeWebFrame::Create(child_frame_local_token.ToString(),
-                                /*is_main_frame=*/true, GURL(kTestURL));
+                                /*is_main_frame=*/true, url);
   web::WebFrame* child_frame_ptr = child_frame.get();
   AddWebFrame(std::move(child_frame));
 
   FormData main_form = CreateFormDataForRenderFrameHost(
-      main_frame_ptr, main_frame_local_frame_token,
+      main_frame_ptr, url, main_frame_local_frame_token,
       {CreateTestFormField("Search", "search", "",
                            autofill::FormControlType::kInputText)});
   {
@@ -335,7 +338,7 @@
   }
 
   FormData child_form = CreateFormDataForRenderFrameHost(
-      child_frame_ptr, child_frame_local_token,
+      child_frame_ptr, url, child_frame_local_token,
       {CreateTestFormField("Username", "username", "",
                            autofill::FormControlType::kInputText),
        CreateTestFormField("Password", "password", "",
@@ -1340,11 +1343,10 @@
       form.fields()[1].renderer_id().value(), "super!secret", nullptr, nullptr,
       &form_fill_data);
 
-  [controller_
-      processPasswordFormFillData:form_fill_data
-                       forFrameId:web_frame_id
-                      isMainFrame:frame->IsMainFrame()
-                forSecurityOrigin:frame->GetSecurityOriginDeprecated()];
+  [controller_ processPasswordFormFillData:form_fill_data
+                                forFrameId:web_frame_id
+                               isMainFrame:frame->IsMainFrame()
+                         forSecurityOrigin:frame->GetSecurityOrigin()];
 
   // Check that completion handler was called.
   EXPECT_TRUE(completion_was_called);
@@ -1439,11 +1441,10 @@
       form.fields()[1].renderer_id().value(), "super!secret", nullptr, nullptr,
       &form_fill_data);
 
-  [controller_
-      processPasswordFormFillData:form_fill_data
-                       forFrameId:web_frame_id
-                      isMainFrame:frame->IsMainFrame()
-                forSecurityOrigin:frame->GetSecurityOriginDeprecated()];
+  [controller_ processPasswordFormFillData:form_fill_data
+                                forFrameId:web_frame_id
+                               isMainFrame:frame->IsMainFrame()
+                         forSecurityOrigin:frame->GetSecurityOrigin()];
 
   // Check that completion handlers were called.
   EXPECT_TRUE(completion_was_called1);
@@ -1470,7 +1471,7 @@
   AddWebFrame(std::move(web_frame));
 
   ASSERT_TRUE(IsCrossOriginIframe(&web_state_, frame->IsMainFrame(),
-                                  frame->GetSecurityOriginDeprecated()));
+                                  frame->GetSecurityOrigin()));
 
   PasswordFormFillData form_fill_data;
   test_helpers::SetPasswordFormFillData(
@@ -1479,11 +1480,10 @@
       form.fields()[1].renderer_id().value(), "super!secret", nullptr, nullptr,
       &form_fill_data);
 
-  [controller_
-      processPasswordFormFillData:form_fill_data
-                       forFrameId:web_frame_id
-                      isMainFrame:frame->IsMainFrame()
-                forSecurityOrigin:frame->GetSecurityOriginDeprecated()];
+  [controller_ processPasswordFormFillData:form_fill_data
+                                forFrameId:web_frame_id
+                               isMainFrame:frame->IsMainFrame()
+                         forSecurityOrigin:frame->GetSecurityOrigin()];
 
   FormSuggestionProviderQuery* form_query = [[FormSuggestionProviderQuery alloc]
       initWithFormName:@"form"
@@ -1547,11 +1547,10 @@
                                    forFrameId:""])
       .andCompareStringAtIndex(web_frame_id, 1);
 
-  [controller_
-      processPasswordFormFillData:form_fill_data
-                       forFrameId:web_frame_id
-                      isMainFrame:frame->IsMainFrame()
-                forSecurityOrigin:frame->GetSecurityOriginDeprecated()];
+  [controller_ processPasswordFormFillData:form_fill_data
+                                forFrameId:web_frame_id
+                               isMainFrame:frame->IsMainFrame()
+                         forSecurityOrigin:frame->GetSecurityOrigin()];
 
   [delegate_ verify];
 }
@@ -1573,7 +1572,7 @@
   web_frames_manager_->AddWebFrame(std::move(web_frame));
 
   ASSERT_TRUE(IsCrossOriginIframe(&web_state_, frame->IsMainFrame(),
-                                  frame->GetSecurityOriginDeprecated()));
+                                  frame->GetSecurityOrigin()));
   [form_helper_ verify];
 }
 
@@ -1590,7 +1589,7 @@
   AddWebFrame(std::move(web_frame));
 
   ASSERT_TRUE(IsCrossOriginIframe(&web_state_, frame->IsMainFrame(),
-                                  frame->GetSecurityOriginDeprecated()));
+                                  frame->GetSecurityOrigin()));
 
   //  OCMExpect([driver_helper_ PasswordManagerDriver:frame]);
   EXPECT_CALL(password_manager_, OnIframeDetach).Times(1);
@@ -1610,7 +1609,7 @@
   AddWebFrame(std::move(web_frame));
 
   ASSERT_TRUE(IsCrossOriginIframe(&web_state_, frame->IsMainFrame(),
-                                  frame->GetSecurityOriginDeprecated()));
+                                  frame->GetSecurityOrigin()));
 
   FormSuggestionProviderQuery* form_query = [[FormSuggestionProviderQuery alloc]
       initWithFormName:@"form"
@@ -1655,7 +1654,7 @@
   AddWebFrame(std::move(web_frame));
 
   ASSERT_TRUE(IsCrossOriginIframe(&web_state_, frame->IsMainFrame(),
-                                  frame->GetSecurityOriginDeprecated()));
+                                  frame->GetSecurityOrigin()));
 
   FormSuggestionProviderQuery* form_query = [[FormSuggestionProviderQuery alloc]
       initWithFormName:@"form"
@@ -1698,7 +1697,7 @@
   AddWebFrame(std::move(web_frame));
 
   ASSERT_TRUE(IsCrossOriginIframe(&web_state_, frame->IsMainFrame(),
-                                  frame->GetSecurityOriginDeprecated()));
+                                  frame->GetSecurityOrigin()));
 
   OCMExpect([driver_helper_ PasswordManagerDriver:frame]);
 
@@ -1720,7 +1719,7 @@
   web::WebFrame* frame = web_frame.get();
 
   ASSERT_TRUE(IsCrossOriginIframe(&web_state_, frame->IsMainFrame(),
-                                  frame->GetSecurityOriginDeprecated()));
+                                  frame->GetSecurityOrigin()));
 
   OCMExpect([form_helper_ findPasswordFormsInFrame:frame
                                  completionHandler:[OCMArg any]]);
@@ -1753,7 +1752,7 @@
   AddWebFrame(std::move(web_frame));
 
   ASSERT_TRUE(IsCrossOriginIframe(&web_state_, frame->IsMainFrame(),
-                                  frame->GetSecurityOriginDeprecated()));
+                                  frame->GetSecurityOrigin()));
 
   OCMExpect([driver_helper_ PasswordManagerDriver:frame]);
   EXPECT_CALL(password_manager_, OnPasswordFormsRemoved).Times(1);
diff --git a/components/payments/content/android/BUILD.gn b/components/payments/content/android/BUILD.gn
index bd77ad17..f3e55dfe 100644
--- a/components/payments/content/android/BUILD.gn
+++ b/components/payments/content/android/BUILD.gn
@@ -13,8 +13,6 @@
     "byte_buffer_helper.h",
     "csp_checker_android.cc",
     "csp_checker_android.h",
-    "currency_formatter_android.cc",
-    "currency_formatter_android.h",
     "error_message_util.cc",
     "has_enrolled_instrument_query_android.cc",
     "jni_payment_app.cc",
@@ -42,6 +40,8 @@
     "payment_request_web_contents_data_android.cc",
     "payment_validator_android.cc",
     "ssl_validity_checker_android.cc",
+    "ui/currency_formatter_android.cc",
+    "ui/currency_formatter_android.h",
     "url_util.cc",
   ]
 
@@ -274,6 +274,7 @@
     ":browser_binding_java",
     "//base:base_junit_test_support",
     "//third_party/junit:junit",
+    "//third_party/mockito:mockito_java",
   ]
 }
 
@@ -287,6 +288,7 @@
     "//third_party/androidx:androidx_test_monitor_java",
     "//third_party/androidx:androidx_test_runner_java",
     "//third_party/junit:junit",
+    "//third_party/mockito:mockito_java",
     "//ui/android:ui_java_test_support",
   ]
 }
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/browser_binding/BrowserBoundKey.java b/components/payments/content/android/java/src/org/chromium/components/payments/browser_binding/BrowserBoundKey.java
index 05edfd3..8408ba2 100644
--- a/components/payments/content/android/java/src/org/chromium/components/payments/browser_binding/BrowserBoundKey.java
+++ b/components/payments/content/android/java/src/org/chromium/components/payments/browser_binding/BrowserBoundKey.java
@@ -9,11 +9,15 @@
 
 import org.chromium.base.Log;
 
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
 import java.security.InvalidKeyException;
 import java.security.KeyPair;
 import java.security.NoSuchAlgorithmException;
 import java.security.Signature;
 import java.security.SignatureException;
+import java.security.interfaces.ECPublicKey;
+import java.util.Arrays;
 
 /**
  * A browser bound key pair for a matching passkey.
@@ -41,7 +45,8 @@
         try {
             signature = Signature.getInstance(SHA256_WITH_ECDSA);
         } catch (NoSuchAlgorithmException e) {
-            // TODO: Eventually we will want to let Native code know that we can't do our job.
+            // TODO(crbug.com/377278827): Eventually we will want to let native code know that we
+            // can't do our job.
             Log.e(TAG, "Could not sign clientData for browser bound key support.", e);
             return null;
         }
@@ -57,22 +62,158 @@
         }
     }
 
-    private static final byte[] EMPTY_ARRAY = new byte[] {};
-
     /**
      * Returns the public key encoded as as COSE_Key including its algorithm type and parameters.
      *
+     * <p>Only ES256 with curve P-256 is implemented, and the key must be 256 bits.
+     *
      * <p>See credentialPublicKey in
      * https://www.w3.org/TR/webauthn-2/#sctn-attested-credential-data.
      */
     @CalledByNative
     @JniType("std::vector<uint8_t>")
     public byte[] getPublicKeyAsCoseKey() {
-        // TODO(crbug.com/377278827): Encode the key as a COSE_Key.
-        return EMPTY_ARRAY;
+        if (!(mKeyPair.getPublic() instanceof ECPublicKey)) {
+            return null;
+        }
+        return encodeCoseKeyWithEs256SignatureAlgorithm((ECPublicKey) mKeyPair.getPublic());
     }
 
     KeyPair getKeyPairForTesting() {
         return mKeyPair;
     }
+
+    private static class UnsupportedCborEncodingException extends Exception {
+        private UnsupportedCborEncodingException(String message) {
+            super(message);
+        }
+    }
+
+    /**
+     * Encodes the given public key as a COSE key with ES256 as the signature algorithm.
+     *
+     * <p>See credentialPublicKey, https://www.w3.org/TR/webauthn-2/#credentialpublickey.
+     *
+     * @param ecPublicKey An elliptic curve public key. The bit size must be 256.
+     */
+    private static byte[] encodeCoseKeyWithEs256SignatureAlgorithm(ECPublicKey ecPublicKey) {
+        try {
+            final int coseKeySizeForEs256 = 77;
+            ByteBuffer coseKeyBuffer = ByteBuffer.allocate(coseKeySizeForEs256);
+            // Begin a map of 5 pairs: For an ES256 key we need the key type (kty), algorithm (alg),
+            // curve type (crv), X-coordinate (x), and Y-coordinate (y). As in the WebAuthn spec
+            // other (optional) labels are not included.
+            putCborMajorTypeWithValue(coseKeyBuffer, CBOR_MAJOR_TYPE_MAP, 5); // Map with 5 pairs.
+
+            putCborInteger(coseKeyBuffer, 1); // Key type (kty)
+            putCborInteger(coseKeyBuffer, 2); // Elliptic curve key. See
+            // https://www.iana.org/assignments/cose/cose.xhtml#key-type
+
+            putCborInteger(coseKeyBuffer, 3); // Key restricted to algorithm (alg)
+            putCborInteger(coseKeyBuffer, -7); // ECDSA with SHA256. See
+            // https://www.iana.org/assignments/cose/cose.xhtml#algorithms
+
+            // The remaining pairs are key type parameters. See
+            // https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters
+
+            putCborInteger(coseKeyBuffer, -1); // Key type parameter: Curve Type (crv)
+            putCborInteger(coseKeyBuffer, 1); // P-256. See
+            // https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves
+
+            putCborInteger(coseKeyBuffer, -2); // Key type parameter: X-coordinate (x)
+            putCoordinateAsCborByteString(coseKeyBuffer, ecPublicKey.getW().getAffineX());
+
+            putCborInteger(coseKeyBuffer, -3); // Key type parameter: Y-coordinate (y)
+            putCoordinateAsCborByteString(coseKeyBuffer, ecPublicKey.getW().getAffineY());
+
+            // The buffer must be filled; otherwise, there is a problem with the encoding.
+            assert coseKeyBuffer.position() == coseKeySizeForEs256;
+            return coseKeyBuffer.array();
+        } catch (IndexOutOfBoundsException | UnsupportedCborEncodingException e) {
+            Log.e(TAG, "The browser bound public key could not be encoded.", e);
+            return null;
+        }
+    }
+
+    // The CBOR major types are encoded as integers in the top bits (bits 5-7). The lower bits (bits
+    // 0-4) are intentionally 0 here and will be filled by the value. See CBOR Major Types,
+    // https://datatracker.ietf.org/doc/html/rfc7049#section-2.1.
+
+    /** CBOR major type 0, a positive integer. */
+    private static final byte CBOR_MAJOR_TYPE_POSITIVE_INTEGER = (byte) 0b000_00000;
+
+    /** CBOR major type 1, a negative integer. */
+    private static final byte CBOR_MAJOR_TYPE_NEGATIVE_INTEGER = (byte) 0b001_00000;
+
+    /** CBOR major type 2, a byte string. */
+    private static final byte CBOR_MAJOR_TYPE_BYTE_STRING = (byte) 0b010_00000;
+
+    /** CBOR major type 5, a map of pairs. */
+    private static final byte CBOR_MAJOR_TYPE_MAP = (byte) 0b101_00000;
+
+    /** Writes a CBOR integer value in the range [-256, 255]. */
+    private static void putCborInteger(ByteBuffer out, int value)
+            throws UnsupportedCborEncodingException {
+        if (value >= 0) {
+            putCborMajorTypeWithValue(out, CBOR_MAJOR_TYPE_POSITIVE_INTEGER, value);
+        } else {
+            putCborMajorTypeWithValue(out, CBOR_MAJOR_TYPE_NEGATIVE_INTEGER, -(value + 1));
+        }
+    }
+
+    /**
+     * Serializes a 256-bit coordinate to a CBOR byte string in big endian format.
+     *
+     * @param coordinate The coordinate of a 256-bit elliptic curve key. Must not be negative.
+     */
+    private static void putCoordinateAsCborByteString(ByteBuffer out, BigInteger coordinate)
+            throws UnsupportedCborEncodingException {
+        if (coordinate.signum() == -1) {
+            throw new UnsupportedCborEncodingException("The coordinate must non-negative.");
+        }
+        if (coordinate.bitLength() > 256) {
+            throw new UnsupportedCborEncodingException("The coordinate must be 256-bits.");
+        }
+        byte[] twosComplementBytes = coordinate.toByteArray();
+        byte[] unsignedBytes;
+        // The twosComplementBytes representation might contain an initial extra zero (0) byte, this
+        // byte needs to be ignored when the leading zero would make the byte array larger than 32
+        // bytes.
+        if (twosComplementBytes.length == 33) {
+            unsignedBytes = Arrays.copyOfRange(twosComplementBytes, /* from= */ 1, /* to= */ 33);
+        } else {
+            unsignedBytes = new byte[32];
+            int start = 32 - twosComplementBytes.length;
+            // The upper bytes stay initialized to 0, fill the remaining bytes with the
+            // twosComplementBytes.
+            System.arraycopy(
+                    /* src= */ twosComplementBytes,
+                    /* srcPos= */ 0,
+                    /* dest= */ unsignedBytes,
+                    /* destPos= */ start,
+                    /* length= */ twosComplementBytes.length);
+        }
+        putCborMajorTypeWithValue(out, CBOR_MAJOR_TYPE_BYTE_STRING, unsignedBytes.length);
+        out.put(unsignedBytes);
+    }
+
+    /**
+     * Writes small CBOR values with the given major type.
+     *
+     * @param value The value to write. Must be less than 256.
+     */
+    private static void putCborMajorTypeWithValue(ByteBuffer out, byte majorType, int value)
+            throws UnsupportedCborEncodingException {
+        // See CBOR Major Types: https://datatracker.ietf.org/doc/html/rfc7049#section-2.1.
+        assert value >= 0;
+        if (value <= 23) {
+            out.put((byte) (majorType | value));
+        } else if (value <= 255) {
+            out.put((byte) (majorType | 24)); // A uint8_t follows (1 byte)
+            out.put((byte) value);
+        } else {
+            throw new UnsupportedCborEncodingException(
+                    "Writing values larger than 255 is unimplemented.");
+        }
+    }
 }
diff --git a/components/payments/content/android/junit/src/org/chromium/components/payments/browser_binding/BrowserBoundKeyTest.java b/components/payments/content/android/junit/src/org/chromium/components/payments/browser_binding/BrowserBoundKeyTest.java
index a0da33e..cec5310 100644
--- a/components/payments/content/android/junit/src/org/chromium/components/payments/browser_binding/BrowserBoundKeyTest.java
+++ b/components/payments/content/android/junit/src/org/chromium/components/payments/browser_binding/BrowserBoundKeyTest.java
@@ -4,7 +4,13 @@
 
 package org.chromium.components.payments.browser_binding;
 
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import android.security.keystore.KeyProperties;
 
@@ -13,10 +19,14 @@
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
 
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
 import java.security.Signature;
+import java.security.interfaces.ECPublicKey;
 import java.security.spec.ECGenParameterSpec;
+import java.security.spec.ECPoint;
 
 @RunWith(BaseRobolectricTestRunner.class)
 public class BrowserBoundKeyTest {
@@ -41,4 +51,154 @@
         signature.update(clientData);
         assertTrue(signature.verify(actualSignature));
     }
+
+    /** The CBOR byte denoting a bytestring with uint8_t length, then followed by the bytestring. */
+    private static final byte CBOR_BYTESTRING_UINT8 = 0b010_11000;
+
+    /** Test that coordinates of 32 bytes with and without leading zeros are encoded. */
+    @Test
+    public void testEncodeCoseKeyWith256BitEcPublicKey() {
+        // BigInteger serializes this to a 33 byte array. The first byte will be 0 followed by the
+        // the same bytes listed here.
+        final byte[] coordinate_with_leading_one =
+                new byte[] {
+                    -128, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+                    22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
+                };
+        // BigInteger serializes this to 32 bytes.
+        final byte[] coordinate_with_leading_zero =
+                new byte[] {
+                    127, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+                    53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
+                };
+        ECPublicKey publicKey =
+                mockEcPublicKey(
+                        new BigInteger(/* signum= */ 1, coordinate_with_leading_one),
+                        new BigInteger(/* signum= */ 1, coordinate_with_leading_zero));
+        BrowserBoundKey bbk = new BrowserBoundKey(new KeyPair(publicKey, /* private= */ null));
+
+        byte[] encodedKey = bbk.getPublicKeyAsCoseKey();
+
+        assertNotNull(encodedKey);
+        assertEncodedCoseKey(encodedKey, coordinate_with_leading_one, coordinate_with_leading_zero);
+    }
+
+    /**
+     * Test that a coordinate that serializes to less than 32 bytes encodes as 32 bytes.
+     *
+     * <p>BigInteger.toByteArray() will encode fewer than 32 bytes when the integer does not require
+     * 32 bytes to be encoded; however, the COSE key format needs 32 bytes with leading zeros.
+     */
+    @Test
+    public void testEncodeCoseKeyAddsLeadingZerosForSmallCoordinates() {
+        final byte[] small_coordinate =
+                new byte[] {
+                    -128, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+                    25, 26, 27, 28, 29, 30, 31, 32
+                };
+        final byte[] small_coordinate_encoded =
+                new byte[] {
+                    0, 0, 0, 0, -128, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+                    22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
+                };
+        ECPublicKey publicKey =
+                mockEcPublicKey(
+                        new BigInteger(/* signum= */ 1, small_coordinate),
+                        new BigInteger(/* signum= */ 1, small_coordinate));
+        BrowserBoundKey bbk = new BrowserBoundKey(new KeyPair(publicKey, /* private= */ null));
+
+        byte[] encodedKey = bbk.getPublicKeyAsCoseKey();
+
+        assertNotNull(encodedKey);
+        assertEncodedCoseKey(encodedKey, small_coordinate_encoded, small_coordinate_encoded);
+    }
+
+    /** Test that a null is returned for a unexpected negative coordinates. */
+    @Test
+    public void testEncodeCoseKeyReturnsNullOnNegativeCoordinate() {
+        BigInteger negative_coordinate = BigInteger.valueOf(-1);
+        ECPublicKey publicKey = mockEcPublicKey(negative_coordinate, negative_coordinate);
+        BrowserBoundKey bbk = new BrowserBoundKey(new KeyPair(publicKey, /* private= */ null));
+
+        byte[] encodedKey = bbk.getPublicKeyAsCoseKey();
+
+        assertNull(encodedKey);
+    }
+
+    /** Test that a null is returned for an unexpected coordinate size. */
+    @Test
+    public void testEncodeCoseKeyReturnsNullOnUnexpectedCoordinateSize() {
+        final byte[] large_coordinate_bytes = new byte[257];
+        large_coordinate_bytes[0] = 1;
+        final BigInteger large_coordinate = new BigInteger(/* signum= */ 1, large_coordinate_bytes);
+        ECPublicKey publicKey = mockEcPublicKey(large_coordinate, large_coordinate);
+        BrowserBoundKey bbk = new BrowserBoundKey(new KeyPair(publicKey, /* private= */ null));
+
+        byte[] encodedKey = bbk.getPublicKeyAsCoseKey();
+
+        assertNull(encodedKey);
+    }
+
+    /** Create a mock ECPublicKey with the given bytes for the curve coordinates. */
+    ECPublicKey mockEcPublicKey(BigInteger x, BigInteger y) {
+        ECPublicKey publicKey = mock(ECPublicKey.class);
+        when(publicKey.getW()).thenReturn(new ECPoint(x, y));
+        return publicKey;
+    }
+
+    /**
+     * Asserts an encoded COSE key with curve P-256 restricted to ES256.
+     *
+     * @param expectedX The encoded 32 byte x-coordinate.
+     * @param expectedY The encoded 32 byte y-coordinate.
+     */
+    private static void assertEncodedCoseKey(byte[] actualKey, byte[] expectedX, byte[] expectedY) {
+        ByteBuffer actualKeyBuffer = ByteBuffer.wrap(actualKey);
+        readAndAssertEqual(actualKeyBuffer, COSE_KEY_ES256_PREFIX);
+        readAndAssertEqual(actualKeyBuffer, COSE_KEY_X_COORDINATE_PREFIX);
+        readAndAssertEqual(actualKeyBuffer, expectedX);
+        readAndAssertEqual(actualKeyBuffer, COSE_KEY_Y_COORDINATE_PREFIX);
+        readAndAssertEqual(actualKeyBuffer, expectedY);
+        assertEquals(0, actualKeyBuffer.remaining());
+    }
+
+    private static final byte CBOR_MAP_5 = (byte) 0b101_00101;
+    private static final byte CBOR_1 = 0b000_00001;
+    private static final byte CBOR_2 = 0b000_00010;
+    private static final byte CBOR_3 = 0b000_00011;
+    private static final byte CBOR_NEGATIVE_1 = 0b001_00000;
+    private static final byte CBOR_NEGATIVE_2 = 0b001_00001;
+    private static final byte CBOR_NEGATIVE_3 = 0b001_00010;
+    private static final byte CBOR_NEGATIVE_7 = 0b001_00110;
+
+    private static final byte[] COSE_KEY_ES256_PREFIX =
+            new byte[] {
+                CBOR_MAP_5, // The COSE key is a map.
+                CBOR_1, // The key type is
+                CBOR_2, // EC2.
+                CBOR_3, // Restricted to algorithm
+                CBOR_NEGATIVE_7, // ES256.
+                CBOR_NEGATIVE_1, // The curve type is
+                CBOR_1, // P-256
+            };
+    private static final byte[] COSE_KEY_X_COORDINATE_PREFIX =
+            new byte[] {
+                CBOR_NEGATIVE_2, // The X-coordinate label.
+                CBOR_BYTESTRING_UINT8, // A byte string of
+                32, // size 32 bytes.
+            };
+    private static final byte[] COSE_KEY_Y_COORDINATE_PREFIX =
+            new byte[] {
+                CBOR_NEGATIVE_3, // The Y-coordinate label.
+                CBOR_BYTESTRING_UINT8, // A byte string of
+                32, // size 32 bytes.
+            };
+
+    /** Reads the expected length from the buffer and asserts the arrays are equal. */
+    private static void readAndAssertEqual(ByteBuffer actualBuffer, byte[] expected) {
+        assertTrue(actualBuffer.remaining() >= expected.length);
+        byte[] actual = new byte[expected.length];
+        actualBuffer.get(actual);
+        assertArrayEquals(expected, actual);
+    }
 }
diff --git a/components/payments/content/android/currency_formatter_android.cc b/components/payments/content/android/ui/currency_formatter_android.cc
similarity index 96%
rename from components/payments/content/android/currency_formatter_android.cc
rename to components/payments/content/android/ui/currency_formatter_android.cc
index 73ffaa4..4648045 100644
--- a/components/payments/content/android/currency_formatter_android.cc
+++ b/components/payments/content/android/ui/currency_formatter_android.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/payments/content/android/currency_formatter_android.h"
+#include "components/payments/content/android/ui/currency_formatter_android.h"
 
 #include <memory>
 #include <string>
diff --git a/components/payments/content/android/currency_formatter_android.h b/components/payments/content/android/ui/currency_formatter_android.h
similarity index 87%
rename from components/payments/content/android/currency_formatter_android.h
rename to components/payments/content/android/ui/currency_formatter_android.h
index 446068f9..a785962 100644
--- a/components/payments/content/android/currency_formatter_android.h
+++ b/components/payments/content/android/ui/currency_formatter_android.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_PAYMENTS_CONTENT_ANDROID_CURRENCY_FORMATTER_ANDROID_H_
-#define COMPONENTS_PAYMENTS_CONTENT_ANDROID_CURRENCY_FORMATTER_ANDROID_H_
+#ifndef COMPONENTS_PAYMENTS_CONTENT_ANDROID_UI_CURRENCY_FORMATTER_ANDROID_H_
+#define COMPONENTS_PAYMENTS_CONTENT_ANDROID_UI_CURRENCY_FORMATTER_ANDROID_H_
 
 #include <jni.h>
 #include <memory>
@@ -51,4 +51,4 @@
 
 }  // namespace payments
 
-#endif  // COMPONENTS_PAYMENTS_CONTENT_ANDROID_CURRENCY_FORMATTER_ANDROID_H_
+#endif  // COMPONENTS_PAYMENTS_CONTENT_ANDROID_UI_CURRENCY_FORMATTER_ANDROID_H_
diff --git a/components/payments/content/payment_request_state.cc b/components/payments/content/payment_request_state.cc
index 49cad22b..c827077f 100644
--- a/components/payments/content/payment_request_state.cc
+++ b/components/payments/content/payment_request_state.cc
@@ -19,12 +19,12 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/single_thread_task_runner.h"
 #include "components/autofill/core/browser/address_data_manager.h"
-#include "components/autofill/core/browser/address_normalizer.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_quality/addresses/address_normalizer.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/geo/autofill_country.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/payments/content/content_payment_request_delegate.h"
 #include "components/payments/content/payment_app.h"
 #include "components/payments/content/payment_manifest_web_data_service.h"
diff --git a/components/payments/content/payment_response_helper.cc b/components/payments/content/payment_response_helper.cc
index 41aed8c..e041707 100644
--- a/components/payments/content/payment_response_helper.cc
+++ b/components/payments/content/payment_response_helper.cc
@@ -11,9 +11,9 @@
 #include "base/functional/bind.h"
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/address_normalizer.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/data_quality/addresses/address_normalizer.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #include "components/autofill/core/browser/geo/autofill_country.h"
 #include "components/autofill/core/browser/geo/phone_number_i18n.h"
 #include "components/payments/content/payment_request_spec.h"
diff --git a/components/payments/content/secure_payment_confirmation_app.cc b/components/payments/content/secure_payment_confirmation_app.cc
index 3143067..5ad6cef 100644
--- a/components/payments/content/secure_payment_confirmation_app.cc
+++ b/components/payments/content/secure_payment_confirmation_app.cc
@@ -4,7 +4,10 @@
 
 #include "components/payments/content/secure_payment_confirmation_app.h"
 
+#include <cstdint>
+#include <optional>
 #include <utility>
+#include <vector>
 
 #include "base/base64.h"
 #include "base/base64url.h"
@@ -121,6 +124,7 @@
   options->allow_credentials = std::move(credentials);
 
   options->challenge = request_->challenge;
+  std::optional<std::vector<uint8_t>> maybe_browser_bound_key = std::nullopt;
 #if BUILDFLAG(IS_ANDROID)
   if (base::FeatureList::IsEnabled(
           blink::features::kSecurePaymentConfirmationBrowserBoundKeys)) {
@@ -130,12 +134,9 @@
     browser_bound_key_ =
         browser_bound_key_store_->GetOrCreateBrowserBoundKeyForCredentialId(
             credential_id_);
-    // TOOD(crbug.com/377278827): Add the browser bound public key to the
-    // clientDataJson via a new parameter on
-    // InternalAuthenticator::SetPaymentOptions.
+    maybe_browser_bound_key = browser_bound_key_->GetPublicKeyAsCoseKey();
   }
 #endif
-
   // TODO(crbug.com/40225659): The 'showOptOut' flag status must also be signed
   // in the assertion, so that the verifier can check that the caller offered
   // the experience if desired.
@@ -145,7 +146,8 @@
   authenticator_->SetPaymentOptions(blink::mojom::PaymentOptions::New(
       spec_->GetTotal(/*selected_app=*/this)->amount.Clone(),
       request_->instrument.Clone(), request_->payee_name,
-      request_->payee_origin));
+      request_->payee_origin, maybe_browser_bound_key));
+
   authenticator_->GetAssertion(
       std::move(options),
       base::BindOnce(&SecurePaymentConfirmationApp::OnGetAssertion,
diff --git a/components/payments/content/secure_payment_confirmation_app_unittest.cc b/components/payments/content/secure_payment_confirmation_app_unittest.cc
index c084d95..72ce148 100644
--- a/components/payments/content/secure_payment_confirmation_app_unittest.cc
+++ b/components/payments/content/secure_payment_confirmation_app_unittest.cc
@@ -4,8 +4,12 @@
 
 #include "components/payments/content/secure_payment_confirmation_app.h"
 
+#include <cstdint>
+#include <map>
 #include <memory>
+#include <optional>
 #include <utility>
+#include <vector>
 
 #include "base/base64.h"
 #include "base/memory/raw_ptr.h"
@@ -37,6 +41,7 @@
 using ::testing::ElementsAreArray;
 using ::testing::Eq;
 using ::testing::Field;
+using ::testing::Optional;
 using ::testing::Property;
 
 static constexpr char kChallengeBase64[] = "aaaa";
@@ -45,18 +50,18 @@
 class FakeBrowserBoundKey : public BrowserBoundKey {
  public:
   FakeBrowserBoundKey() = default;
-  FakeBrowserBoundKey(std::vector<uint8_t> cose_key,
+  FakeBrowserBoundKey(std::vector<uint8_t> public_key_as_cose_key,
                       std::vector<uint8_t> signature,
                       std::vector<uint8_t> expected_client_data)
-      : cose_key_(cose_key),
+      : public_key_as_cose_key_(public_key_as_cose_key),
         signature_(signature),
         expected_client_data_(expected_client_data) {}
   FakeBrowserBoundKey(const FakeBrowserBoundKey& other)
-      : cose_key_(other.cose_key_),
+      : public_key_as_cose_key_(other.public_key_as_cose_key_),
         signature_(other.signature_),
         expected_client_data_(other.expected_client_data_) {}
   FakeBrowserBoundKey& operator=(const FakeBrowserBoundKey& other) {
-    cose_key_ = other.cose_key_;
+    public_key_as_cose_key_ = other.public_key_as_cose_key_;
     signature_ = other.signature_;
     expected_client_data_ = other.expected_client_data_;
     return *this;
@@ -69,10 +74,12 @@
     }
     return {};
   }
-  std::vector<uint8_t> GetPublicKeyAsCoseKey() override { return cose_key_; }
+  std::vector<uint8_t> GetPublicKeyAsCoseKey() override {
+    return public_key_as_cose_key_;
+  }
 
  private:
-  std::vector<uint8_t> cose_key_;
+  std::vector<uint8_t> public_key_as_cose_key_;
   std::vector<uint8_t> signature_;
   std::vector<uint8_t> expected_client_data_;
 };
@@ -223,7 +230,7 @@
 }
 
 #if BUILDFLAG(IS_ANDROID)
-TEST_F(SecurePaymentConfirmationAppTest, AddsBrowserBoundSignature) {
+TEST_F(SecurePaymentConfirmationAppTest, AddsBrowserBoundKeyAndSignature) {
   base::test::ScopedFeatureList features(
       blink::features::kSecurePaymentConfirmationBrowserBoundKeys);
   auto authenticator =
@@ -232,8 +239,9 @@
   std::vector<uint8_t> credential_id(credential_id_bytes_.begin(),
                                      credential_id_bytes_.end());
   const std::vector<uint8_t> client_data_json({0x01, 0x02, 0x03, 0x04});
-  const std::vector<uint8_t> signature({0x05, 0x06, 0x07, 0x08});
-  FakeBrowserBoundKey browser_bound_key(/*cose_key=*/{}, signature,
+  const std::vector<uint8_t> public_key_as_cose_key({0x05, 0x06, 0x07, 0x08});
+  const std::vector<uint8_t> signature({0x09, 0x0a, 0x0b, 0x0c});
+  FakeBrowserBoundKey browser_bound_key(public_key_as_cose_key, signature,
                                         client_data_json);
   SecurePaymentConfirmationApp app(
       web_contents_, "effective_rp.example", payment_instrument_label_,
@@ -245,6 +253,11 @@
   app.SetBrowserBoundKeyStoreForTesting(MakeFakeBrowserBoundKeyStore());
   browser_bound_key_store_->PutFakeKey(credential_id, browser_bound_key);
 
+  EXPECT_CALL(*mock_authenticator,
+              SetPaymentOptions(Pointee(
+                  Field("browser_bound_public_key",
+                        &blink::mojom::PaymentOptions::browser_bound_public_key,
+                        Optional(ElementsAreArray(public_key_as_cose_key))))));
   EXPECT_CALL(*mock_authenticator, GetAssertion(_, _))
       .WillOnce(
           [client_data_json](
diff --git a/components/payments/core/payment_request_data_util.cc b/components/payments/core/payment_request_data_util.cc
index 4798f6d..2e6d6b9 100644
--- a/components/payments/core/payment_request_data_util.cc
+++ b/components/payments/core/payment_request_data_util.cc
@@ -10,12 +10,12 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/geo/autofill_country.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/payments/core/method_strings.h"
 #include "components/payments/core/payment_method_data.h"
 #include "components/payments/core/payments_validators.h"
diff --git a/components/payments/core/payments_profile_comparator.cc b/components/payments/core/payments_profile_comparator.cc
index ad04b83e..0535310 100644
--- a/components/payments/core/payments_profile_comparator.cc
+++ b/components/payments/core/payments_profile_comparator.cc
@@ -10,12 +10,12 @@
 #include "base/memory/raw_ptr.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_quality/autofill_data_util.h"
+#include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/geo/address_i18n.h"
 #include "components/autofill/core/browser/geo/autofill_country.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/payments/core/payment_options_provider.h"
 #include "components/payments/core/payment_request_data_util.h"
 #include "components/strings/grit/components_strings.h"
diff --git a/components/payments/core/test_payment_request_delegate.h b/components/payments/core/test_payment_request_delegate.h
index 29b8bda..6170b9e 100644
--- a/components/payments/core/test_payment_request_delegate.h
+++ b/components/payments/core/test_payment_request_delegate.h
@@ -11,9 +11,9 @@
 #include "base/memory/raw_ptr.h"
 #include "base/task/single_thread_task_executor.h"
 #include "base/task/single_thread_task_runner.h"
+#include "components/autofill/core/browser/data_quality/addresses/test_address_normalizer.h"
 #include "components/autofill/core/browser/payments/full_card_request.h"
 #include "components/autofill/core/browser/payments/payments_network_interface.h"
-#include "components/autofill/core/browser/test_address_normalizer.h"
 #include "components/autofill/core/browser/test_autofill_client.h"
 #include "components/payments/core/payment_request_delegate.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
diff --git a/components/policy/core/common/cloud/cloud_policy_client_unittest.cc b/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
index 452ab3f..99019b4 100644
--- a/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
+++ b/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
@@ -2,16 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifdef UNSAFE_BUFFERS_BUILD
-// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
-#pragma allow_unsafe_buffers
-#endif
-
 #include "components/policy/core/common/cloud/cloud_policy_client.h"
 
 #include <stddef.h>
 #include <stdint.h>
 
+#include <array>
 #include <map>
 #include <memory>
 #include <set>
@@ -1877,11 +1873,11 @@
   em::DeviceManagementResponse policy_response = GetPolicyResponse();
 
   // Set up the |expected_responses| and |policy_response|.
-  static const char* kExtensions[] = {
+  static auto kExtensions = std::to_array<const char*>({
       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
       "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
       "cccccccccccccccccccccccccccccccc",
-  };
+  });
   typedef std::map<std::pair<std::string, std::string>, em::PolicyFetchResponse>
       ResponseMap;
   ResponseMap expected_responses;
diff --git a/components/policy/core/common/cloud/external_policy_data_fetcher_unittest.cc b/components/policy/core/common/cloud/external_policy_data_fetcher_unittest.cc
index 01bef14..05f72d5 100644
--- a/components/policy/core/common/cloud/external_policy_data_fetcher_unittest.cc
+++ b/components/policy/core/common/cloud/external_policy_data_fetcher_unittest.cc
@@ -2,21 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/memory/raw_ptr.h"
-
-#ifdef UNSAFE_BUFFERS_BUILD
-// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
-#pragma allow_unsafe_buffers
-#endif
-
 #include "components/policy/core/common/cloud/external_policy_data_fetcher.h"
 
 #include <stdint.h>
+
+#include <array>
 #include <utility>
 
 #include "base/compiler_specific.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
+#include "base/memory/raw_ptr.h"
 #include "base/run_loop.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/test/task_environment.h"
@@ -31,10 +27,8 @@
 
 namespace {
 
-const char* kExternalPolicyDataURLs[] = {
-    "http://localhost/data_1",
-    "http://localhost/data_2"
-};
+auto kExternalPolicyDataURLs = std::to_array<const char*>(
+    {"http://localhost/data_1", "http://localhost/data_2"});
 
 const int64_t kExternalPolicyDataMaxSize = 20;
 
diff --git a/components/policy/core/common/cloud/external_policy_data_updater_unittest.cc b/components/policy/core/common/cloud/external_policy_data_updater_unittest.cc
index 5c92c10..0ae82d48 100644
--- a/components/policy/core/common/cloud/external_policy_data_updater_unittest.cc
+++ b/components/policy/core/common/cloud/external_policy_data_updater_unittest.cc
@@ -2,16 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifdef UNSAFE_BUFFERS_BUILD
-// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
-#pragma allow_unsafe_buffers
-#endif
-
 #include "components/policy/core/common/cloud/external_policy_data_updater.h"
 
 #include <stddef.h>
 #include <stdint.h>
 
+#include <array>
 #include <memory>
 
 #include "base/compiler_specific.h"
@@ -40,12 +36,16 @@
 
 namespace {
 
-const char* kExternalPolicyDataKeys[] = {"external_policy_data_1",
-                                         "external_policy_data_2",
-                                         "external_policy_data_3"};
-const char* kExternalPolicyDataURLs[] = {"http://example.com/data_1",
-                                         "http://example.com/data_2",
-                                         "http://example.com/data_3"};
+auto kExternalPolicyDataKeys = std::to_array<const char*>({
+    "external_policy_data_1",
+    "external_policy_data_2",
+    "external_policy_data_3",
+});
+auto kExternalPolicyDataURLs = std::to_array<const char*>({
+    "http://example.com/data_1",
+    "http://example.com/data_2",
+    "http://example.com/data_3",
+});
 
 const int64_t kExternalPolicyDataMaxSize = 20;
 
diff --git a/components/policy/core/common/policy_statistics_collector_unittest.cc b/components/policy/core/common/policy_statistics_collector_unittest.cc
index f49a2b6..0740875 100644
--- a/components/policy/core/common/policy_statistics_collector_unittest.cc
+++ b/components/policy/core/common/policy_statistics_collector_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "components/policy/core/common/policy_statistics_collector.h"
 
+#include <array>
 #include <cstring>
 #include <memory>
 #include <string>
@@ -62,7 +63,7 @@
       }
     })";
 
-const PolicyDetails kTestPolicyDetails[] = {
+const auto kTestPolicyDetails = std::to_array<PolicyDetails>({
     // is_deprecated is_future is_device_policy id  max_external_data_size
     {false, false, kProfile, kTestPolicy1Id, 0},
     {false, false, kProfile, kTestPolicy2Id, 0},
@@ -70,7 +71,7 @@
     {false, false, kProfile, kEnrollmentTokenPolicyId, 0},
     {false, false, kProfile, kEnrollmentOptionPolicyId, 0},
     {false, false, kProfile, kBrowserSigninPolicyId, 0},
-};
+});
 
 }  // namespace
 
diff --git a/components/policy/core/common/schema_unittest.cc b/components/policy/core/common/schema_unittest.cc
index 73a2c5f..308f5d0 100644
--- a/components/policy/core/common/schema_unittest.cc
+++ b/components/policy/core/common/schema_unittest.cc
@@ -2,15 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifdef UNSAFE_BUFFERS_BUILD
-// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
-#pragma allow_unsafe_buffers
-#endif
-
 #include "components/policy/core/common/schema.h"
 
 #include <stddef.h>
 
+#include <array>
 #include <memory>
 #include <utility>
 
@@ -603,10 +599,11 @@
   // Wrapped schemas have no sensitive values.
   EXPECT_FALSE(schema.IsSensitiveValue());
 
-  struct {
+  struct ExpectedProperties {
     const char* key;
     base::Value::Type type;
-  } kExpectedProperties[] = {
+  };
+  auto kExpectedProperties = std::to_array<ExpectedProperties>({
       {"Boolean", base::Value::Type::BOOLEAN},
       {"DictRequired", base::Value::Type::DICT},
       {"Integer", base::Value::Type::INTEGER},
@@ -617,7 +614,7 @@
       {"RangedInt", base::Value::Type::INTEGER},
       {"StrEnum", base::Value::Type::STRING},
       {"StrPat", base::Value::Type::STRING},
-  };
+  });
 
   Schema::Iterator it = schema.GetPropertiesIterator();
   for (size_t i = 0; i < std::size(kExpectedProperties); ++i) {
diff --git a/components/policy/resources/policy_templates_zh-TW.xtb b/components/policy/resources/policy_templates_zh-TW.xtb
index 8bb2b62..4a9f16c 100644
--- a/components/policy/resources/policy_templates_zh-TW.xtb
+++ b/components/policy/resources/policy_templates_zh-TW.xtb
@@ -266,6 +266,7 @@
 <translation id="117080706484659953">允許 <ph name="MAC_OS_NAME" /> 上的政策範圍偵測</translation>
 <translation id="1171106901454883937">啟用裝置版本資訊回報功能</translation>
 <translation id="1173493742686115032">在所有網頁上啟用 <ph name="SEARCH_SIDE_PANEL_FEATURE_NAME" /></translation>
+<translation id="1176740714945046981">啟用隔離網頁應用程式 (IWA) 降級功能。根據預設,系統只會安裝較新版本的 IWA。如果設為 <ph name="TRUE" />,則使用者也能安裝較舊版本的 IWA。如要啟用降級功能,必須使用「pinned_version」欄位指定所需的版本值。如果未提供「allow_downgrades」或已設為 <ph name="FALSE" />,則系統會停用該 IWA 的降級功能。</translation>
 <translation id="1177624681620856105"> 這項政策可控管系統是否要在外部通訊協定的啟動確認提示中顯示「一律開啟」核取方塊。
 
       如果將這項政策設為 True 或不予設定,當系統顯示外部通訊協定的確認訊息時,使用者可以選取「一律允許」,這樣日後會略過這個網站上的所有通訊協定確認提示。
@@ -3152,6 +3153,16 @@
 <translation id="3387211681524224831">如果將這項政策設為啟用,系統不會儲存瀏覽記錄,並會停用分頁同步功能,且使用者無法變更這項設定。
 
       如果將這項政策設為停用或不設定,系統會儲存瀏覽記錄。</translation>
+<translation id="3387875422525138489">如果設定這項政策,就能指定以無訊息方式安裝的隔離網頁應用程式 (IWA) 清單。
+      相較於一般網頁,IWA 這類應用程式有實用的安全屬性,而且是透過已簽署網頁套件的形式包裝。已簽署網頁套件的公開金鑰會用於建立可辨識 IWA 的網頁軟體包 ID。
+      這項政策目前僅適用於受管理的訪客工作階段。
+
+      這項政策中的每個清單項目都是一個物件,當中有兩個必填欄位:更新資訊清單 (<ph name="URL_LABEL" />) 和隔離網頁應用程式的網頁軟體包 ID。
+
+      每個項目還含有下列選用欄位:
+
+        * <ph name="UPDATE_CHANNEL_OPTION" />:IWA 發布版本/更新版本名稱。如果未設定,系統會使用「default」。* <ph name="PINNED_VERSION_OPTION" />:要安裝的特定版本。如果指定的更新版本可用,系統就會嘗試安裝這個版本。根據預設,如果將 IWA 固定在特定版本,該應用程式就不會再繼續更新。如要取消固定,請移除這個欄位。
+        * <ph name="ALLOW_DOWNGRADES_OPTION" />:可安裝較舊版本的 IWA。如要這麼做,必須先設定「pinned_version」欄位。如果未提供或設為 <ph name="FALSE" />,系統就會停用該 IWA 的降級功能。</translation>
 <translation id="3387999258705169775">setTimeout() 巢狀函式的預設行為出現延遲。</translation>
 <translation id="3388628790024977864">不允許 <ph name="GOOGLE_DRIVE_NAME" />和 <ph name="GOOGLE_WORKSPACE_NAME" /> 的<ph name="CLOUD_UPLOAD_NAME" />資料流</translation>
 <translation id="3389088527709746815">針對遠端存取主機啟用 gnubby 驗證機制</translation>
diff --git a/components/policy/resources/webui/policy_promotion.html b/components/policy/resources/webui/policy_promotion.html
index 6e65dd1..f2a5412 100644
--- a/components/policy/resources/webui/policy_promotion.html
+++ b/components/policy/resources/webui/policy_promotion.html
@@ -66,6 +66,7 @@
   color: var(--promotion-banner-description-color);
   font-size: 14px;
   font-weight: 400;
+  line-height: 20px;
 }
 
 .promotion-icon-container {
diff --git a/components/spellcheck/browser/spellcheck_host_metrics_unittest.cc b/components/spellcheck/browser/spellcheck_host_metrics_unittest.cc
index 7cf04e42..0b89103510 100644
--- a/components/spellcheck/browser/spellcheck_host_metrics_unittest.cc
+++ b/components/spellcheck/browser/spellcheck_host_metrics_unittest.cc
@@ -11,6 +11,7 @@
 
 #include <stddef.h>
 
+#include <array>
 #include <memory>
 
 #include "base/metrics/histogram_samples.h"
@@ -57,10 +58,13 @@
 TEST_F(SpellcheckHostMetricsTest, RecordWordCountsDiscardsDuplicates) {
   // This test ensures that RecordWordCounts only records metrics if they
   // have changed from the last invocation.
-  const char* const histogram_names[] = {
-      "SpellCheck.CheckedWords", "SpellCheck.MisspelledWords",
-      "SpellCheck.ReplacedWords", "SpellCheck.UniqueWords",
-      "SpellCheck.ShownSuggestions"};
+  const auto histogram_names = std::to_array<const char*>({
+      "SpellCheck.CheckedWords",
+      "SpellCheck.MisspelledWords",
+      "SpellCheck.ReplacedWords",
+      "SpellCheck.UniqueWords",
+      "SpellCheck.ShownSuggestions",
+  });
 
   // Ensure all histograms exist.
   metrics()->RecordCheckedWordStats(u"test", false);
diff --git a/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc b/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc
index eb65a3b6..cb9422b 100644
--- a/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc
+++ b/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc
@@ -10,6 +10,7 @@
 #include <stddef.h>
 
 #include <algorithm>
+#include <array>
 #include <memory>
 #include <string_view>
 #include <utility>
@@ -227,7 +228,7 @@
 // Ensure that suggestions are handled properly for multiple languages.
 TEST_F(MultilingualSpellCheckTest, MultilingualSpellCheckSuggestions) {
   ReinitializeSpellCheck("en-US,es-ES");
-  static const struct {
+  struct TestCases {
     // A string of text for checking.
     const wchar_t* input;
     // The position and the length of the first invalid word.
@@ -236,13 +237,14 @@
     // A comma separated string of suggested words that should occur, in their
     // expected order.
     const wchar_t* expected_suggestions;
-  } kTestCases[] = {
+  };
+  static const auto kTestCases = std::to_array<TestCases>({
       {L"rocket", 0, 0},
       {L"destruyan", 0, 0},
       {L"rocet", 0, 5, L"rocket,roce,crochet,troce,rocen"},
       {L"jum", 0, 3, L"hum,jun,ju,um,juma"},
       {L"asdne", 0, 5, L"sadness,desasne"},
-  };
+  });
 
   for (size_t i = 0; i < std::size(kTestCases); ++i) {
     blink::WebVector<blink::WebString> suggestions;
diff --git a/components/spellcheck/renderer/spellcheck_unittest.cc b/components/spellcheck/renderer/spellcheck_unittest.cc
index 2016455a..3e034374 100644
--- a/components/spellcheck/renderer/spellcheck_unittest.cc
+++ b/components/spellcheck/renderer/spellcheck_unittest.cc
@@ -2,15 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifdef UNSAFE_BUFFERS_BUILD
-// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
-#pragma allow_unsafe_buffers
-#endif
-
 #include "components/spellcheck/renderer/spellcheck.h"
 
 #include <stddef.h>
 
+#include <array>
 #include <memory>
 #include <utility>
 
@@ -194,7 +190,7 @@
 // grammatically incorrect string.
 // TODO(groby): Please feel free to add more tests.
 TEST_F(SpellCheckTest, SpellCheckStrings_EN_US) {
-  static const struct {
+  struct TestCases {
     // A string to be tested.
     const wchar_t* input;
     // An expected result for this test case.
@@ -204,7 +200,8 @@
     // The position and the length of the first invalid word.
     size_t misspelling_start;
     size_t misspelling_length;
-  } kTestCases[] = {
+  };
+  static const auto kTestCases = std::to_array<TestCases>({
       // Empty strings.
       {L"", true},
       {L" ", true},
@@ -551,7 +548,7 @@
       {L"2012", true},
       {L"100,000,000", true},
       {L"3.141592653", true},
-  };
+  });
   for (size_t i = 0; i < std::size(kTestCases); ++i) {
     size_t misspelling_start;
     size_t misspelling_length;
@@ -617,10 +614,11 @@
 // This test verifies our spellchecker can split a text into words and check
 // the spelling of each word in the text.
 TEST_F(SpellCheckTest, SpellCheckText) {
-  static const struct {
+  struct TestCases {
     const char* language;
     const wchar_t* input;
-  } kTestCases[] = {
+  };
+  static const auto kTestCases = std::to_array<TestCases>({
       {// Afrikaans
        "af-ZA",
        L"Google se missie is om die w\x00EAreld se inligting te organiseer en "
@@ -950,7 +948,7 @@
        L"\x0443\x043c\x0443\x043c "
        L"\x0433\x0430\x0440\x0434\x043e\x043d\x0438\x0434\x0430\x043d\x0438 "
        L"\x043e\x043d\x04b3\x043e \x0430\x0441\x0442."},
-  };
+  });
 
   for (size_t i = 0; i < std::size(kTestCases); ++i) {
     ReinitializeSpellCheck(kTestCases[i].language);
@@ -975,36 +973,42 @@
 // Verify that our SpellCheck::SpellCheckWord() returns false when it checks
 // misspelled words.
 TEST_F(SpellCheckTest, MisspelledWords) {
-  static const struct {
+  struct TestCases {
     const char* language;
     const wchar_t* input;
-  } kTestCases[] = {
-    {
-      // A misspelled word for English
-      "en-US",
-      L"aaaaaaaaaa",
-    }, {
-      // A misspelled word for Greek.
-      "el-GR",
-      L"\x03B1\x03B1\x03B1\x03B1\x03B1\x03B1\x03B1\x03B1\x03B1\x03B1",
-    }, {
-      // A misspelled word for Persian.
-      "fa",
-      L"\x06cc\x06a9\x06cc\x0634\x0627\x0646",
-    }, {
-      // A misspelled word for Hebrew
-      "he-IL",
-      L"\x05D0\x05D0\x05D0\x05D0\x05D0\x05D0\x05D0\x05D0\x05D0\x05D0",
-    }, {
-      // Hindi
-      "hi-IN",
-      L"\x0905\x0905\x0905\x0905\x0905\x0905\x0905\x0905\x0905\x0905",
-    }, {
-      // A misspelled word for Russian
-      "ru-RU",
-      L"\x0430\x0430\x0430\x0430\x0430\x0430\x0430\x0430\x0430\x0430",
-    },
   };
+  static const auto kTestCases = std::to_array<TestCases>({
+      {
+          // A misspelled word for English
+          "en-US",
+          L"aaaaaaaaaa",
+      },
+      {
+          // A misspelled word for Greek.
+          "el-GR",
+          L"\x03B1\x03B1\x03B1\x03B1\x03B1\x03B1\x03B1\x03B1\x03B1\x03B1",
+      },
+      {
+          // A misspelled word for Persian.
+          "fa",
+          L"\x06cc\x06a9\x06cc\x0634\x0627\x0646",
+      },
+      {
+          // A misspelled word for Hebrew
+          "he-IL",
+          L"\x05D0\x05D0\x05D0\x05D0\x05D0\x05D0\x05D0\x05D0\x05D0\x05D0",
+      },
+      {
+          // Hindi
+          "hi-IN",
+          L"\x0905\x0905\x0905\x0905\x0905\x0905\x0905\x0905\x0905\x0905",
+      },
+      {
+          // A misspelled word for Russian
+          "ru-RU",
+          L"\x0430\x0430\x0430\x0430\x0430\x0430\x0430\x0430\x0430\x0430",
+      },
+  });
 
   for (size_t i = 0; i < std::size(kTestCases); ++i) {
     ReinitializeSpellCheck(kTestCases[i].language);
@@ -1173,9 +1177,10 @@
 // A test case that multiple requests comes at once. Make sure all
 // requests are processed.
 TEST_F(SpellCheckTest, RequestSpellCheckWithMultipleRequests) {
-  MockTextCheckingResult completion[3];
+  std::array<MockTextCheckingResult, 3> completion;
 
-  const std::u16string text[3] = {u"what, zz", u"apple, zz", u"orange, zz"};
+  const std::array<std::u16string, 3> text = {u"what, zz", u"apple, zz",
+                                              u"orange, zz"};
 
   for (int i = 0; i < 3; ++i)
     spell_check()->RequestTextChecking(
@@ -1214,8 +1219,9 @@
 TEST_F(SpellCheckTest, RequestSpellCheckMultipleTimesWithoutInitialization) {
   UninitializeSpellCheck();
 
-  MockTextCheckingResult completion[3];
-  const std::u16string text[3] = {u"what, zz", u"apple, zz", u"orange, zz"};
+  std::array<MockTextCheckingResult, 3> completion;
+  const std::array<std::u16string, 3> text = {u"what, zz", u"apple, zz",
+                                              u"orange, zz"};
 
   // Calls RequestTextchecking a few times.
   for (int i = 0; i < 3; ++i)
@@ -1375,33 +1381,36 @@
 
 // Checks some words that should be present in all English dictionaries.
 TEST_F(SpellCheckTest, EnglishWords) {
-  static const struct {
+  struct TestCases {
     const char* input;
     bool should_pass;
-  } kTestCases[] = {
-    // Issue 146093: "Chromebook" and "Chromebox" not included in spell-checking
-    // dictionary.
-    {"Chromebook", true},
-    {"Chromebooks", true},
-    {"Chromebox", true},
-    {"Chromeboxes", true},
-    {"Chromeblade", true},
-    {"Chromeblades", true},
-    {"Chromebase", true},
-    {"Chromebases", true},
-    // Issue 94708: Spell-checker incorrectly reports whisky as misspelled.
-    {"whisky", true},
-    {"whiskey", true},
-    {"whiskies", true},
-    // Issue 98678: "Recency" should be included in client-side dictionary.
-    {"recency", true},
-    {"recencies", false},
-    // Issue 140486
-    {"movie", true},
-    {"movies", true},
   };
+  static const auto kTestCases = std::to_array<TestCases>({
+      // Issue 146093: "Chromebook" and "Chromebox" not included in
+      // spell-checking
+      // dictionary.
+      {"Chromebook", true},
+      {"Chromebooks", true},
+      {"Chromebox", true},
+      {"Chromeboxes", true},
+      {"Chromeblade", true},
+      {"Chromeblades", true},
+      {"Chromebase", true},
+      {"Chromebases", true},
+      // Issue 94708: Spell-checker incorrectly reports whisky as misspelled.
+      {"whisky", true},
+      {"whiskey", true},
+      {"whiskies", true},
+      // Issue 98678: "Recency" should be included in client-side dictionary.
+      {"recency", true},
+      {"recencies", false},
+      // Issue 140486
+      {"movie", true},
+      {"movies", true},
+  });
 
-  static const char* const kLocales[] = { "en-GB", "en-US", "en-CA", "en-AU" };
+  static const auto kLocales =
+      std::to_array<const char*>({"en-GB", "en-US", "en-CA", "en-AU"});
 
   for (size_t j = 0; j < std::size(kLocales); ++j) {
     ReinitializeSpellCheck(kLocales[j]);
diff --git a/components/spellcheck/renderer/spellcheck_worditerator_unittest.cc b/components/spellcheck/renderer/spellcheck_worditerator_unittest.cc
index 9f929de..db8b81bd 100644
--- a/components/spellcheck/renderer/spellcheck_worditerator_unittest.cc
+++ b/components/spellcheck/renderer/spellcheck_worditerator_unittest.cc
@@ -2,15 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifdef UNSAFE_BUFFERS_BUILD
-// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
-#pragma allow_unsafe_buffers
-#endif
-
 #include "components/spellcheck/renderer/spellcheck_worditerator.h"
 
 #include <stddef.h>
 
+#include <array>
 #include <string>
 #include <vector>
 
@@ -107,59 +103,47 @@
       u"e.g.,";
 
   // The languages and expected results used in this test.
-  static const TestCase kTestCases[] = {
-    {
-      // English (keep contraction words)
-      "en-US", true, L"hello:hello affix Hello e.g"
-    }, {
-      // English (split contraction words)
-      "en-US", false, L"hello hello affix Hello e g"
-    }, {
-      // Greek
-      "el-GR", true,
-      L"\x03B3\x03B5\x03B9\x03AC\x0020\x03C3\x03BF\x03C5"
-    }, {
-      // Russian
-      "ru-RU", true,
-      L"\x0437\x0434\x0440\x0430\x0432\x0441\x0442\x0432"
-      L"\x0443\x0439\x0442\x0435"
-    }, {
-      // Hebrew
-      "he-IL", true,
-      L"\x05e9\x05dc\x05d5\x05dd "
-      L"\x05e6\x0027\x05d9\x05e4\x05e1 \x05e6\x05F3\x05d9\x05e4\x05e1 "
-      L"\x05e6\x05d4\x0022\x05dc \x05e6\x05d4\x05f4\x05dc "
-      L"\x05e6\x05d4\x0022\x05dc \x05e9\x05dc\x05d5"
-    }, {
-      // Arabic
-      "ar", true,
-      L"\x0627\x0644\x0633\x0644\x0627\x0645 "
-      L"\x0639\x0644\x064a\x0643\x0645 "
-      // Farsi/Persian
-      L"\x0647\x0634\x0631\x062d "
-      L"\x0647\x062e\x0648\x0627\x0647 "
-      L"\x062f\x0631\x062f "
-      L"\x0631\x0645\x0627\x0646 "
-      L"\x0633\x0631 "
-      L"\x0646\x0646\x062c\x0633 "
-      L"\x0627\x0644\x062d\x0645\x062f "
-      L"\x062c\x062c\x062c\x062c"
-    }, {
-      // Hindi
-      "hi-IN", true,
-      L"\x0930\x093E\x091C\x0927\x093E\x0928"
-    }, {
-      // Thai
-      "th-TH", true,
-      L"\x0e2a\x0e27\x0e31\x0e2a\x0e14\x0e35\x0020\x0e04"
-      L"\x0e23\x0e31\x0e1a"
-    }, {
-      // Korean
-      "ko-KR", true,
-      L"\x110b\x1161\x11ab\x1102\x1167\x11bc\x1112\x1161"
-      L"\x1109\x1166\x110b\x116d"
-    },
-  };
+  static const auto kTestCases = std::to_array<TestCase>({
+      {// English (keep contraction words)
+       "en-US", true, L"hello:hello affix Hello e.g"},
+      {// English (split contraction words)
+       "en-US", false, L"hello hello affix Hello e g"},
+      {// Greek
+       "el-GR", true, L"\x03B3\x03B5\x03B9\x03AC\x0020\x03C3\x03BF\x03C5"},
+      {// Russian
+       "ru-RU", true,
+       L"\x0437\x0434\x0440\x0430\x0432\x0441\x0442\x0432"
+       L"\x0443\x0439\x0442\x0435"},
+      {// Hebrew
+       "he-IL", true,
+       L"\x05e9\x05dc\x05d5\x05dd "
+       L"\x05e6\x0027\x05d9\x05e4\x05e1 \x05e6\x05F3\x05d9\x05e4\x05e1 "
+       L"\x05e6\x05d4\x0022\x05dc \x05e6\x05d4\x05f4\x05dc "
+       L"\x05e6\x05d4\x0022\x05dc \x05e9\x05dc\x05d5"},
+      {// Arabic
+       "ar", true,
+       L"\x0627\x0644\x0633\x0644\x0627\x0645 "
+       L"\x0639\x0644\x064a\x0643\x0645 "
+       // Farsi/Persian
+       L"\x0647\x0634\x0631\x062d "
+       L"\x0647\x062e\x0648\x0627\x0647 "
+       L"\x062f\x0631\x062f "
+       L"\x0631\x0645\x0627\x0646 "
+       L"\x0633\x0631 "
+       L"\x0646\x0646\x062c\x0633 "
+       L"\x0627\x0644\x062d\x0645\x062f "
+       L"\x062c\x062c\x062c\x062c"},
+      {// Hindi
+       "hi-IN", true, L"\x0930\x093E\x091C\x0927\x093E\x0928"},
+      {// Thai
+       "th-TH", true,
+       L"\x0e2a\x0e27\x0e31\x0e2a\x0e14\x0e35\x0020\x0e04"
+       L"\x0e23\x0e31\x0e1a"},
+      {// Korean
+       "ko-KR", true,
+       L"\x110b\x1161\x11ab\x1102\x1167\x11bc\x1112\x1161"
+       L"\x1109\x1166\x110b\x116d"},
+  });
 
   for (size_t i = 0; i < std::size(kTestCases); ++i) {
     SCOPED_TRACE(base::StringPrintf("kTestCases[%" PRIuS "]: language=%s", i,
@@ -234,37 +218,69 @@
   // numbers and an alphabet of the language, into words. When ASCII numbers are
   // treated as word characters, the split word becomes equal to the dummy word.
   // Otherwise, the split word does not include ASCII numbers.
-  static const struct {
+  struct TestCases {
     const char* language;
     const wchar_t* text;
     bool left_to_right;
-  } kTestCases[] = {
-    {
-      // English
-      "en-US", L"0123456789" L"a", true,
-    }, {
-      // Greek
-      "el-GR", L"0123456789" L"\x03B1", true,
-    }, {
-      // Russian
-      "ru-RU", L"0123456789" L"\x0430", true,
-    }, {
-      // Hebrew
-      "he-IL", L"0123456789" L"\x05D0", false,
-    }, {
-      // Arabic
-      "ar",  L"0123456789" L"\x0627", false,
-    }, {
-      // Hindi
-      "hi-IN", L"0123456789" L"\x0905", true,
-    }, {
-      // Thai
-      "th-TH", L"0123456789" L"\x0e01", true,
-    }, {
-      // Korean
-      "ko-KR", L"0123456789" L"\x1100\x1161", true,
-    },
   };
+  static const auto kTestCases = std::to_array<TestCases>({
+      {
+          // English
+          "en-US",
+          L"0123456789"
+          L"a",
+          true,
+      },
+      {
+          // Greek
+          "el-GR",
+          L"0123456789"
+          L"\x03B1",
+          true,
+      },
+      {
+          // Russian
+          "ru-RU",
+          L"0123456789"
+          L"\x0430",
+          true,
+      },
+      {
+          // Hebrew
+          "he-IL",
+          L"0123456789"
+          L"\x05D0",
+          false,
+      },
+      {
+          // Arabic
+          "ar",
+          L"0123456789"
+          L"\x0627",
+          false,
+      },
+      {
+          // Hindi
+          "hi-IN",
+          L"0123456789"
+          L"\x0905",
+          true,
+      },
+      {
+          // Thai
+          "th-TH",
+          L"0123456789"
+          L"\x0e01",
+          true,
+      },
+      {
+          // Korean
+          "ko-KR",
+          L"0123456789"
+          L"\x1100\x1161",
+          true,
+      },
+  });
 
   for (size_t i = 0; i < std::size(kTestCases); ++i) {
     SCOPED_TRACE(base::StringPrintf("kTestCases[%" PRIuS "]: language=%s", i,
@@ -294,11 +310,12 @@
 // Verify SpellcheckWordIterator treats typographical apostrophe as a part of
 // the word.
 TEST(SpellcheckWordIteratorTest, TypographicalApostropheIsPartOfWord) {
-  static const struct {
+  struct TestCases {
     const char* language;
     const wchar_t* input;
     const wchar_t* expected;
-  } kTestCases[] = {
+  };
+  static const auto kTestCases = std::to_array<TestCases>({
       // Typewriter apostrophe:
       {"en-AU", L"you're", L"you're"},
       {"en-CA", L"you're", L"you're"},
@@ -311,7 +328,7 @@
       {"en-GB", L"you\x2019re", L"you\x2019re"},
       {"en-US", L"you\x2019re", L"you\x2019re"},
       {"en-US", L"....you\x2019re", L"you\x2019re"},
-  };
+  });
 
   for (size_t i = 0; i < std::size(kTestCases); ++i) {
     SpellcheckCharAttribute attributes;
diff --git a/components/strings/components_strings_am.xtb b/components/strings/components_strings_am.xtb
index 4917fb174..dc0352a 100644
--- a/components/strings/components_strings_am.xtb
+++ b/components/strings/components_strings_am.xtb
@@ -4534,6 +4534,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" /> የማይጠቀም ፕሮቶኮል ይጠቀማል።</translation>
 <translation id="918454845714257218">በ<ph name="SIDE_OF_CARD" /> ላይ ያለውን ኮድ ይመልከቱ እና እንደገና ይሞክሩ</translation>
 <translation id="9186203289258525843">Chromeን እንደ ነባሪ የአሳሽ አዝራር ያቀናብሩ፣ Chromeን እንደ የሥርዓቱ ነባር አሳሽ ለማቀናበር ያግብሩ</translation>
+<translation id="9189789270972826888">ካርዱ ካልተሞላ ለመቅዳት እና ለመለጠፍ የካርድ ዝርዝሮችን ከስር ጠቅ ያድርጉ። <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">ከ4 ሳምንታት በላይ የቆዩ ርዕሶች በራስ-ሰር ይሰረዛሉ</translation>
 <translation id="9191834167571392248">ግራ በኩል ከታች ብሳ</translation>
 <translation id="9192361865877479444">ብረት (ድብዳብ)</translation>
diff --git a/components/strings/components_strings_as.xtb b/components/strings/components_strings_as.xtb
index 8978a66..5a2e17a 100644
--- a/components/strings/components_strings_as.xtb
+++ b/components/strings/components_strings_as.xtb
@@ -169,6 +169,7 @@
 <translation id="129553762522093515">শেহতীয়াকৈ বন্ধ কৰা</translation>
 <translation id="1296930489679394997">বিক্ৰী</translation>
 <translation id="1297814096526086484">আপোনাৰ কীব’ৰ্ড আৰু মাউছ লক কৰিবনে?</translation>
+<translation id="1297832388362139384">সেউজীয়া ১</translation>
 <translation id="1301227606947843452">লিগেল এক্সট্ৰা</translation>
 <translation id="1301324364792935241">আপোনাৰ সুৰক্ষিত DNS ছেটিংসমূহ পৰীক্ষা কৰক</translation>
 <translation id="1302418742166945866"><ph name="URL" />এ আপোনাৰ MIDI ডিভাইচ নিয়ন্ত্ৰণ আৰু ৰিপ্ৰ’গ্ৰাম কৰিব বিচাৰে</translation>
@@ -228,6 +229,7 @@
 <translation id="1384725838384960382">সুৰক্ষিত পৰিশোধৰ ক্ৰিডেনশ্বিয়েলৰ বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ শ্বীট</translation>
 <translation id="1386623374109090026">এন’টেশ্বন</translation>
 <translation id="138810468159004008">ছাইটটো চোৱাৰ সময়ত অনুমতি দিয়ক</translation>
+<translation id="139161720020179799">গাঢ় ধোঁৱাবৰণীয়া ১</translation>
 <translation id="1391625539203220400">এই ডিভাইচত IBAN ছেভ কৰিবনে?</translation>
 <translation id="139305205187523129"><ph name="HOST_NAME" />এ কোনো ডেটা পঠিওৱা নাই।</translation>
 <translation id="1393071644879491291">আপুনি চাবলৈ চেষ্টা কৰি থকা ছাইটটোত থকা আক্ৰমণকাৰীসকলে আপোনাক কোনো ছফ্টৱেৰ ইনষ্টল কৰিবলৈ বা আপোনাৰ পাছৱৰ্ড, ফট’ বা ক্ৰেডিট কাৰ্ডৰ নম্বৰৰ দৰে তথ্য ফাদিল কৰিবলৈ ছলনা কৰিব পাৰে। Chromeএ পুনৰ সুৰক্ষা ব্যৱস্থা গ্ৰহণ কৰিবলৈ দৃঢ়ভাৱে চুপাৰিছ কৰে। <ph name="BEGIN_LEARN_MORE_LINK" />এই সকীয়নিৰ বিষয়ে অধিক জানক<ph name="END_LEARN_MORE_LINK" /></translation>
@@ -703,6 +705,7 @@
 <translation id="2227758700723188171">শিক্ষাৰ বাবে দিয়া অনুদান আৰু জলপানি</translation>
 <translation id="2228057197024893428">এই ঠিকনাটো বৰ্তমান Chromeত ছেভ কৰা হয়। এইটো সমগ্ৰ Google প্ৰ’ডাক্টসমূহত ব্যৱহাৰ কৰিবলৈ, ইয়াক আপোনাৰ Google একাউণ্ট <ph name="ACCOUNT" />ত ছেভ কৰক।</translation>
 <translation id="2229456043301340598">অদ্বিতীয় নোহোৱা শ্বৰ্টকাট উপেক্ষা কৰা হৈছে: <ph name="SHORTCUT_NAME" /></translation>
+<translation id="222962001646502673">গাঢ় ধোঁৱাবৰণীয়া ২</translation>
 <translation id="2233041017768270281">{COUNT,plural, =1{১ টা টেব}one{# টা টেব}other{# টা টেব}}</translation>
 <translation id="2233745931693710080">কমপেক্ট ডিস্ক</translation>
 <translation id="2235344399760031203">তৃতীয় পক্ষৰ কুকিসমূহ অৱৰোধ কৰা হৈছে</translation>
@@ -1727,6 +1730,7 @@
 <translation id="4084219288110917128">এনভেল’প C1</translation>
 <translation id="4085326869263783566">মোক লিখাত সহায় কৰক। খুলিবলৈ টেব আৰু এণ্টাৰ টিপক</translation>
 <translation id="4085769736382018559">প্ৰ’ডাক্টৰ তুলনা কৰক</translation>
+<translation id="4085778582400064057">নীলা ২</translation>
 <translation id="4088981014127559358">কাষৰ ১ প্ৰতিচ্ছবি Y শ্বিফ্ট</translation>
 <translation id="4089152113577680600">ট্ৰে’ ১৪</translation>
 <translation id="4092349052316400070">ঠিকনা পূৰাওক</translation>
@@ -1969,6 +1973,7 @@
 <translation id="4509074745930862522"><ph name="TRANSLATE_FOCUSED_FRIENDLY_MATCH_TEXT" />, এই পৃষ্ঠাখন Google Translateৰ জৰিয়তে অনুবাদ কৰিবলৈ প্ৰথমে টেব আৰু তাৰ পাছত এণ্টাৰ টিপক</translation>
 <translation id="4515275063822566619">Chrome আৰু আপোনাৰ Google একাউণ্ট (<ph name="ACCOUNT_EMAIL" />)ৰ কার্ড আৰু ঠিকনাসমূহ। আপুনি সেইবোৰ <ph name="BEGIN_LINK" />ছেটিংসমূহ<ph name="END_LINK" />ত পৰিচালনা কৰক।</translation>
 <translation id="4515847625438516456">মাইক্ৰ’কাৰ আৰু ছাবকম্পেক্ট</translation>
+<translation id="451601984112574365">সেউজীয়া ৩</translation>
 <translation id="4519245469315452746">আপডে’টৰ প্ৰক্ৰিয়াটো চলি থকাৰ সময়ত আপোনাৰ ডিভাইচটো বাধাপ্ৰাপ্ত হৈছে।</translation>
 <translation id="4520048001084013693">এই ফাইলটো ডাউনল’ড কৰাটো প্ৰশাসকৰ নীতিয়ে অৱৰোধ কৰিছে</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> মি.মি. (<ph name="ORIENTATION" />)</translation>
@@ -2177,6 +2182,7 @@
 <translation id="4901952598169637881">কেজুৱেল জোতা</translation>
 <translation id="4905659621780993806">আপোনাৰ প্ৰশাসকে আপোনাৰ ডিভাইচটো <ph name="DATE" />ৰ <ph name="TIME" />ত স্বয়ংক্ৰিয়ভাৱে ৰিষ্টার্ট কৰিব। আপোনাৰ ডিভাইচটো ৰিষ্টার্ট হোৱাৰ পূর্বে যিকোনো খোলা বস্তু ছেভ কৰক।</translation>
 <translation id="4913987521957242411">বাওঁফালে ওপৰৰ অংশত পাঞ্চ কৰক</translation>
+<translation id="4914727764832832057">নীলা ১</translation>
 <translation id="4916389289686916969">টিভিৰ ৰিয়েলিটী শ্ব’</translation>
 <translation id="4917064667437236721">ইমেজিং চিলিণ্ডাৰ</translation>
 <translation id="4918221908152712722"><ph name="APP_NAME" /> ইনষ্টল কৰক (ডাউনল’ড কৰাৰ প্ৰয়োজন নাই)</translation>
@@ -2250,6 +2256,7 @@
 <translation id="5039804452771397117">অনুমতি দিয়ক</translation>
 <translation id="5040262127954254034">গোপনীয়তা</translation>
 <translation id="5043480802608081735">আপুনি প্ৰতিলিপি কৰা লিংক</translation>
+<translation id="5043753287208271200">হালধীয়া ৩</translation>
 <translation id="5045550434625856497">ভুল পাছৱৰ্ড</translation>
 <translation id="5048293684454354469">বিজ্ঞাপনৰ বিষয়বস্তু হৈছে বিজ্ঞাপন ব্যক্তিগতকৰণ কৰিবলৈ ছাইটসমূহে ব্যৱহাৰ কৰিব পৰা বহুতো বস্তুৰ মাজৰ এটা। বিজ্ঞাপনৰ বিষয়বস্তু অবিহনেও ছাইটসমূহে আপোনাক তথাপি বিজ্ঞাপন দেখুৱাব পাৰে, কিন্তু সেয়া কম পৰিমাণে ব্যক্তিগতকৰণ কৰা হ’ব পাৰে। <ph name="BEGIN_LINK" />আপোনাৰ বিজ্ঞাপনৰ গোপনীয়তা পৰিচালনা কৰা<ph name="LINK_END" />ৰ বিষয়ে অধিক জানক।</translation>
 <translation id="5052517576853118371">সক্ৰিয় বিষয়বস্তু</translation>
@@ -2556,6 +2563,7 @@
 <translation id="5593640815048812868">লেপটপ আৰু ন’টবুক</translation>
 <translation id="5595485650161345191">ঠিকনা সম্পাদনা কৰক</translation>
 <translation id="5596939519753369075">২ x ৩.৫ ইঞ্চি</translation>
+<translation id="5597254438174353289">নীলা ৩</translation>
 <translation id="560412284261940334">পৰিচালক প্ৰযোজ্য নহয়</translation>
 <translation id="5605249000617390290">মূল্য ট্ৰেক কৰাৰ বিষয়ে অধিক জানক</translation>
 <translation id="5605670050355397069">লেজাৰ</translation>
@@ -2611,6 +2619,7 @@
 <translation id="5701381305118179107">কেন্দ্ৰ</translation>
 <translation id="5707154300732650394">আপোনাৰ যাত্ৰা পুনৰ আৰম্ভ কৰক</translation>
 <translation id="57094364128775171">জটিল পাছৱৰ্ডৰ পৰামৰ্শ দিয়ক…</translation>
+<translation id="570953204696852961">ৰঙা ৩</translation>
 <translation id="571403275720188526">(arm64)</translation>
 <translation id="571510845185711675">পশু চিকিৎসা</translation>
 <translation id="5715150588940290235">ছেভ কৰি ৰখা সুৰক্ষা ক'ড মচিবনে?</translation>
@@ -2811,6 +2820,7 @@
 <translation id="6085149458302186532">লেবেল (ৰঙীন)</translation>
 <translation id="6087312102907839798">সম্বন্ধীয় সন্ধানসমুহ</translation>
 <translation id="6089505343295765444">আপোনাৰ Chromeৰ ইতিহাসৰ পৰা আপুনি মচা টেবসমূহ তথাপি আপোনাৰ তুলনাৰ তালিকাত দেখা যাব</translation>
+<translation id="6093599771645355227">হালধীয়া ১</translation>
 <translation id="6093795393556121384">আপোনাৰ কাৰ্ডখন সত্যাপন কৰা হৈছে</translation>
 <translation id="6094273045989040137">এন'টেট</translation>
 <translation id="6094290315941448991">প্ৰশাসকৰ নীতিয়ে গোপনীয় সমল দৃশ্যমান হৈ থাকোঁতে স্ক্ৰীন ৰেকৰ্ডিং অক্ষম কৰে</translation>
@@ -3348,6 +3358,7 @@
 <translation id="7058774143982824355">CSV পাছৱৰ্ড পাৰ্ছাৰ সেৱা</translation>
 <translation id="7062635574500127092">গাঢ় সেউজ-নীলা</translation>
 <translation id="706295145388601875">Chromeৰ ছেটিঙত ঠিকনা যোগ দিয়ক আৰু পৰিচালনা কৰক</translation>
+<translation id="7063157783216323487">সেউজীয়া ২</translation>
 <translation id="7064443976734085921">কমপেক্ট গাড়ী</translation>
 <translation id="7064851114919012435">যোগাযোগৰ তথ্য</translation>
 <translation id="7067633076996245366">Soul &amp; R&amp;B</translation>
@@ -3899,6 +3910,7 @@
 <translation id="8028698320761417183"><ph name="CREATE_GOOGLE_FORM_FOCUSED_FRIENDLY_MATCH_TEXT" />, Google Formsত ক্ষিপ্ৰভাৱে এখন নতুন ফ’ৰ্ম সৃষ্টি কৰিবলৈ প্ৰথমে টেব আৰু তাৰ পাছত এণ্টাৰ টিপক</translation>
 <translation id="8028892419725165118">অনানুষ্ঠানিক গে’ম</translation>
 <translation id="8028960012888758725">কামৰ পাছত ট্ৰিম কৰক</translation>
+<translation id="8029829038322015001">ৰঙা ১</translation>
 <translation id="8030729864112325446">বৃত্তি সম্পৰ্কীয় শিক্ষা আৰু শিক্ষা অব্যাহত ৰখা</translation>
 <translation id="8032546467100845887">স্বচ্ছতা</translation>
 <translation id="8035152190676905274">পেন</translation>
@@ -3906,6 +3918,7 @@
 <translation id="8037117624646282037">যিয়ে শেহতীয়াকৈ ডিভাইচটো ব্যৱহাৰ কৰিছে</translation>
 <translation id="8037357227543935929">সোধক (ডিফ'ল্ট)</translation>
 <translation id="803771048473350947">ফাইল</translation>
+<translation id="8038182528865038593">ৰঙা ২</translation>
 <translation id="8041089156583427627">মতামত পঠিয়াওক</translation>
 <translation id="8041940743680923270">গ্ল’বেল ডিফ’ল্ট ব্যৱহাৰ কৰক (সোধক)</translation>
 <translation id="8043255123207491407">বিক্ৰেতাৰ নিয়ম আৰু চৰ্তাৱলী চাওক</translation>
@@ -4304,6 +4317,8 @@
 <translation id="8767765348545497220">সহায়ৰ বাবল বন্ধ কৰক</translation>
 <translation id="8767881944435256294">{COUNT,plural, =1{১ টা পৰিশোধ পদ্ধতি}one{# টা পৰিশোধ পদ্ধতি}other{# টা পৰিশোধ পদ্ধতি}}</translation>
 <translation id="8768225988514678921">উপস্থাপন সৃষ্টি কৰাৰ বুটাম, Slidesত এটা নতুন Google উপস্থাপন ক্ষিপ্ৰতাৰে সৃষ্টি কৰিবলৈ সক্ৰিয় কৰক</translation>
+<translation id="8769662576926275897">কাৰ্ডৰ সবিশেষ</translation>
+<translation id="8769858749286369844">টেন ২</translation>
 <translation id="8770286973007342895">লনৰ ঘাঁহ কটা যন্ত্ৰ</translation>
 <translation id="8772387130037509473">যোগাসন আৰু পিলাটিজ</translation>
 <translation id="877348612833018844">{0,plural, =1{গোপনীয় ফাইলটো স্থানান্তৰ কৰিবনে?}one{গোপনীয় ফাইলসমূহ স্থানান্তৰ কৰিবনে?}other{গোপনীয় ফাইলসমূহ স্থানান্তৰ কৰিবনে?}}</translation>
@@ -4395,6 +4410,7 @@
 <translation id="8956124158020778855">আপুনি এই ছেটিংটো অন কৰাৰ পাছত, লিখিবলৈ আৰম্ভ কৰাৰ বাবে এই টেবটোলৈ উভতি আহক।</translation>
 <translation id="8957210676456822347">কেপটিভ পর্টেল বিশ্বাসযোগ্যতাৰ প্ৰমাণীকৰণ</translation>
 <translation id="8959282183248574156"><ph name="NICKNAME_COUNT" />/<ph name="NICKNAME_MAX" /></translation>
+<translation id="8959288490306482616">টেন ৩</translation>
 <translation id="8963117664422609631">ছাইটৰ ছেটিঙলৈ যাওক</translation>
 <translation id="8963213021028234748"><ph name="MARKUP_1" />পৰামৰ্শ:<ph name="MARKUP_2" />আপোনাৰ এটা ডেটা সংযোগ থকাটো নিশ্চিত কৰক<ph name="MARKUP_3" />এই ৱেবপে‘জটো পাছত ৰিল‘ড কৰক<ph name="MARKUP_4" />আপুনি দিয়া ঠিকনাটো পৰীক্ষা কৰক<ph name="MARKUP_5" /></translation>
 <translation id="8968766641738584599">কার্ড ছেভ কৰক</translation>
@@ -4457,6 +4473,7 @@
 <translation id="90695670378604968">প্লাষ্টিক (মেট)</translation>
 <translation id="9069693763241529744">এটা এক্সটেনশ্বনে অৱৰোধ কৰিছে</translation>
 <translation id="9073799351042754113">আপুনি এই ছাইটটোৰ বাবে সুৰক্ষা সকীয়নি অফ কৰিবলৈ বাছনি কৰিছে।</translation>
+<translation id="9075717835386447447">টেন ১</translation>
 <translation id="9076283476770535406">ইয়াত প্ৰাপ্তবয়স্কৰ সমল থাকিব পাৰে</translation>
 <translation id="9078912659001679888">ব্লেণ্ডাৰ আৰু জুচাৰ</translation>
 <translation id="9078964945751709336">অধিক তথ্য আৱশ্যক</translation>
@@ -4527,6 +4544,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" />এ এটা অসমর্থিত প্ৰ'ট'কল ব্যৱহাৰ কৰে।</translation>
 <translation id="918454845714257218"><ph name="SIDE_OF_CARD" />ত থকা ক’ডটো পৰীক্ষা কৰি পুনৰ চেষ্টা কৰক</translation>
 <translation id="9186203289258525843">Chromeক ডিফ’ল্ট ব্ৰাউজাৰ হিচাপে ছেট কৰাৰ বুটাম, Chromeক ছিষ্টেমৰ ডিফ’ল্ট ব্ৰাউজাৰ হিচাপে ছেট কৰিবলৈ সক্ৰিয় কৰক</translation>
+<translation id="9189789270972826888">যদি কাৰ্ডখন পূৰ কৰা হোৱা নাই, প্ৰতিলিপি কৰি পে’ষ্ট কৰিবলৈ তলত থকা কাৰ্ডৰ সবিশেষত ক্লিক কৰক। <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">৪ সপ্তাহতকৈ পুৰণি বিষয়বস্তু স্বয়ংক্ৰিয়ভাৱে মচা হয়</translation>
 <translation id="9191834167571392248">বাওঁফালে তলৰ অংশত পাঞ্চ কৰক</translation>
 <translation id="9192361865877479444">মেটেল (Matte)</translation>
@@ -4565,6 +4583,7 @@
 <translation id="949314938206378263">আপোনাক এই ছাইটটোলৈ যাবলৈ কোৱা হৈছে। আপোনাৰ অভিভাৱকে Family Linkত প্ৰত্যুত্তৰ দিব পাৰে।</translation>
 <translation id="950736567201356821">ওপৰৰ অংশত তিনিবাৰ পাঞ্চ কৰা</translation>
 <translation id="950926967802086924">পাছকী • Google Password Manager</translation>
+<translation id="95721182352849470">হালধীয়া ২</translation>
 <translation id="961663415146723894">তলৰ অংশত সংযুক্ত কৰক</translation>
 <translation id="961856697154696964">ব্ৰাউজিঙৰ ডেটা মচক</translation>
 <translation id="961930410699694996">এইবাৰ অৱস্থান ব্যৱহাৰৰ অনুমতি দিয়া হৈছে</translation>
diff --git a/components/strings/components_strings_az.xtb b/components/strings/components_strings_az.xtb
index 3c2aadb..40a5d751 100644
--- a/components/strings/components_strings_az.xtb
+++ b/components/strings/components_strings_az.xtb
@@ -4529,6 +4529,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" /> dəstəklənməyən protokol istifadə edir.</translation>
 <translation id="918454845714257218"><ph name="SIDE_OF_CARD" /> tərəfində kodu yoxlayıb yenidən cəhd edin</translation>
 <translation id="9186203289258525843">"Chrome-u defolt brauzer kimi ayarlayın" düyməsi, aktivləşdirərək Chrome-u sistemin defolt brauzeri kimi ayarlayın</translation>
+<translation id="9189789270972826888">Kart doldurulmayıbsa, kopiyalayıb yerləşdirmək üçün aşağıdakı kart detallarına klikləyin. <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">4 həftədən əvvələ aid mövzular avtomatik silinir</translation>
 <translation id="9191834167571392248">Aşağı soldan deşik açın</translation>
 <translation id="9192361865877479444">Metal (mat)</translation>
diff --git a/components/strings/components_strings_ca.xtb b/components/strings/components_strings_ca.xtb
index 52142a5c..a308d55 100644
--- a/components/strings/components_strings_ca.xtb
+++ b/components/strings/components_strings_ca.xtb
@@ -4533,6 +4533,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" /> fa servir un protocol no admès.</translation>
 <translation id="918454845714257218">Comprova el codi que hi ha <ph name="SIDE_OF_CARD" /> i torna-ho a provar</translation>
 <translation id="9186203289258525843">Botó Estableix Chrome com a navegador predeterminat: activa'l per establir Chrome com a navegador predeterminat del sistema</translation>
+<translation id="9189789270972826888">Fes clic als detalls de la targeta que hi ha a continuació per copiar-los i enganxar-los si la targeta no s'ha emplenat. <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">Els temes que tinguin més de 4 setmanes d'antiguitat se suprimiran automàticament</translation>
 <translation id="9191834167571392248">Encunyació a la part inferior esquerra</translation>
 <translation id="9192361865877479444">Metall (mat)</translation>
diff --git a/components/strings/components_strings_da.xtb b/components/strings/components_strings_da.xtb
index 9cf6554..3b1b29a2 100644
--- a/components/strings/components_strings_da.xtb
+++ b/components/strings/components_strings_da.xtb
@@ -4535,6 +4535,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" /> anvender en ikke-understøttet protokol.</translation>
 <translation id="918454845714257218">Tjek koden på <ph name="SIDE_OF_CARD" />, og prøv igen</translation>
 <translation id="9186203289258525843">Knappen Angiv Chrome som standardbrowser, aktivér for at angive Chrome som systemets standardbrowser</translation>
+<translation id="9189789270972826888">Klik på kortoplysningerne nedenfor for at kopiere og indsætte, hvis kortet ikke blev udfyldt. <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">Emner, der er mere end 4 uger gamle, slettes automatisk</translation>
 <translation id="9191834167571392248">Hul nederst til venstre</translation>
 <translation id="9192361865877479444">Metal (mat)</translation>
diff --git a/components/strings/components_strings_el.xtb b/components/strings/components_strings_el.xtb
index 1010cba..5ccbd40 100644
--- a/components/strings/components_strings_el.xtb
+++ b/components/strings/components_strings_el.xtb
@@ -169,6 +169,7 @@
 <translation id="129553762522093515">Έκλεισαν πρόσφατα</translation>
 <translation id="1296930489679394997">Πωλήσεις</translation>
 <translation id="1297814096526086484">Να κλειδωθεί το πληκτρολόγιο και το ποντίκι;</translation>
+<translation id="1297832388362139384">Πράσινο 1</translation>
 <translation id="1301227606947843452">Legal Extra</translation>
 <translation id="1301324364792935241">Ελέγξτε τις ρυθμίσεις ασφαλούς DNS</translation>
 <translation id="1302418742166945866">Το <ph name="URL" /> θέλει να ελέγχει και να επαναπρογραμματίζει τις συσκευές MIDI</translation>
@@ -228,6 +229,7 @@
 <translation id="1384725838384960382">Φύλλο ελέγχου ταυτότητας διαπιστευτηρίων για ασφαλείς πληρωμές</translation>
 <translation id="1386623374109090026">Σχολιασμοί</translation>
 <translation id="138810468159004008">Να επιτρέπεται κατά την επίσκεψη στον ιστότοπο</translation>
+<translation id="139161720020179799">Σκούρο γκρι 1</translation>
 <translation id="1391625539203220400">Αποθήκευση IBAN σε αυτήν τη συσκευή;</translation>
 <translation id="139305205187523129">Ο κεντρικός υπολογιστής <ph name="HOST_NAME" /> δεν έστειλε δεδομένα.</translation>
 <translation id="1393071644879491291">Οι υπεύθυνοι επίθεσης στον ιστότοπο που προσπαθήσατε να επισκεφτείτε ενδέχεται να σας ξεγελάσουν, για να εγκαταστήσετε λογισμικό ή να αποκαλύψετε στοιχεία, όπως τους κωδικούς πρόσβασης, τον αριθμό τηλεφώνου ή τους αριθμούς των πιστωτικών καρτών σας. Το Chrome συνιστά να επιστρέψετε σε έναν ασφαλή ιστότοπο. <ph name="BEGIN_LEARN_MORE_LINK" />Μάθετε περισσότερα σχετικά με αυτή την ειδοποίηση<ph name="END_LEARN_MORE_LINK" /></translation>
@@ -703,6 +705,7 @@
 <translation id="2227758700723188171">Υποτροφίες σπουδών</translation>
 <translation id="2228057197024893428">Αυτή η διεύθυνση είναι αποθηκευμένη στο Chrome. Για να τη χρησιμοποιήσετε σε όλα τα προϊόντα Google, αποθηκεύστε τη στον Λογαριασμό σας Google, <ph name="ACCOUNT" />.</translation>
 <translation id="2229456043301340598">Παραβλέφθηκε η μη μοναδική συντόμευση: <ph name="SHORTCUT_NAME" /></translation>
+<translation id="222962001646502673">Σκούρο γκρι 2</translation>
 <translation id="2233041017768270281">{COUNT,plural, =1{1 καρτέλα}other{# καρτέλες}}</translation>
 <translation id="2233745931693710080">Compact Disc (CD)</translation>
 <translation id="2235344399760031203">Τα cookie τρίτου μέρους αποκλείστηκαν.</translation>
@@ -1730,6 +1733,7 @@
 <translation id="4084219288110917128">Φάκελος C1</translation>
 <translation id="4085326869263783566">Βοήθησέ με να γράψω. Πατήστε Tab και έπειτα Enter για άνοιγμα</translation>
 <translation id="4085769736382018559">Σύγκριση προϊόντων</translation>
+<translation id="4085778582400064057">Μπλε 2</translation>
 <translation id="4088981014127559358">Πλευρά 1 μετατόπιση εικόνας στον άξονα Y</translation>
 <translation id="4089152113577680600">Τροφοδότης χαρτιού 14</translation>
 <translation id="4092349052316400070">Συμπλήρωση διεύθυνσης</translation>
@@ -1974,6 +1978,7 @@
 <translation id="4509074745930862522"><ph name="TRANSLATE_FOCUSED_FRIENDLY_MATCH_TEXT" />, πατήστε Tab και έπειτα Enter για μετάφραση αυτής της σελίδας με τη Μετάφραση Google.</translation>
 <translation id="4515275063822566619">Οι κάρτες και οι διευθύνσεις προέρχονται από το Chrome και τον Λογαριασμό σας Google (<ph name="ACCOUNT_EMAIL" />). Μπορείτε να τις διαχειριστείτε στις <ph name="BEGIN_LINK" />Ρυθμίσεις<ph name="END_LINK" />.</translation>
 <translation id="4515847625438516456">Αυτοκίνητα μίνι και πόλης</translation>
+<translation id="451601984112574365">Πράσινο 3</translation>
 <translation id="4519245469315452746">Η συσκευή διακόπηκε κατά τη διάρκεια της διαδικασίας ενημέρωσης.</translation>
 <translation id="4520048001084013693">Η λήψη αυτού του αρχείου έχει αποκλειστεί από την πολιτική διαχειριστή</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> χιλ. (<ph name="ORIENTATION" />)</translation>
@@ -2182,6 +2187,7 @@
 <translation id="4901952598169637881">Υποδήματα για καθημερινή χρήση</translation>
 <translation id="4905659621780993806">Ο διαχειριστής σας θα επανεκκινήσει τη συσκευή σας αυτόματα στις <ph name="TIME" /> στις <ph name="DATE" />. Αποθηκεύστε τυχόν ανοιχτά στοιχεία πριν από την επανεκκίνηση της συσκευής σας.</translation>
 <translation id="4913987521957242411">Τρύπημα επάνω αριστερά</translation>
+<translation id="4914727764832832057">Μπλε 1</translation>
 <translation id="4916389289686916969">Τηλεοπτικές εκπομπές ριάλιτι</translation>
 <translation id="4917064667437236721">Κύλινδρος απεικόνισης</translation>
 <translation id="4918221908152712722">Εγκατάσταση εφαρμογής <ph name="APP_NAME" /> (δεν απαιτείται λήψη)</translation>
@@ -2255,6 +2261,7 @@
 <translation id="5039804452771397117">Επιτρέπεται</translation>
 <translation id="5040262127954254034">Απόρρητο</translation>
 <translation id="5043480802608081735">Σύνδεσμος που αντιγράψατε</translation>
+<translation id="5043753287208271200">Κίτρινο 3</translation>
 <translation id="5045550434625856497">Λανθασμένος κωδικός πρόσβασης</translation>
 <translation id="5048293684454354469">Τα θέματα διαφημίσεων είναι μόνο ένα από τα πολλά πράγματα που μπορεί να χρησιμοποιήσει ένας ιστότοπος για την εξατομίκευση των διαφημίσεων. Ακόμη και χωρίς τα θέματα διαφημίσεων, οι ιστότοποι μπορούν να συνεχίσουν να εμφανίζουν διαφημίσεις, αλλά ενδέχεται να είναι λιγότερο εξατομικευμένες. Μάθετε περισσότερα σχετικά με τη <ph name="BEGIN_LINK" />διαχείριση του απορρήτου διαφημίσεων<ph name="LINK_END" />.</translation>
 <translation id="5052517576853118371">Ενεργά θέματα</translation>
@@ -2562,6 +2569,7 @@
 <translation id="5593640815048812868">Φορητοί υπολογιστές και notebook</translation>
 <translation id="5595485650161345191">Επεξεργασία διεύθυνσης</translation>
 <translation id="5596939519753369075">2 x 3,5 ίντσες</translation>
+<translation id="5597254438174353289">Μπλε 3</translation>
 <translation id="560412284261940334">Η διαχείριση δεν υποστηρίζεται</translation>
 <translation id="5605249000617390290">Μάθετε περισσότερα σχετικά με την παρακολούθηση τιμής</translation>
 <translation id="5605670050355397069">Ledger</translation>
@@ -2617,6 +2625,7 @@
 <translation id="5701381305118179107">Κέντρο</translation>
 <translation id="5707154300732650394">Συνέχιση της διαδρομής σας</translation>
 <translation id="57094364128775171">Πρόταση για ισχυρό κωδικό πρόσβασης…</translation>
+<translation id="570953204696852961">Κόκκινο 3</translation>
 <translation id="571403275720188526">(arm64)</translation>
 <translation id="571510845185711675">Κτηνίατροι</translation>
 <translation id="5715150588940290235">Διαγραφή αποθηκευμένων κωδικών ασφαλείας;</translation>
@@ -2817,6 +2826,7 @@
 <translation id="6085149458302186532">Ετικέτες (Έγχρωμες)</translation>
 <translation id="6087312102907839798">Συναφείς αναζητήσεις</translation>
 <translation id="6089505343295765444">Οι καρτέλες που διαγράφετε από το Ιστορικό Chrome θα εξακολουθούν να εμφανίζονται στους πίνακες σύγκρισης</translation>
+<translation id="6093599771645355227">Κίτρινο 1</translation>
 <translation id="6093795393556121384">Η κάρτα σας επαληθεύτηκε</translation>
 <translation id="6094273045989040137">Σχολιασμός</translation>
 <translation id="6094290315941448991">Η πολιτική διαχειριστή απενεργοποιεί την εγγραφή οθόνης όταν είναι ορατό εμπιστευτικό περιεχόμενο.</translation>
@@ -3355,6 +3365,7 @@
 <translation id="7058774143982824355">Υπηρεσία ανάλυσης κωδικού πρόσβασης CSV</translation>
 <translation id="7062635574500127092">Γαλαζοπράσινο</translation>
 <translation id="706295145388601875">Προσθήκη και διαχείριση διευθύνσεων από τις ρυθμίσεις του Chrome</translation>
+<translation id="7063157783216323487">Πράσινο 2</translation>
 <translation id="7064443976734085921">Μικρά αυτοκίνητα</translation>
 <translation id="7064851114919012435">Στοιχεία επικοινωνίας</translation>
 <translation id="7067633076996245366">Μουσική soul και R&amp;B</translation>
@@ -3907,6 +3918,7 @@
 <translation id="8028698320761417183"><ph name="CREATE_GOOGLE_FORM_FOCUSED_FRIENDLY_MATCH_TEXT" />, πατήστε το πλήκτρο Tab και έπειτα το πλήκτρο Enter για να δημιουργήσετε γρήγορα μια νέα φόρμα στις Φόρμες Google</translation>
 <translation id="8028892419725165118">Παιχνίδια casual</translation>
 <translation id="8028960012888758725">Περικοπή μετά την εργασία</translation>
+<translation id="8029829038322015001">Κόκκινο 1</translation>
 <translation id="8030729864112325446">Τεχνική και δια βίου εκπαίδευση</translation>
 <translation id="8032546467100845887">Διαφάνεια</translation>
 <translation id="8035152190676905274">Πένα</translation>
@@ -3914,6 +3926,7 @@
 <translation id="8037117624646282037">Ποιοι χρησιμοποίησαν πρόσφατα τη συσκευή</translation>
 <translation id="8037357227543935929">Να γίνεται ερώτηση (προεπιλογή)</translation>
 <translation id="803771048473350947">Αρχείο</translation>
+<translation id="8038182528865038593">Κόκκινο 2</translation>
 <translation id="8041089156583427627">Αποστολή σχολίων</translation>
 <translation id="8041940743680923270">Χρήση καθολικής προεπιλεγμένης ρύθμισης (Ερώτηση)</translation>
 <translation id="8043255123207491407">Δείτε τους όρους και τις προϋποθέσεις του πωλητή</translation>
@@ -4314,6 +4327,7 @@
 <translation id="8767881944435256294">{COUNT,plural, =1{1 τρόπος πληρωμής}other{# τρόποι πληρωμής}}</translation>
 <translation id="8768225988514678921">Κουμπί Δημιουργία παρουσίασης, ενεργοποιήστε το για να δημιουργήσετε γρήγορα μια νέα παρουσίαση Google στις Παρουσιάσεις</translation>
 <translation id="8769662576926275897">Στοιχεία κάρτας</translation>
+<translation id="8769858749286369844">Ανοιχτό καφέ 2</translation>
 <translation id="8770286973007342895">Χλοοκοπτικές μηχανές</translation>
 <translation id="8772387130037509473">Γιόγκα και πιλάτες</translation>
 <translation id="877348612833018844">{0,plural, =1{Μετακίνηση εμπιστευτικού αρχείου;}other{Μετακίνηση εμπιστευτικών αρχείων;}}</translation>
@@ -4405,6 +4419,7 @@
 <translation id="8956124158020778855">Αφού ενεργοποιήσετε αυτή τη ρύθμιση, επιστρέψτε σε αυτή την καρτέλα για να ξεκινήσετε να γράφετε.</translation>
 <translation id="8957210676456822347">Εξουσιοδότηση πύλης υποδοχής</translation>
 <translation id="8959282183248574156"><ph name="NICKNAME_COUNT" />/<ph name="NICKNAME_MAX" /></translation>
+<translation id="8959288490306482616">Ανοιχτό καφέ 3</translation>
 <translation id="8963117664422609631">Μετάβαση στις ρυθμίσεις ιστοτόπου</translation>
 <translation id="8963213021028234748"><ph name="MARKUP_1" />Προτάσεις:<ph name="MARKUP_2" />Βεβαιωθείτε ότι έχετε μια σύνδεση δεδομένων<ph name="MARKUP_3" />Επαναλάβετε τη φόρτωση αυτής της ιστοσελίδας αργότερα<ph name="MARKUP_4" />Ελέγξτε τη διεύθυνση που έχετε εισαγάγει<ph name="MARKUP_5" /></translation>
 <translation id="8968766641738584599">Αποθήκευση κάρτας</translation>
@@ -4467,6 +4482,7 @@
 <translation id="90695670378604968">Πλαστικό (Ματ)</translation>
 <translation id="9069693763241529744">Αποκλείστηκε από μια επέκταση</translation>
 <translation id="9073799351042754113">Έχετε επιλέξει να απενεργοποιήσετε τις ειδοποιήσεις ασφάλειας για αυτόν τον ιστότοπο.</translation>
+<translation id="9075717835386447447">Ανοιχτό καφέ 1</translation>
 <translation id="9076283476770535406">Μπορεί να διαθέτει περιεχόμενο για ενηλίκους</translation>
 <translation id="9078912659001679888">Μπλέντερ και αποχυμωτές</translation>
 <translation id="9078964945751709336">Απαιτούνται περισσότερες πληροφορίες</translation>
@@ -4575,6 +4591,7 @@
 <translation id="949314938206378263">Ζήτησες να επισκεφτείς αυτόν τον ιστότοπο. Ο γονέας σου μπορεί να απαντήσει σε αυτό το αίτημα στο Family Link.</translation>
 <translation id="950736567201356821">Τριπλό τρύπημα στο επάνω μέρος</translation>
 <translation id="950926967802086924">Κλειδί πρόσβασης • Διαχείριση κωδικών πρόσβασης Google</translation>
+<translation id="95721182352849470">Κίτρινο 2</translation>
 <translation id="961663415146723894">Δέσιμο στο κάτω μέρος</translation>
 <translation id="961856697154696964">Διαγραφή δεδομένων περιήγησης</translation>
 <translation id="961930410699694996">Επιτράπηκε η χρήση της τοποθεσίας για αυτήν τη φορά</translation>
diff --git a/components/strings/components_strings_en-GB.xtb b/components/strings/components_strings_en-GB.xtb
index 24f26cd..7ec8433d 100644
--- a/components/strings/components_strings_en-GB.xtb
+++ b/components/strings/components_strings_en-GB.xtb
@@ -4534,6 +4534,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" /> uses an unsupported protocol.</translation>
 <translation id="918454845714257218">Check the code on the <ph name="SIDE_OF_CARD" /> and try again</translation>
 <translation id="9186203289258525843">Set Chrome as default browser button, activate to set Chrome as the system's default browser</translation>
+<translation id="9189789270972826888">Click card details below to copy and paste if the card wasn't filled. <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">Topics older than four weeks get auto-deleted</translation>
 <translation id="9191834167571392248">Punch bottom left</translation>
 <translation id="9192361865877479444">Metal (matte)</translation>
diff --git a/components/strings/components_strings_es-419.xtb b/components/strings/components_strings_es-419.xtb
index 2f405291..98d7654 100644
--- a/components/strings/components_strings_es-419.xtb
+++ b/components/strings/components_strings_es-419.xtb
@@ -169,6 +169,7 @@
 <translation id="129553762522093515">Cerrado recientemente</translation>
 <translation id="1296930489679394997">Ofertas</translation>
 <translation id="1297814096526086484">¿Quieres bloquear el teclado y el mouse?</translation>
+<translation id="1297832388362139384">Verde 1</translation>
 <translation id="1301227606947843452">Legal extra</translation>
 <translation id="1301324364792935241">Revisa la configuración de DNS seguro</translation>
 <translation id="1302418742166945866"><ph name="URL" /> quiere controlar y reprogramar tus dispositivos MIDI</translation>
@@ -228,6 +229,7 @@
 <translation id="1384725838384960382">Hoja de autenticación de credenciales de pago seguro</translation>
 <translation id="1386623374109090026">Anotaciones</translation>
 <translation id="138810468159004008">Permitir mientras visitas el sitio</translation>
+<translation id="139161720020179799">Gris oscuro 1</translation>
 <translation id="1391625539203220400">¿Quieres guardar el IBAN en este dispositivo?</translation>
 <translation id="139305205187523129"><ph name="HOST_NAME" /> no envió ningún dato.</translation>
 <translation id="1393071644879491291">Los atacantes del sitio que intentaste visitar podrían engañarte para que instales software o reveles información como tus contraseñas, teléfono o números de tarjeta de crédito. Chrome recomienda que regreses a un sitio seguro. <ph name="BEGIN_LEARN_MORE_LINK" />Más información sobre esta advertencia<ph name="END_LEARN_MORE_LINK" /></translation>
@@ -703,6 +705,7 @@
 <translation id="2227758700723188171">Subvenciones y becas para estudiantes</translation>
 <translation id="2228057197024893428">Actualmente, esta dirección se guarda en Chrome. Para usarla en todos los productos de Google, guárdala en tu Cuenta de Google, <ph name="ACCOUNT" />.</translation>
 <translation id="2229456043301340598">Se ignoró el atajo duplicado: <ph name="SHORTCUT_NAME" /></translation>
+<translation id="222962001646502673">Gris oscuro 2</translation>
 <translation id="2233041017768270281">{COUNT,plural, =1{1 pestaña}other{# pestañas}}</translation>
 <translation id="2233745931693710080">Disco compacto</translation>
 <translation id="2235344399760031203">Se bloquearon las cookies de terceros</translation>
@@ -1731,6 +1734,7 @@
 <translation id="4084219288110917128">Sobre C1</translation>
 <translation id="4085326869263783566">Ayúdame a escribir. Presionar Tab y presionar Intro para abrir</translation>
 <translation id="4085769736382018559">Comparar productos</translation>
+<translation id="4085778582400064057">Azul 2</translation>
 <translation id="4088981014127559358">Cambio en el eje Y del lado 1 de la imagen</translation>
 <translation id="4089152113577680600">Bandeja 14</translation>
 <translation id="4092349052316400070">Elige una dirección</translation>
@@ -1974,6 +1978,7 @@
 <translation id="4509074745930862522"><ph name="TRANSLATE_FOCUSED_FRIENDLY_MATCH_TEXT" />: presiona Tab y, luego, Intro para traducir esta página con Google Traductor</translation>
 <translation id="4515275063822566619">Las tarjetas y direcciones provienen de Chrome y de tu cuenta de Google (<ph name="ACCOUNT_EMAIL" />). Puedes administrar esta información en <ph name="BEGIN_LINK" />Configuración<ph name="END_LINK" />.</translation>
 <translation id="4515847625438516456">Microautos y subcompactos</translation>
+<translation id="451601984112574365">Verde 3</translation>
 <translation id="4519245469315452746">Tu dispositivo se interrumpió durante el proceso de actualización.</translation>
 <translation id="4520048001084013693">La política del administrador no permite descargar este archivo</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> mm (<ph name="ORIENTATION" />)</translation>
@@ -2182,6 +2187,7 @@
 <translation id="4901952598169637881">Calzado informal</translation>
 <translation id="4905659621780993806">El administrador reiniciará el dispositivo el <ph name="DATE" /> a las <ph name="TIME" />. Guarda los elementos abiertos antes de reiniciar el dispositivo.</translation>
 <translation id="4913987521957242411">Perforación en la esquina superior izquierda</translation>
+<translation id="4914727764832832057">Azul 1</translation>
 <translation id="4916389289686916969">Reality shows de TV</translation>
 <translation id="4917064667437236721">Cilindro de impresión</translation>
 <translation id="4918221908152712722">Instala <ph name="APP_NAME" /> (no es necesario que descargues la app)</translation>
@@ -2255,6 +2261,7 @@
 <translation id="5039804452771397117">Permitir</translation>
 <translation id="5040262127954254034">Privacidad</translation>
 <translation id="5043480802608081735">Vínculo que copiaste</translation>
+<translation id="5043753287208271200">Amarillo 3</translation>
 <translation id="5045550434625856497">Contraseña incorrecta</translation>
 <translation id="5048293684454354469">Los temas de anuncios son solo una de las muchas opciones que un sitio puede usar para personalizar los anuncios. Incluso sin estos temas, los sitios pueden seguir mostrándote anuncios, pero es posible que estén menos personalizados. Obtén más información para <ph name="BEGIN_LINK" />administrar tu privacidad en los anuncios<ph name="LINK_END" />.</translation>
 <translation id="5052517576853118371">Temas activos</translation>
@@ -2561,6 +2568,7 @@
 <translation id="5593640815048812868">Computadoras portátiles</translation>
 <translation id="5595485650161345191">Editar dirección</translation>
 <translation id="5596939519753369075">5.1 × 8.9 cm (2 × 3.5 in)</translation>
+<translation id="5597254438174353289">Azul 3</translation>
 <translation id="560412284261940334">No se admite la administración.</translation>
 <translation id="5605249000617390290">Más información sobre el seguimiento de precios</translation>
 <translation id="5605670050355397069">Ledger</translation>
@@ -2616,6 +2624,7 @@
 <translation id="5701381305118179107">Centrar</translation>
 <translation id="5707154300732650394">Reanudar tu exploración</translation>
 <translation id="57094364128775171">Sugerir contraseña segura…</translation>
+<translation id="570953204696852961">Rojo 3</translation>
 <translation id="571403275720188526">(arm64)</translation>
 <translation id="571510845185711675">Veterinarios</translation>
 <translation id="5715150588940290235">¿Quieres borrar los códigos de seguridad guardados?</translation>
@@ -2816,6 +2825,7 @@
 <translation id="6085149458302186532">Etiquetas (de color)</translation>
 <translation id="6087312102907839798">Búsquedas relacionadas</translation>
 <translation id="6089505343295765444">Las pestañas que borres de tu historial de Chrome seguirán apareciendo en tus tablas de comparación</translation>
+<translation id="6093599771645355227">Amarillo 1</translation>
 <translation id="6093795393556121384">Se verificó tu tarjeta.</translation>
 <translation id="6094273045989040137">Agregar anotación</translation>
 <translation id="6094290315941448991">La política del administrador inhabilita la grabación de pantalla cuando hay contenido confidencial a la vista.</translation>
@@ -3354,6 +3364,7 @@
 <translation id="7058774143982824355">Servicio del analizador de contraseñas CSV</translation>
 <translation id="7062635574500127092">Verde azulado</translation>
 <translation id="706295145388601875">Agrega y administra direcciones en la configuración de Chrome</translation>
+<translation id="7063157783216323487">Verde 2</translation>
 <translation id="7064443976734085921">Vehículos compactos</translation>
 <translation id="7064851114919012435">Información de contacto</translation>
 <translation id="7067633076996245366">Soul y R&amp;B</translation>
@@ -3906,6 +3917,7 @@
 <translation id="8028698320761417183"><ph name="CREATE_GOOGLE_FORM_FOCUSED_FRIENDLY_MATCH_TEXT" />, presiona Tab y, luego, Intro para crear un formulario nuevo en Formularios de Google rápidamente</translation>
 <translation id="8028892419725165118">Juegos casuales</translation>
 <translation id="8028960012888758725">Cortar al finalizar el trabajo</translation>
+<translation id="8029829038322015001">Rojo 1</translation>
 <translation id="8030729864112325446">Enseñanza profesional y formación continua</translation>
 <translation id="8032546467100845887">Transparencia</translation>
 <translation id="8035152190676905274">Lápiz</translation>
@@ -3913,6 +3925,7 @@
 <translation id="8037117624646282037">Quién usó el dispositivo recientemente</translation>
 <translation id="8037357227543935929">Preguntar (predeterminado)</translation>
 <translation id="803771048473350947">Archivo</translation>
+<translation id="8038182528865038593">Rojo 2</translation>
 <translation id="8041089156583427627">Enviar comentario</translation>
 <translation id="8041940743680923270">Usar configuración global predeterminada (Preguntar)</translation>
 <translation id="8043255123207491407">Ver los términos y condiciones del vendedor</translation>
@@ -4313,6 +4326,7 @@
 <translation id="8767881944435256294">{COUNT,plural, =1{1 forma de pago}other{# formas de pago}}</translation>
 <translation id="8768225988514678921">Botón Crear presentación: actívalo para crear una nueva presentación de Google en Presentaciones rápidamente</translation>
 <translation id="8769662576926275897">Detalles de la tarjeta</translation>
+<translation id="8769858749286369844">Canela 2</translation>
 <translation id="8770286973007342895">Cortadoras de césped</translation>
 <translation id="8772387130037509473">Yoga y pilates</translation>
 <translation id="877348612833018844">{0,plural, =1{¿Quieres mover este archivo confidencial?}other{¿Quieres mover estos archivos confidenciales?}}</translation>
@@ -4404,6 +4418,7 @@
 <translation id="8956124158020778855">Después de activar este parámetro de configuración, vuelve a esta pestaña para empezar a escribir.</translation>
 <translation id="8957210676456822347">Autorización de portal cautivo</translation>
 <translation id="8959282183248574156"><ph name="NICKNAME_COUNT" />/<ph name="NICKNAME_MAX" /></translation>
+<translation id="8959288490306482616">Canela 3</translation>
 <translation id="8963117664422609631">Ir a la configuración del sitio</translation>
 <translation id="8963213021028234748"><ph name="MARKUP_1" />Sugerencias:<ph name="MARKUP_2" />Asegúrate de tener una conexión de datos.<ph name="MARKUP_3" />Vuelve a cargar esta pagina web más adelante.<ph name="MARKUP_4" />Comprueba la dirección que ingresaste.<ph name="MARKUP_5" /></translation>
 <translation id="8968766641738584599">Guardar la tarjeta</translation>
@@ -4466,6 +4481,7 @@
 <translation id="90695670378604968">Plástico (mate)</translation>
 <translation id="9069693763241529744">Bloqueado por una extensión</translation>
 <translation id="9073799351042754113">Elegiste desactivar las advertencias de seguridad para este sitio.</translation>
+<translation id="9075717835386447447">Canela 1</translation>
 <translation id="9076283476770535406">Es posible que incluya contenido para adultos</translation>
 <translation id="9078912659001679888">Batidoras y jugueras</translation>
 <translation id="9078964945751709336">Se requiere más información</translation>
@@ -4575,6 +4591,7 @@
 <translation id="949314938206378263">Solicitaste visitar este sitio. Tu madre o padre puede responder en Family Link.</translation>
 <translation id="950736567201356821">Perforación triple en la parte superior</translation>
 <translation id="950926967802086924">Llave de acceso • Administrador de contraseñas de Google</translation>
+<translation id="95721182352849470">Amarillo 2</translation>
 <translation id="961663415146723894">Encuadernado en la parte inferior</translation>
 <translation id="961856697154696964">Borrar datos de navegación</translation>
 <translation id="961930410699694996">Se permite la ubicación esta vez</translation>
diff --git a/components/strings/components_strings_et.xtb b/components/strings/components_strings_et.xtb
index df0822a..7aad541a 100644
--- a/components/strings/components_strings_et.xtb
+++ b/components/strings/components_strings_et.xtb
@@ -884,7 +884,7 @@
 <translation id="2544644783021658368">Üks dokument</translation>
 <translation id="254524874071906077">Sea Chrome vaikebrauseriks</translation>
 <translation id="2545721997179863249">Tehti valik Sisestage kõik</translation>
-<translation id="2546283357679194313">Küpsised ja saidiandmed</translation>
+<translation id="2546283357679194313">Küpsised ja saidi andmed</translation>
 <translation id="254947805923345898">Reegli väärtus on kehtetu.</translation>
 <translation id="2549836668759467704">Ehitusalane nõustamine ja ehituslepingud</translation>
 <translation id="255002559098805027">Host <ph name="HOST_NAME" /> saatis sobimatu vastuse.</translation>
diff --git a/components/strings/components_strings_fr.xtb b/components/strings/components_strings_fr.xtb
index b7063c3..ecab13b 100644
--- a/components/strings/components_strings_fr.xtb
+++ b/components/strings/components_strings_fr.xtb
@@ -564,7 +564,7 @@
 <translation id="1999416967035780066">Freewares et sharewares</translation>
 <translation id="2001146170449793414">{COUNT,plural, =1{et 1 autre}one{et # autre}other{et # autres}}</translation>
 <translation id="2001469757375372617">Un problème est survenu. Votre modification n'a pas été enregistrée.</translation>
-<translation id="2002436619517051938">Vous pouvez effectuer des modifications dans les paramètres Chrome.</translation>
+<translation id="2002436619517051938">Vous pouvez modifier ces options dans les paramètres Chrome.</translation>
 <translation id="2003709556000175978">Réinitialiser votre mot de passe maintenant</translation>
 <translation id="2003775180883135320">Quadruple perforation en haut</translation>
 <translation id="2004697686368036666">Il est possible que les fonctionnalités de certains sites ne fonctionnent pas</translation>
diff --git a/components/strings/components_strings_gu.xtb b/components/strings/components_strings_gu.xtb
index caf741d..f1c62db 100644
--- a/components/strings/components_strings_gu.xtb
+++ b/components/strings/components_strings_gu.xtb
@@ -4534,6 +4534,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" />, એક અસમર્થિત પ્રોટોકોલનો ઉપયોગ કરે છે.</translation>
 <translation id="918454845714257218"><ph name="SIDE_OF_CARD" /> કોડ ચેક કરો અને ફરી પ્રયાસ કરો</translation>
 <translation id="9186203289258525843">'Chromeને ડિફૉલ્ટ બ્રાઉઝર તરીકે સેટ કરો' બટન, Chromeને સિસ્ટમના ડિફૉલ્ટ બ્રાઉઝર તરીકે સેટ કરવા માટે સક્રિય કરો</translation>
+<translation id="9189789270972826888">જો કાર્ડ ઑટોમૅટિક રીતે ભરવામાં આવ્યું ન હોય, તો કાર્ડની વિગતો કૉપિ પેસ્ટ કરવા માટે, તેના પર ક્લિક કરો. <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">4 અઠવાડિયાથી જૂના વિષયોને ઑટોમૅટિક રીતે ડિલીટ કરવામાં આવે છે</translation>
 <translation id="9191834167571392248">નીચે ડાબી બાજુએ કાણું પાડો</translation>
 <translation id="9192361865877479444">ધાતુ (મૅટ)</translation>
diff --git a/components/strings/components_strings_hy.xtb b/components/strings/components_strings_hy.xtb
index 14da7f0be..8bc8824 100644
--- a/components/strings/components_strings_hy.xtb
+++ b/components/strings/components_strings_hy.xtb
@@ -4541,6 +4541,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" />-ն օգտագործում է չաջակցվող հաղորդակարգ:</translation>
 <translation id="918454845714257218">Ստուգեք կոդը <ph name="SIDE_OF_CARD" /> և նորից փորձեք</translation>
 <translation id="9186203289258525843">«Դարձնել Chrome-ը կանխադրված դիտարկիչ» կոճակ․ ակտիվացրեք՝ Chrome-ը համակարգի կանխադրված դիտարկիչը դարձնելու համար</translation>
+<translation id="9189789270972826888">Եթե քարտի տվյալները չեն լրացվել, ներքևում սեղմեք քարտի տվյալների վրա, որպեսզի պատճենեք և տեղադրեք։ <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">4 շաբաթից հին թեմաներն ավտոմատ ջնջվում են</translation>
 <translation id="9191834167571392248">Անցք ներքևի ձախ կողմում</translation>
 <translation id="9192361865877479444">Մետաղ (անփայլ)</translation>
diff --git a/components/strings/components_strings_id.xtb b/components/strings/components_strings_id.xtb
index 4fbb80e9e..08b1405 100644
--- a/components/strings/components_strings_id.xtb
+++ b/components/strings/components_strings_id.xtb
@@ -4530,6 +4530,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" /> menggunakan protokol yang tidak didukung.</translation>
 <translation id="918454845714257218">Periksa kode di <ph name="SIDE_OF_CARD" /> dan coba lagi</translation>
 <translation id="9186203289258525843">Tombol Setel Chrome sebagai browser default, aktifkan untuk menyetel Chrome sebagai browser default sistem</translation>
+<translation id="9189789270972826888">Klik detail kartu di bawah untuk menyalin dan menempelkan jika kartu tidak terisi otomatis. <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">Topik yang lebih lama dari 4 minggu akan dihapus otomatis</translation>
 <translation id="9191834167571392248">Lubang di kiri bawah</translation>
 <translation id="9192361865877479444">Logam (Matte)</translation>
diff --git a/components/strings/components_strings_ja.xtb b/components/strings/components_strings_ja.xtb
index 1f536b6..728733b 100644
--- a/components/strings/components_strings_ja.xtb
+++ b/components/strings/components_strings_ja.xtb
@@ -3265,7 +3265,7 @@
 <translation id="6896758677409633944">コピー</translation>
 <translation id="6897140037006041989">ユーザー エージェント</translation>
 <translation id="6898699227549475383">組織(O)</translation>
-<translation id="6903907808598579934">同期を ON にする</translation>
+<translation id="6903907808598579934">同期をオンにする</translation>
 <translation id="6907458757809079309">フィットネス</translation>
 <translation id="691024665142758461">複数ファイルのダウンロード</translation>
 <translation id="6915804003454593391">ユーザー:</translation>
diff --git a/components/strings/components_strings_ka.xtb b/components/strings/components_strings_ka.xtb
index 5ea8f331..0db0569b 100644
--- a/components/strings/components_strings_ka.xtb
+++ b/components/strings/components_strings_ka.xtb
@@ -169,6 +169,7 @@
 <translation id="129553762522093515">ბოლოს დახურული</translation>
 <translation id="1296930489679394997">გაყიდვები</translation>
 <translation id="1297814096526086484">დაიბლოკოს თქვენი კლავიატურა და მაუსი?</translation>
+<translation id="1297832388362139384">მწვანე 1</translation>
 <translation id="1301227606947843452">Legal Extra</translation>
 <translation id="1301324364792935241">შეამოწმეთ თქვენი დაცული DNS-ის პარამეტრები</translation>
 <translation id="1302418742166945866"><ph name="URL" />-ს სურს, მართოს და გადააპროგრამოს თქვენი MIDI-მოწყობილობები</translation>
@@ -228,6 +229,7 @@
 <translation id="1384725838384960382">უსაფრთხო გადახდის ავტორიზაციის რეგისტრაციის ფურცელი</translation>
 <translation id="1386623374109090026">ანოტაციები</translation>
 <translation id="138810468159004008">ნების დართვა ვებსაიტის მონახულების დროს</translation>
+<translation id="139161720020179799">მუქი ნაცრისფერი 1</translation>
 <translation id="1391625539203220400">გსურთ, შეინახოთ IBAN ამ მოწყობილობაზე?</translation>
 <translation id="139305205187523129"><ph name="HOST_NAME" />-ს არ გამოუგზავნია მონაცემები.</translation>
 <translation id="1393071644879491291">თავდამსხმელებმა საიტზე, რომლის მონახულებაც ცადეთ, შესაძლოა, მოტყუებით დაგაინსტალირებინონ პროგრამული უზრუნველყოფა, ან გაგამჟღავნებინონ პაროლები, ტელეფონის ნომრები, საკრედიტო ბარათის ნომრები ან სხვა მსგავსი ინფორმაცია. Chrome დაჟინებით გირჩევთ, დაუბრუნდეთ უსაფრთხოებას. <ph name="BEGIN_LEARN_MORE_LINK" />შეიტყვეთ მეტი ამ გაფრთხილების შესახებ<ph name="END_LEARN_MORE_LINK" /></translation>
@@ -703,6 +705,7 @@
 <translation id="2227758700723188171">სასწავლო გრანტები და სტიპენდიები</translation>
 <translation id="2228057197024893428">ეს მისამართი ამჟამად შენახულია Chrome-ში. სხვადასხვა Google პროდუქტში მის გამოსაყენებლად შეინახეთ ის თქვენს Google ანგარიშში (<ph name="ACCOUNT" />).</translation>
 <translation id="2229456043301340598">იგნორირებულია არაუნიკალური მალსახმობი: „<ph name="SHORTCUT_NAME" />“</translation>
+<translation id="222962001646502673">მუქი ნაცრისფერი 2</translation>
 <translation id="2233041017768270281">{COUNT,plural, =1{1 ჩანართი}other{# ჩანართი}}</translation>
 <translation id="2233745931693710080">კომპაქტდისკი</translation>
 <translation id="2235344399760031203">მესამე მხარის ქუქი-ჩანაწერები დაბლოკილია</translation>
@@ -1730,6 +1733,7 @@
 <translation id="4084219288110917128">კონვერტი C1</translation>
 <translation id="4085326869263783566">ტექსტის შემქმნელი გასახსნელად დააჭირეთ Tab-ს და შემდეგ კი შეყვანას</translation>
 <translation id="4085769736382018559">პროდუქტების შედარება</translation>
+<translation id="4085778582400064057">ლურჯი 2</translation>
 <translation id="4088981014127559358">მხარე 1 — სურათის წანაცვლება Y ღერძზე</translation>
 <translation id="4089152113577680600">ლანგარი 14</translation>
 <translation id="4092349052316400070">მისამართის შევსება</translation>
@@ -1973,6 +1977,7 @@
 <translation id="4509074745930862522"><ph name="TRANSLATE_FOCUSED_FRIENDLY_MATCH_TEXT" />, ამ გვერდის Google Translate-ით სათარგმნად დააჭირეთ კლავიშს Tab, შემდეგ კი Enter-ს</translation>
 <translation id="4515275063822566619">ბარათებისა და მისამართების შესახებ ინფორმაცია მიღებულია Chrome-იდან და თქვენი Google ანგარიშიდან (<ph name="ACCOUNT_EMAIL" />). მათი მართვა შეგიძლიათ <ph name="BEGIN_LINK" />პარამეტრებში<ph name="END_LINK" />.</translation>
 <translation id="4515847625438516456">მიკრო და კომპაქტური ავტომობილები</translation>
+<translation id="451601984112574365">მწვანე 3</translation>
 <translation id="4519245469315452746">თქვენი მოწყობილობის მუშაობა შეფერხდა განახლების მიმდინარეობისას.</translation>
 <translation id="4520048001084013693">ამ ფაილის ჩამოტვირთვა დაბლოკილია ადმინისტრატორის წესების მიხედვით</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> მმ (<ph name="ORIENTATION" />)</translation>
@@ -2181,6 +2186,7 @@
 <translation id="4901952598169637881">ყოველდღიური ფეხსაცმელი</translation>
 <translation id="4905659621780993806">თქვენი ადმინისტრატორი ავტომატურად გადატვირთავს თქვენს მოწყობილობას <ph name="DATE" />-ის <ph name="TIME" />-ზე. მოწყობილობის გადატვირთვამდე შეინახეთ გახსნილი ერთეულები.</translation>
 <translation id="4913987521957242411">ზედა მარცხენა ნაწილის გახვრეტა</translation>
+<translation id="4914727764832832057">ლურჯი 1</translation>
 <translation id="4916389289686916969">სატელევიზიო რეალითი შოუები</translation>
 <translation id="4917064667437236721">სასურათე ცილინდრი</translation>
 <translation id="4918221908152712722">დააინსტალირეთ <ph name="APP_NAME" /> (ჩამოტვირთვა აუცილებელი არ არის)</translation>
@@ -2254,6 +2260,7 @@
 <translation id="5039804452771397117">დაშვება</translation>
 <translation id="5040262127954254034">კონფიდენციალურობა</translation>
 <translation id="5043480802608081735">თქვენ მიერ კოპირებული ბმული</translation>
+<translation id="5043753287208271200">ყვითელი 3</translation>
 <translation id="5045550434625856497">არასწორი პაროლი</translation>
 <translation id="5048293684454354469">სარეკლამო თემები არის ერთ-ერთი იმ მრავალი საშუალებიდან, რომლებითაც საიტს შეუძლია რეკლამის პერსონალიზება. საიტებს რეკლამის ჩვენება სარეკლამო თემების გარეშეც შეუძლია, თუმცა ის ნაკლებად პერსონალიზებული იქნება. შეიტყვეთ მეტი <ph name="BEGIN_LINK" />რეკლამის კონფიდენციალურობის მართვის<ph name="LINK_END" /> შესახებ.</translation>
 <translation id="5052517576853118371">აქტიური თემები</translation>
@@ -2560,6 +2567,7 @@
 <translation id="5593640815048812868">ლეპტოპები და ნოუთბუქები</translation>
 <translation id="5595485650161345191">მისამართის რედაქტირება</translation>
 <translation id="5596939519753369075">2 x 3,5 დუიმი</translation>
+<translation id="5597254438174353289">ლურჯი 3</translation>
 <translation id="560412284261940334">მართვა არ არის მხარდაჭერილი</translation>
 <translation id="5605249000617390290">შეიტყვეთ მეტი ფასებისთვის თვალის მიდევნების შესახებ</translation>
 <translation id="5605670050355397069">Ledger</translation>
@@ -2615,6 +2623,7 @@
 <translation id="5701381305118179107">ცენტრირება</translation>
 <translation id="5707154300732650394">თქვენი პროცესის გაგრძელება</translation>
 <translation id="57094364128775171">ძლიერი პაროლის შემოთავაზება…</translation>
+<translation id="570953204696852961">წითელი 3</translation>
 <translation id="571403275720188526">(arm64)</translation>
 <translation id="571510845185711675">ვეტერინარები</translation>
 <translation id="5715150588940290235">გსურთ, წაშალოთ უსაფრთხოების შენახული კოდები?</translation>
@@ -2815,6 +2824,7 @@
 <translation id="6085149458302186532">ლეიბლები (ფერადი)</translation>
 <translation id="6087312102907839798">დაკავშირებული ძიებები</translation>
 <translation id="6089505343295765444">თქვენი Chrome-ის ისტორიიდან წაშლილი ჩანართები მაინც გამოჩნდება შედარების ცხრილებში</translation>
+<translation id="6093599771645355227">ყვითელი 1</translation>
 <translation id="6093795393556121384">თქვენი ბარათი დადასტურდა</translation>
 <translation id="6094273045989040137">ანოტირება</translation>
 <translation id="6094290315941448991">ადმინისტრატორის წესების მიხედვით, ეკრანის ჩაწერა გათიშულია, როცა ხილულია კონფიდენციალური კონტენტი</translation>
@@ -3353,6 +3363,7 @@
 <translation id="7058774143982824355">CSV პაროლების სინტაქსიკური ანალიზის სერვისი</translation>
 <translation id="7062635574500127092">ზურმუხტისფერი</translation>
 <translation id="706295145388601875">მისამართების დამატება და მართვა Chrome-ის პარამეტრებიდან</translation>
+<translation id="7063157783216323487">მწვანე 2</translation>
 <translation id="7064443976734085921">კომპაქტური მანქანები</translation>
 <translation id="7064851114919012435">საკონტაქტო ინფორმაცია</translation>
 <translation id="7067633076996245366">სოული და რიტმ-ენდ-ბლუზი</translation>
@@ -3483,6 +3494,7 @@
 <translation id="7304030187361489308">მაღალი</translation>
 <translation id="7304562222803846232">Google ანგარიშის კონფიდენციალურობის პარამეტრების მართვა</translation>
 <translation id="7305756307268530424">უფრო ნელა გაშვება</translation>
+<translation id="7307063504147610123">მისამართი შენახულია ამ მოწყობილობაში</translation>
 <translation id="7308436126008021607">ფონური სინქრონიზაცია</translation>
 <translation id="7309058266849426521">შეიტყვეთ მეტი Chrome-ში რეკლამის კონფიდენციალურობის მართვის შესახებ.</translation>
 <translation id="7310392214323165548">მოწყობილობა ძალიან მალე გადაიტვირთება</translation>
@@ -3904,6 +3916,7 @@
 <translation id="8028698320761417183"><ph name="CREATE_GOOGLE_FORM_FOCUSED_FRIENDLY_MATCH_TEXT" />, Google Forms-ში ახალი ფორმის სწრაფად შესაქმნელად დააჭირეთ კლავიშს Tab, შემდეგ კი Enter-ს</translation>
 <translation id="8028892419725165118">ყოველდღიური თამაშები</translation>
 <translation id="8028960012888758725">შემოჭრა დავალების შესრულების შემდეგ</translation>
+<translation id="8029829038322015001">წითელი 1</translation>
 <translation id="8030729864112325446">პროფესიული და უწყვეტი განათლება</translation>
 <translation id="8032546467100845887">გამჭვირვალობა</translation>
 <translation id="8035152190676905274">კალამი</translation>
@@ -3911,6 +3924,7 @@
 <translation id="8037117624646282037">მოწყობილობის ბოლოდროინდელი მომხმარებლები</translation>
 <translation id="8037357227543935929">შეკითხვა (ნაგულისხმევი)</translation>
 <translation id="803771048473350947">ფაილი</translation>
+<translation id="8038182528865038593">წითელი 2</translation>
 <translation id="8041089156583427627">გამოხმაურება</translation>
 <translation id="8041940743680923270">გლობალური ნაგულისხმევის გამოყენება (კითხვა)</translation>
 <translation id="8043255123207491407">გამყიდველის მომსახურების პირობების ნახვა</translation>
@@ -4158,6 +4172,7 @@
 <translation id="8473626140772740486">300 x 450 მმ</translation>
 <translation id="8473863474539038330">მისამართები და სხვა</translation>
 <translation id="8474910779563686872">დეველოპერის დეტალების ჩვენება</translation>
+<translation id="8476959635632921417">ამ მისამართის თქვენს ყველა მოწყობილობაში შესანახად და გამოსაყენებლად საჭიროა ვინაობის დადასტურება</translation>
 <translation id="8479754468255770962">ქვედა მარცხენა ნაწილის დასტეპლერება</translation>
 <translation id="8483229036294884935">ეს მისამართი წაიშლება თქვენი Google ანგარიშიდან (<ph name="ACCOUNT" />)</translation>
 <translation id="8488350697529856933">გამოიყენება</translation>
@@ -4310,6 +4325,7 @@
 <translation id="8767881944435256294">{COUNT,plural, =1{გადახდის 1 მეთოდი}other{გადახდის # მეთოდი}}</translation>
 <translation id="8768225988514678921">პრეზენტაციის შექმნის ღილაკი, Slides-ში ახალი Google პრეზენტაციის სწრაფად შესაქმნელად გაააქტიურეთ ის</translation>
 <translation id="8769662576926275897">ბარათის დეტალები</translation>
+<translation id="8769858749286369844">რუჯისფერი 2</translation>
 <translation id="8770286973007342895">გაზონის საჭრელი მანქანები</translation>
 <translation id="8772387130037509473">იოგა და პილატესი</translation>
 <translation id="877348612833018844">{0,plural, =1{გსურთ კონფიდენციალური ფაილის გადატანა?}other{გსურთ კონფიდენციალური ფაილების გადატანა?}}</translation>
@@ -4401,6 +4417,7 @@
 <translation id="8956124158020778855">ამ პარამეტრის ჩართვის შემდეგ დაბრუნდით ამ ჩანართზე, წერა რომ დაიწყოთ.</translation>
 <translation id="8957210676456822347">დაკავებული პორტალების ავტორიზაცია</translation>
 <translation id="8959282183248574156"><ph name="NICKNAME_COUNT" />/<ph name="NICKNAME_MAX" /></translation>
+<translation id="8959288490306482616">რუჯისფერი 3</translation>
 <translation id="8963117664422609631">საიტის პარამეტრებზე გადასვლა</translation>
 <translation id="8963213021028234748"><ph name="MARKUP_1" />მითითებები:<ph name="MARKUP_2" />დარწმუნდით, რომ მონაცემთა კავშირი გაქვთ<ph name="MARKUP_3" />ხელახლა ჩატვირთეთ გვერდი მოგვიანებით<ph name="MARKUP_4" />შეამოწმეთ თქვენ მიერ შეყვანილი მისამართი<ph name="MARKUP_5" /></translation>
 <translation id="8968766641738584599">ბარათის შენახვა</translation>
@@ -4463,6 +4480,7 @@
 <translation id="90695670378604968">პლასტმასა (მქრქალი)</translation>
 <translation id="9069693763241529744">დაბლოკილია გაფართოების მიერ</translation>
 <translation id="9073799351042754113">თქვენ აირჩიეთ უსაფრთხოებასთან დაკავშირებული გაფრთხილებების გამორთვა ამ საიტისთვის.</translation>
+<translation id="9075717835386447447">რუჯისფერი 1</translation>
 <translation id="9076283476770535406">ის შეიძლება შეიცავდეს ზრდასრულებისთვის განკუთვნილ კონტენტს</translation>
 <translation id="9078912659001679888">ბლენდერები და წვენსაწურები</translation>
 <translation id="9078964945751709336">დამატებითი ინფორმაცია აუცილებელია</translation>
@@ -4572,6 +4590,7 @@
 <translation id="949314938206378263">თქვენ მოითხოვეთ ამ საიტის მონახულება. თქვენს მშობელს გამოხმაურება შეუძლია Family Link-იდან.</translation>
 <translation id="950736567201356821">სამმაგად გახვრეტა ზემოთ</translation>
 <translation id="950926967802086924">წვდომის გასაღები • Google პაროლების მმართველი</translation>
+<translation id="95721182352849470">ყვითელი 2</translation>
 <translation id="961663415146723894">აკინძვა ქვემოთ</translation>
 <translation id="961856697154696964">დათვალ. მონაცემების წაშლა</translation>
 <translation id="961930410699694996">მდებარეობა დაშვებულია ამჯერად</translation>
diff --git a/components/strings/components_strings_ko.xtb b/components/strings/components_strings_ko.xtb
index a2e3665..9640a7e 100644
--- a/components/strings/components_strings_ko.xtb
+++ b/components/strings/components_strings_ko.xtb
@@ -4532,6 +4532,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" />에서 지원되지 않는 프로토콜을 사용합니다.</translation>
 <translation id="918454845714257218"><ph name="SIDE_OF_CARD" />에서 코드를 확인한 후 다시 시도해 주세요.</translation>
 <translation id="9186203289258525843">Chrome을 기본 브라우저로 설정 버튼, Chrome을 시스템 기본 브라우저로 설정하려면 활성화하세요.</translation>
+<translation id="9189789270972826888">카드가 입력되지 않은 경우 아래의 카드 세부정보를 클릭하고 복사하여 붙여넣으세요. <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">4주가 지난 주제는 자동으로 삭제됩니다.</translation>
 <translation id="9191834167571392248">왼쪽 하단 펀칭</translation>
 <translation id="9192361865877479444">금속(매트)</translation>
diff --git a/components/strings/components_strings_lo.xtb b/components/strings/components_strings_lo.xtb
index 5c0ce66..c3deb7a 100644
--- a/components/strings/components_strings_lo.xtb
+++ b/components/strings/components_strings_lo.xtb
@@ -169,6 +169,7 @@
 <translation id="129553762522093515">ປິດ​ບໍ່​ດົນ​ມາ​ນີ້</translation>
 <translation id="1296930489679394997">ຫຼຸດລາຄາ</translation>
 <translation id="1297814096526086484">ລັອກແປ້ນພິມ ແລະ ເມົ້າຂອງທ່ານບໍ?</translation>
+<translation id="1297832388362139384">ສີຂຽວທີ 1</translation>
 <translation id="1301227606947843452">Legal Extra</translation>
 <translation id="1301324364792935241">ກວດເບິ່ງການຕັ້ງຄ່າ DNS ທີ່ປອດໄພຂອງທ່ານ</translation>
 <translation id="1302418742166945866"><ph name="URL" /> ຕ້ອງການຄວບຄຸມ ແລະ ຕັ້ງໂປຣແກຣມໃໝ່ໃນອຸປະກອນ MIDI ຂອງທ່ານ</translation>
@@ -228,6 +229,7 @@
 <translation id="1384725838384960382">ຊີດການພິສູດຢືນຢັນຂໍ້ມູນການເຂົ້າສູ່ລະບົບການຈ່າຍເງິນແບບປອດໄພ</translation>
 <translation id="1386623374109090026">ການອະທິບາຍຄວາມເຫັນ</translation>
 <translation id="138810468159004008">ອະນຸຍາດໃນລະຫວ່າງເຂົ້າເບິ່ງເວັບໄຊ</translation>
+<translation id="139161720020179799">ສີເທົາເຂັ້ມທີ 1</translation>
 <translation id="1391625539203220400">ບັນທຶກ IBAN ໃສ່ອຸປະກອນນີ້ບໍ?</translation>
 <translation id="139305205187523129"><ph name="HOST_NAME" /> ບໍ່ໄດ້ສົ່ງຂໍ້ມູນໃດໆ.</translation>
 <translation id="1393071644879491291">ຜູ້ໂຈມຕີຢູ່ເວັບໄຊທີ່ທ່ານພະຍາຍາມເຂົ້າເບິ່ງອາດຈະຫຼອກລວງໃຫ້ທ່ານຕິດຕັ້ງຊອບແວ ຫຼື ເປີດເຜີຍຂໍ້ມູນຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ເບີໂທລະສັບ ຫຼື ໝາຍເລກບັດເຄຣດິດຂອງທ່ານ. Chrome ຂໍແນະນຳຢ່າງຍິ່ງໃຫ້ກັບໄປຫາຄວາມປອດໄພ. <ph name="BEGIN_LEARN_MORE_LINK" />ສຶກສາເພີ່ມເຕີມກ່ຽວກັບຄຳເຕືອນນີ້<ph name="END_LEARN_MORE_LINK" /></translation>
@@ -703,6 +705,7 @@
 <translation id="2227758700723188171">ການຊ່ວຍເຫຼືອດ້ານການສຶກສາ ແລະ ທຶນການສຶກສາ</translation>
 <translation id="2228057197024893428">ປັດຈຸບັນທີ່ຢູ່ນີ້ຖືກບັນທຶກໃສ່ Chrome ແລ້ວ. ເພື່ອໃຊ້ມັນທົ່ວຜະລິດຕະພັນ Google, ໃຫ້ບັນທຶກມັນໃສ່ໃນບັນຊີ Google ຂອງທ່ານ, <ph name="ACCOUNT" />.</translation>
 <translation id="2229456043301340598">ທາງລັດທີ່ຊ້ຳກັນຖືກຂ້າມ: <ph name="SHORTCUT_NAME" /></translation>
+<translation id="222962001646502673">ສີເທົາເຂັ້ມທີ 2</translation>
 <translation id="2233041017768270281">{COUNT,plural, =1{1 ແຖບ}other{# ແຖບ}}</translation>
 <translation id="2233745931693710080">ແຜ່ນຊີດີ</translation>
 <translation id="2235344399760031203">ບລັອກຄຸກກີ້ພາກສ່ວນທີສາມໄວ້</translation>
@@ -1730,6 +1733,7 @@
 <translation id="4084219288110917128">Envelope C1</translation>
 <translation id="4085326869263783566">ຊ່ວຍຂ້ອຍຂຽນ. ກົດ Tab ແລະ ກົດ Enter ເພື່ອເປີດ</translation>
 <translation id="4085769736382018559">ປຽບທຽບຜະລິດຕະພັນ</translation>
+<translation id="4085778582400064057">ສີຟ້າທີ 2</translation>
 <translation id="4088981014127559358">ປ່ຽນຕຳແໜ່ງຮູບພາບດ້ານ 1 ຕາມແກນ Y</translation>
 <translation id="4089152113577680600">ຖາດ 14</translation>
 <translation id="4092349052316400070">ຕື່ມຂໍ້ມູນທີ່ຢູ່</translation>
@@ -1973,6 +1977,7 @@
 <translation id="4509074745930862522"><ph name="TRANSLATE_FOCUSED_FRIENDLY_MATCH_TEXT" />, ກົດແຖບ ຈາກນັ້ນກົດ Enter ເພື່ອແປໜ້ານີ້ດ້ວຍ Google ແປພາສາ</translation>
 <translation id="4515275063822566619">ບັດ ແລະ ທີ່ຢູ່ມາຈາກ Chrome ແລະ ບັນຊີ Google ຂອງທ່ານ (<ph name="ACCOUNT_EMAIL" />). ທ່ານສາມາດຈັດການພວກມັນໄດ້ໃນ <ph name="BEGIN_LINK" />ການຕັ້ງຄ່າ<ph name="END_LINK" />.</translation>
 <translation id="4515847625438516456">ລົດນ້ອຍ ແລະ ລົດກະທັດຮັດ</translation>
+<translation id="451601984112574365">ສີຂຽວທີ 3</translation>
 <translation id="4519245469315452746">ອຸປະກອນຂອງທ່ານຖືກຂັດຈັງຫວະໃນລະຫວ່າງຂັ້ນຕອນການອັບເດດ.</translation>
 <translation id="4520048001084013693">ການດາວໂຫຼດໄຟລ໌ນີ້ຖືກບລັອກໂດຍນະໂຍບາຍຜູ້ເບິ່ງແຍງລະບົບ</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> ມມ (<ph name="ORIENTATION" />)</translation>
@@ -2181,6 +2186,7 @@
 <translation id="4901952598169637881">ເກີບໃສ່ສະບາຍ</translation>
 <translation id="4905659621780993806">ຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານຈະຣີສະຕາດອຸປະກອນຂອງທ່ານໂດຍອັດຕະໂນມັດເວລາ <ph name="TIME" /> ໃນ <ph name="DATE" />. ກະລຸນາບັນທຶກລາຍການທີ່ເປີດໄວ້ກ່ອນອຸປະກອນຂອງທ່ານຈະຣີສະຕາດ.</translation>
 <translation id="4913987521957242411">ເຈາະຮູຢູ່ເທິງສຸດເບື້ອງຊ້າຍ</translation>
+<translation id="4914727764832832057">ສີຟ້າທີ 1</translation>
 <translation id="4916389289686916969">ລາຍການເຣຍລິຕີທາງໂທລະທັດ</translation>
 <translation id="4917064667437236721">ກະບອກຮູບພາບ</translation>
 <translation id="4918221908152712722">ຕິດຕັ້ງ <ph name="APP_NAME" /> (ບໍ່ຈໍາເປັນຕ້ອງດາວໂຫຼດ)</translation>
@@ -2254,6 +2260,7 @@
 <translation id="5039804452771397117">ອະ​ນຸ​ຍາດ​</translation>
 <translation id="5040262127954254034">ຄວາມ​ເປັນ​ສ່ວນ​ຕົວ</translation>
 <translation id="5043480802608081735">ລິ້ງທີ່ທ່ານສຳເນົາ</translation>
+<translation id="5043753287208271200">ສີເຫຼືອງທີ 3</translation>
 <translation id="5045550434625856497">ລະ​ຫັດ​ຜ່ານ​ບໍ່​ຖືກ​ຕ້ອງ​</translation>
 <translation id="5048293684454354469">ຫົວຂໍ້ໂຄສະນາເປັນພຽງໜຶ່ງໃນຫຼາຍໆສິ່ງທີ່ເວັບໄຊສາມາດໃຊ້ເພື່ອປັບແຕ່ງໂຄສະນາໃຫ້ເປັນແບບສ່ວນຕົວ. ເຖິງແມ່ນວ່າຈະບໍ່ມີຫົວຂໍ້ໂຄສະນາກໍຕາມ, ເວັບໄຊກໍຍັງສາມາດສະແດງໂຄສະນາໃຫ້ທ່ານເຫັນໄດ້ ແຕ່ໂຄສະນາອາດໄດ້ຮັບການປັບແຕ່ງສ່ວນຕົວໜ້ອຍລົງ. ສຶກສາເພີ່ມເຕີມກ່ຽວກັບ <ph name="BEGIN_LINK" />ການຈັດການຄວາມເປັນສ່ວນຕົວກ່ຽວກັບຕົວໂຄສະນາຂອງທ່ານ<ph name="LINK_END" />.</translation>
 <translation id="5052517576853118371">ຫົວຂໍ້ທີ່ນຳໃຊ້ຢູ່</translation>
@@ -2560,6 +2567,7 @@
 <translation id="5593640815048812868">ແລັບທັອບ ແລະ ໂນດບຸກ</translation>
 <translation id="5595485650161345191">ແກ້ໄຂທີ່ຢູ່</translation>
 <translation id="5596939519753369075">2 x 3.5 ນິ້ວ</translation>
+<translation id="5597254438174353289">ສີຟ້າທີ 3</translation>
 <translation id="560412284261940334">ການຈັດການບໍ່ໄດ້ຮັບການຮອງຮັບ</translation>
 <translation id="5605249000617390290">ສຶກສາເພີ່ມເຕີມກ່ຽວກັບການຕິດຕາມລາຄາ</translation>
 <translation id="5605670050355397069">Ledger</translation>
@@ -2615,6 +2623,7 @@
 <translation id="5701381305118179107">ໃຈກາງ</translation>
 <translation id="5707154300732650394">ສືບຕໍ່ບັນທຶກຂອງທ່ານ</translation>
 <translation id="57094364128775171">ແນະນຳລະຫັດຜ່ານທີ່ເດົາຍາກ…</translation>
+<translation id="570953204696852961">ສີແດງທີ 3</translation>
 <translation id="571403275720188526">(arm64)</translation>
 <translation id="571510845185711675">ສັດຕະວະແພດ</translation>
 <translation id="5715150588940290235">ລຶບລະຫັດຄວາມປອດໄພທີ່ບັນທຶກໄວ້ອອກບໍ?</translation>
@@ -2815,6 +2824,7 @@
 <translation id="6085149458302186532">ປ້າຍ (ມີສີ)</translation>
 <translation id="6087312102907839798">ການຊອກຫາທີ່ກ່ຽວຂ້ອງ</translation>
 <translation id="6089505343295765444">ແຖບທີ່ທ່ານລຶບອອກຈາກປະຫວັດ Chrome ຂອງທ່ານຈະຍັງຄົງສະແດງໃນຕາຕະລາງປຽບທຽບຂອງທ່ານ</translation>
+<translation id="6093599771645355227">ສີເຫຼືອງທີ 1</translation>
 <translation id="6093795393556121384">ບັດ​ຂອງ​ທ່ານ​ໄດ້​ຮັບ​ການ​ຢືນ​ຢັນ​ແລ້ວ</translation>
 <translation id="6094273045989040137">ຂຽນອະທິບາຍຄວາມເຫັນ</translation>
 <translation id="6094290315941448991">ນະໂຍບາຍຂອງຜູ້ເບິ່ງແຍງລະບົບປິດການນຳໃຊ້ການບັນທຶກໜ້າຈໍເມື່ອສະແດງເນື້ອຫາທີ່ເປັນຄວາມລັບຢູ່</translation>
@@ -3353,6 +3363,7 @@
 <translation id="7058774143982824355">ບໍລິການຕົວແຍກວິເຄາະລະຫັດຜ່ານ CSV</translation>
 <translation id="7062635574500127092">ສີຂຽວຫົວເປັດ</translation>
 <translation id="706295145388601875">ເພີ່ມ ແລະ ຈັດການທີ່ຢູ່ໃນການຕັ້ງຄ່າ Chrome</translation>
+<translation id="7063157783216323487">ສີຂຽວທີ 2</translation>
 <translation id="7064443976734085921">ລົດຂະໜາດນ້ອຍ</translation>
 <translation id="7064851114919012435">ຂໍ້​ມູນ​ຕິດ​ຕໍ່</translation>
 <translation id="7067633076996245366">ໂຊ ແລະ ອາແອນບີ</translation>
@@ -3483,6 +3494,7 @@
 <translation id="7304030187361489308">ສູງ</translation>
 <translation id="7304562222803846232">ຈັດການການຕັ້ງຄ່າຄວາມເປັນສ່ວນຕົວບັນຊີ Google</translation>
 <translation id="7305756307268530424">ເລີ່ມຊ້າລົງ</translation>
+<translation id="7307063504147610123">ທີ່ຢູ່ທີ່ບັນທຶກໄວ້ໃນອຸປະກອນເຄື່ອງນີ້</translation>
 <translation id="7308436126008021607">ການຊິ້ງຂໍ້ມູນໃນພື້ນຫຼັງ</translation>
 <translation id="7309058266849426521">ສຶກສາເພີ່ມເຕີມກ່ຽວກັບການຈັດການຄວາມເປັນສ່ວນຕົວກ່ຽວກັບຕົວໂຄສະນາຂອງທ່ານໃນ Chrome.</translation>
 <translation id="7310392214323165548">ອຸປະກອນຈະຣີສະຕາດໃນອີກບໍ່ດົນນີ້</translation>
@@ -3904,6 +3916,7 @@
 <translation id="8028698320761417183"><ph name="CREATE_GOOGLE_FORM_FOCUSED_FRIENDLY_MATCH_TEXT" />, ກົດ Tab ຈາກນັ້ນກົດ Enter ເພື່ອສ້າງແບບຟອມໃໝ່ໃນ Google Forms ໄດ້ຢ່າງວ່ອງໄວ</translation>
 <translation id="8028892419725165118">ເກມສະບາຍໆ</translation>
 <translation id="8028960012888758725">ຕັດອອກຫຼັງຈາກສຳເລັດວຽກ</translation>
+<translation id="8029829038322015001">ສີແດງທີ 1</translation>
 <translation id="8030729864112325446">ວິຊາຊີບ ແລະ ການສຶກສາຕໍ່</translation>
 <translation id="8032546467100845887">ຄວາມໂປ່ງແສງ</translation>
 <translation id="8035152190676905274">ບິກ</translation>
@@ -3911,6 +3924,7 @@
 <translation id="8037117624646282037">ໃຜໃຊ້ອຸປະກອນເມື່ອບໍ່ດົນມານີ້</translation>
 <translation id="8037357227543935929">ຖາມ (ຄ່າເລີ່ມຕົ້ນ)</translation>
 <translation id="803771048473350947">ໄຟລ໌</translation>
+<translation id="8038182528865038593">ສີແດງທີ 2</translation>
 <translation id="8041089156583427627">ສົ່ງຄຳຕິຊົມ</translation>
 <translation id="8041940743680923270">ໃຊ້ຄ່າມາດຕະຖານທົ່ວ​ໂລກ (ຖາມ​)</translation>
 <translation id="8043255123207491407">ເບິ່ງຂໍ້ກຳນົດ ແລະ ເງື່ອນໄຂຂອງຜູ້ຂາຍ</translation>
@@ -4158,6 +4172,7 @@
 <translation id="8473626140772740486">300 x 450 ມມ</translation>
 <translation id="8473863474539038330">ທີ່ຢູ່ ແລະ ອື່ນໆອີກ</translation>
 <translation id="8474910779563686872">ສະແດງລາຍລະອຽດຂອງນັກພັດທະນາ</translation>
+<translation id="8476959635632921417">ເພື່ອບັນທຶກ ແລະ ໃຊ້ທີ່ຢູ່ນີ້ໃນອຸປະກອນທຸກເຄື່ອງຂອງທ່ານ, ໃຫ້ຢັ້ງຢືນວ່າແມ່ນທ່ານ</translation>
 <translation id="8479754468255770962">ໜີບກະຫຼັບເຟີຢູ່ລຸ່ມສຸດເບື້ອງຊ້າຍ</translation>
 <translation id="8483229036294884935">ທີ່ຢູ່ນີ້ຈະຖືກລຶບອອກຈາກບັນຊີ Google ຂອງທ່ານ, <ph name="ACCOUNT" /></translation>
 <translation id="8488350697529856933">ນໍາໃຊ້ກັບ</translation>
@@ -4310,6 +4325,7 @@
 <translation id="8767881944435256294">{COUNT,plural, =1{ວິທີການຈ່າຍເງິນ 1 ວິທີ}other{ວິທີການຈ່າຍເງິນ # ວິທີ}}</translation>
 <translation id="8768225988514678921">ປຸ່ມສ້າງພຣີເຊັນເທເຊິນ, ເປີດນຳໃຊ້ເພື່ອສ້າງພຣີເຊັນເທເຊິນຂອງ Google ໃໝ່ໃນ Slides ຢ່າງວ່ອງໄວ</translation>
 <translation id="8769662576926275897">ລາຍ​ລະ​ອຽດ​ບັດ</translation>
+<translation id="8769858749286369844">ສີແທນທີ 2</translation>
 <translation id="8770286973007342895">ເຄື່ອງຕັດຫຍ້າ</translation>
 <translation id="8772387130037509473">ໂຍຄະ ແລະ ພິລາທິສ</translation>
 <translation id="877348612833018844">{0,plural, =1{ຍ້າຍໄຟລ໌ຄວາມລັບບໍ?}other{ຍ້າຍໄຟລ໌ຄວາມລັບບໍ?}}</translation>
@@ -4401,6 +4417,7 @@
 <translation id="8956124158020778855">ຫຼັງຈາກທີ່ທ່ານເປີດການຕັ້ງຄ່ານີ້ແລ້ວ, ໃຫ້ກັບມາແຖບນີ້ເພື່ອເລີ່ມຂຽນ.</translation>
 <translation id="8957210676456822347">ການ​ໃຫ້​ສິດ​ທາງ​ເຂົ້າ​ຈັບ​ໜ້າ​ຈໍ</translation>
 <translation id="8959282183248574156"><ph name="NICKNAME_COUNT" />/<ph name="NICKNAME_MAX" /></translation>
+<translation id="8959288490306482616">ສີແທນທີ 3</translation>
 <translation id="8963117664422609631">ໄປຫາການຕັ້ງຄ່າເວັບໄຊ</translation>
 <translation id="8963213021028234748"><ph name="MARKUP_1" />ຄຳ​ແນະ​ນຳ:<ph name="MARKUP_2" />ເບິ່ງ​ໃຫ້​ແນ່​ໃຈ​ວ່າ ທ່ານ​ມີ​ການ​ເຊື່ອມ​ຕໍ່​ຂໍ້​ມູນ​ຖືກ​ຕ້ອງ​ແລ້ວ<ph name="MARKUP_3" />ໂຫຼຼດ​ໜ້າ​ເວັບ​ນີ້​ພາຍ​ຫຼັງ<ph name="MARKUP_4" />ກວດ​ເບິ່ງ​ທີ່​ຢູ່​ທີ່​ທ່ານ​ປ້ອນ​ເຂົ້າ​<ph name="MARKUP_5" /></translation>
 <translation id="8968766641738584599">ບັນທຶກບັດໄວ້</translation>
@@ -4463,6 +4480,7 @@
 <translation id="90695670378604968">ພລາສຕິກ (ດ້ານ)</translation>
 <translation id="9069693763241529744">ບລັອກໄວ້ໂດຍສ່ວນຂະຫຍາຍ</translation>
 <translation id="9073799351042754113">ທ່ານໄດ້ເລືອກປິດຄຳເຕືອນຄວາມປອດໄພສຳລັບເວັບໄຊນີ້ແລ້ວ.</translation>
+<translation id="9075717835386447447">ສີແທນທີ 1</translation>
 <translation id="9076283476770535406">ມັນອາດຈະມີເນື້ອຫາສຳລັບຜູ້ໃຫຍ່</translation>
 <translation id="9078912659001679888">ເຄື່ອງປັ່ນ ແລະ ເຄື່ອງບີບນ້ຳໝາກໄມ້</translation>
 <translation id="9078964945751709336">ຈຳເປັນຕ້ອງມີຂໍ້ມູນເພີ່ມເຕີມ</translation>
@@ -4572,6 +4590,7 @@
 <translation id="949314938206378263">ທ່ານໄດ້ຂໍເຂົ້າເບິ່ງເວັບໄຊນີ້. ຜູ້ປົກຄອງຂອງທ່ານສາມາດຕອບກັບໃນ Family Link.</translation>
 <translation id="950736567201356821">ເຈາະຮູຢູ່ເທິງສຸດສາມຮູ</translation>
 <translation id="950926967802086924">ກະແຈຜ່ານ • ຕົວຈັດການລະຫັດຜ່ານ Google</translation>
+<translation id="95721182352849470">ສີເຫຼືອງທີ 2</translation>
 <translation id="961663415146723894">ຫຍິບເຫຼັ້ມລຸ່ມສຸດ</translation>
 <translation id="961856697154696964">ລຶບຂໍ້ມູນການທ່ອງເວັບ</translation>
 <translation id="961930410699694996">ຂະນະນີ້ອະນຸຍາດສະຖານທີ່ແລ້ວ</translation>
diff --git a/components/strings/components_strings_lt.xtb b/components/strings/components_strings_lt.xtb
index 79c98ee..74ed1be 100644
--- a/components/strings/components_strings_lt.xtb
+++ b/components/strings/components_strings_lt.xtb
@@ -4536,6 +4536,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" /> naudojamas nepalaikomas protokolas.</translation>
 <translation id="918454845714257218">Patikrinkite kodą, pateiktą <ph name="SIDE_OF_CARD" />, ir bandykite dar kartą</translation>
 <translation id="9186203289258525843">Mygtukas „Nustatyti „Chrome“ kaip numatytąją naršyklę“; suaktyvinkite, kad nustatytumėte „Chrome“ kaip numatytąją sistemos naršyklę</translation>
+<translation id="9189789270972826888">Jei kortelė nebuvo užpildyta, spustelėkite išsamią kortelės informaciją toliau, kad nukopijuotumėte ir įklijuotumėte. <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">Senesnės nei keturių savaičių temos ištrinamos automatiškai</translation>
 <translation id="9191834167571392248">Skylė apačioje kairėje</translation>
 <translation id="9192361865877479444">Metalas (matinis)</translation>
diff --git a/components/strings/components_strings_lv.xtb b/components/strings/components_strings_lv.xtb
index 732b4d22..5035416 100644
--- a/components/strings/components_strings_lv.xtb
+++ b/components/strings/components_strings_lv.xtb
@@ -4532,6 +4532,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" /> izmanto neatbalstītu protokolu.</translation>
 <translation id="918454845714257218">Pārbaudiet kodu (atrodas šeit: <ph name="SIDE_OF_CARD" />) un mēģiniet vēlreiz.</translation>
 <translation id="9186203289258525843">Poga “Iestatīt Chrome kā noklusējuma pārlūku”. Aktivizējiet, lai iestatītu Chrome kā sistēmas noklusējuma pārlūku.</translation>
+<translation id="9189789270972826888">Ja kartes dati nav aizpildīti, noklikšķiniet uz tālāk norādītajiem datiem, lai tos kopētu un ielīmētu. <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">Tēmas, kas vecākas par četrām nedēļām, tiek automātiski dzēstas.</translation>
 <translation id="9191834167571392248">Caurums apakšējā kreisajā malā</translation>
 <translation id="9192361865877479444">Metāls (matēts)</translation>
diff --git a/components/strings/components_strings_mn.xtb b/components/strings/components_strings_mn.xtb
index 79021e9..12c9be7 100644
--- a/components/strings/components_strings_mn.xtb
+++ b/components/strings/components_strings_mn.xtb
@@ -4533,6 +4533,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" /> нь дэмжигдээгүй протоколыг ашигладаг.</translation>
 <translation id="918454845714257218"><ph name="SIDE_OF_CARD" /> дээрх кодыг шалгаад, дахин оролдоно уу</translation>
 <translation id="9186203289258525843">Chrome-г өгөгдмөл хөтөч болгон тохируулах товчлуур, Chrome-г системийн өгөгдмөл хөтөч болгон тохируулахын тулд идэвхжүүлнэ үү</translation>
+<translation id="9189789270972826888">Хэрэв картыг бөглөөгүй бол доорх картын дэлгэрэнгүй мэдээллийг товшиж, хуулаад буулгана уу. <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">4 долоо хоногоос дээш болсон сэдвүүдийг автоматаар устгадаг</translation>
 <translation id="9191834167571392248">Зүүн доод буланд нэг нүх цоолох</translation>
 <translation id="9192361865877479444">Металл (мaтте)</translation>
diff --git a/components/strings/components_strings_mr.xtb b/components/strings/components_strings_mr.xtb
index 3a267fb..368443a 100644
--- a/components/strings/components_strings_mr.xtb
+++ b/components/strings/components_strings_mr.xtb
@@ -169,6 +169,7 @@
 <translation id="129553762522093515">अलीकडे बंद केलेले</translation>
 <translation id="1296930489679394997">विक्री</translation>
 <translation id="1297814096526086484">तुमचा कीबोर्ड आणि माउस लॉक करायचा आहे का?</translation>
+<translation id="1297832388362139384">हिरवा १</translation>
 <translation id="1301227606947843452">Legal Extra</translation>
 <translation id="1301324364792935241">तुमची सुरक्षित DNS सेटिंग्ज तपासा</translation>
 <translation id="1302418742166945866"><ph name="URL" /> ला तुमची MIDI डिव्‍हाइस नियंत्रित आणि रीप्रोग्राम करायची आहेत</translation>
@@ -228,6 +229,7 @@
 <translation id="1384725838384960382">सुरक्षित पेमेंट क्रेडेंशियल ची ऑथेंटिकेशन शीट</translation>
 <translation id="1386623374109090026">भाष्ये</translation>
 <translation id="138810468159004008">साइटला भेट देताना अनुमती द्या</translation>
+<translation id="139161720020179799">गडद राखाडी १</translation>
 <translation id="1391625539203220400">या डिव्हाइसवर IBAN सेव्ह करायचा का?</translation>
 <translation id="139305205187523129"><ph name="HOST_NAME" /> नी कोणताही डेटा पाठविला नाही.</translation>
 <translation id="1393071644879491291">तुम्ही भेट देण्याचा प्रयत्न केलेल्या साइटवरील हल्लेखोर तुम्हाला सॉफ्टवेअर इंस्टॉल करण्यासाठी किंवा तुमचा पासवर्ड, फोन अथवा क्रेडिट कार्ड नंबर यांसारख्या गोष्टी उघड करून फसवण्याचा प्रयत्न करू शकतात. Chrome हे सुरक्षिततेकडे परतण्याची आवर्जून शिफारस करते. <ph name="BEGIN_LEARN_MORE_LINK" />या चेतावणीबद्दल अधिक जाणून घ्या<ph name="END_LEARN_MORE_LINK" /></translation>
@@ -703,6 +705,7 @@
 <translation id="2227758700723188171">शैक्षणिक अनुदाने आणि शिष्यवृत्ती</translation>
 <translation id="2228057197024893428">हा पत्ता सध्या Chrome वर सेव्ह केला आहे. तो सर्व Google उत्पादनांवर वापरण्यासाठी, तुमच्या Google खाते <ph name="ACCOUNT" /> मध्ये सेव्ह करा.</translation>
 <translation id="2229456043301340598">युनिक नसलेल्या शॉर्टकटकडे दुर्लक्ष केले आहे: <ph name="SHORTCUT_NAME" /></translation>
+<translation id="222962001646502673">गडद राखाडी २</translation>
 <translation id="2233041017768270281">{COUNT,plural, =1{१ टॅब}other{# टॅब}}</translation>
 <translation id="2233745931693710080">कॉम्पॅक्ट डिस्क</translation>
 <translation id="2235344399760031203">तृतीय पक्ष कुकी ब्लॉक केल्या आहेत</translation>
@@ -1729,6 +1732,7 @@
 <translation id="4084219288110917128">एन्व्हलप सी१</translation>
 <translation id="4085326869263783566">मला लिहिण्यात मदत करा. उघडण्यासाठी टॅब करून एंटर प्रेस करा</translation>
 <translation id="4085769736382018559">उत्पादनांची तुलना करा</translation>
+<translation id="4085778582400064057">निळा २</translation>
 <translation id="4088981014127559358">साइन १ इमेज Y शिफ्ट</translation>
 <translation id="4089152113577680600">ट्रे १४</translation>
 <translation id="4092349052316400070">पत्ता भरा</translation>
@@ -1972,6 +1976,7 @@
 <translation id="4509074745930862522"><ph name="TRANSLATE_FOCUSED_FRIENDLY_MATCH_TEXT" />, Google Translate वापरून या पेजचे भाषांतर करण्यासाठी टॅब आणि त्यानंतर एंटर प्रेस करा</translation>
 <translation id="4515275063822566619">कार्ड आणि पत्ते Chrome आणि आपल्या Google खात्याकडील (<ph name="ACCOUNT_EMAIL" />) आहेत. तुम्ही त्यांना <ph name="BEGIN_LINK" />सेटिंग्‍ज<ph name="END_LINK" /> मधून व्यवस्थापित करू शकता.</translation>
 <translation id="4515847625438516456">मायक्रोकार आणि सबकॉम्पॅक्ट</translation>
+<translation id="451601984112574365">हिरवा ३</translation>
 <translation id="4519245469315452746">अपडेट प्रक्रियेदरम्यान तुमच्या डिव्हाइसमध्ये व्यत्यय आला.</translation>
 <translation id="4520048001084013693">ही फाइल डाउनलोड करणे अ‍ॅडमिनिस्ट्रेटर धोरणाद्वारे ब्लॉक केले आहे</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> मिमी (<ph name="ORIENTATION" />)</translation>
@@ -2180,6 +2185,7 @@
 <translation id="4901952598169637881">साधे शूज</translation>
 <translation id="4905659621780993806">तुमचा अ‍ॅडमिनिस्ट्रेटर तुमचे डिव्हाइस <ph name="DATE" /> रोजी <ph name="TIME" /> वाजता आपोआप रीस्टार्ट करेल. तुमचे डिव्हाइस रीस्टार्ट होण्यापूर्वी कोणतेही खुले आयटम सेव्ह करा.</translation>
 <translation id="4913987521957242411">पंच टॉप लेफ्ट</translation>
+<translation id="4914727764832832057">निळा १</translation>
 <translation id="4916389289686916969">टीव्‍हीवरील रीअ‍ॅलिटी शो</translation>
 <translation id="4917064667437236721">इमेजिंग सिलिंडर</translation>
 <translation id="4918221908152712722"><ph name="APP_NAME" /> इंस्टॉल करा (डाउनलोड करण्याची आवश्यकता नाही)</translation>
@@ -2253,6 +2259,7 @@
 <translation id="5039804452771397117">परवानगी द्या</translation>
 <translation id="5040262127954254034">गोपनीयता</translation>
 <translation id="5043480802608081735">तुम्ही कॉपी केलेली लिंक</translation>
+<translation id="5043753287208271200">पिवळा ३</translation>
 <translation id="5045550434625856497">चुकीचा पासवर्ड</translation>
 <translation id="5048293684454354469">जाहिराती पर्सनलाइझ करण्यासाठी साइट वापरू शकत असलेल्या अनेक गोष्टींपैकी जाहिरातीचे विषय ही फक्त एक गोष्ट आहे. जाहिरातीच्या विषयांशिवायदेखील साइट तुम्हाला जाहिराती दाखवू शकतात, पण त्या कमी पर्सनलाइझ केलेल्या असतील. <ph name="BEGIN_LINK" />तुमची जाहिरातीसंबंधित गोपनीयता व्यवस्थापित करणे<ph name="LINK_END" /> याबद्दल अधिक जाणून घ्या.</translation>
 <translation id="5052517576853118371">ॲक्टिव्ह विषय</translation>
@@ -2559,6 +2566,7 @@
 <translation id="5593640815048812868">लॅपटॉप आणि नोटबुक</translation>
 <translation id="5595485650161345191">पत्ता संपादित करा</translation>
 <translation id="5596939519753369075">२ x ३.५ इं</translation>
+<translation id="5597254438174353289">निळा ३</translation>
 <translation id="560412284261940334">व्यवस्थापनाला सपोर्ट नाही</translation>
 <translation id="5605249000617390290">किंमत ट्रॅक करण्याबद्दल अधिक जाणून घ्या</translation>
 <translation id="5605670050355397069">Ledger</translation>
@@ -2614,6 +2622,7 @@
 <translation id="5701381305118179107">मध्यभागी</translation>
 <translation id="5707154300732650394">तुमचा प्रवास पुन्हा सुरू करा</translation>
 <translation id="57094364128775171">क्लिष्ट पासवर्ड सुचवा…</translation>
+<translation id="570953204696852961">लाल ३</translation>
 <translation id="571403275720188526">(arm64)</translation>
 <translation id="571510845185711675">पशुचिकित्‍सक</translation>
 <translation id="5715150588940290235">सेव्ह केलेले सुरक्षा कोड हटवायचे आहेत का?</translation>
@@ -2814,6 +2823,7 @@
 <translation id="6085149458302186532">लेबल (कलर्ड)</translation>
 <translation id="6087312102907839798">संबंधित शोध</translation>
 <translation id="6089505343295765444">तुम्ही तुमच्या Chrome इतिहासामधून हटवलेले टॅब तरीही तुमच्या तुलना सारण्यांमध्ये दिसतील</translation>
+<translation id="6093599771645355227">पिवळा १</translation>
 <translation id="6093795393556121384">तुमचे कार्ड सत्यापित केले आहे</translation>
 <translation id="6094273045989040137">भाष्य करा</translation>
 <translation id="6094290315941448991">गोपनीय आशय दृश्यमान असेल तेव्हा अ‍ॅडमिनिस्ट्रेटर धोरण स्क्रीन रेकॉर्डिंग बंद करते</translation>
@@ -3353,6 +3363,7 @@
 <translation id="7058774143982824355">CSV पासवर्ड पार्सर सेवा</translation>
 <translation id="7062635574500127092">हिरवट निळा</translation>
 <translation id="706295145388601875">Chrome सेटिंग्जमध्ये ॲड्रेस जोडा आणि व्यवस्थापित करा</translation>
+<translation id="7063157783216323487">हिरवा २</translation>
 <translation id="7064443976734085921">कॉम्पॅक्ट कार</translation>
 <translation id="7064851114919012435">संपर्क माहिती</translation>
 <translation id="7067633076996245366">सोल आणि आर अँड बी</translation>
@@ -3905,6 +3916,7 @@
 <translation id="8028698320761417183"><ph name="CREATE_GOOGLE_FORM_FOCUSED_FRIENDLY_MATCH_TEXT" />, Google Forms मध्ये नवीन फॉर्म झटपट तयार करण्यासाठी टॅब आणि त्यानंतर एंटर प्रेस करा</translation>
 <translation id="8028892419725165118">साधे गेम</translation>
 <translation id="8028960012888758725">जॉबनंतर ट्रिम करा</translation>
+<translation id="8029829038322015001">लाल १</translation>
 <translation id="8030729864112325446">व्‍यावसायिक आणि प्रौढ शिक्षण</translation>
 <translation id="8032546467100845887">ट्रान्स्परसी</translation>
 <translation id="8035152190676905274">पेन</translation>
@@ -3912,6 +3924,7 @@
 <translation id="8037117624646282037">डिव्हाइस अलीकडे कोणी वापरले</translation>
 <translation id="8037357227543935929">विचारा (डीफॉल्ट)</translation>
 <translation id="803771048473350947">फाइल</translation>
+<translation id="8038182528865038593">लाल २</translation>
 <translation id="8041089156583427627">अभिप्राय पाठवा</translation>
 <translation id="8041940743680923270">सार्वत्रिक डीफॉल्‍ट वापरा (विचारा)</translation>
 <translation id="8043255123207491407">विक्रेत्याच्या अटी आणि नियम पहा</translation>
@@ -4311,6 +4324,7 @@
 <translation id="8767881944435256294">{COUNT,plural, =1{१ पेमेंट पद्धत}other{# पेमेंट पद्धती}}</translation>
 <translation id="8768225988514678921">प्रेझेंटेशन तयार करा बटण, Slides मध्ये नवीन Google प्रेझेंटेशन झटपट तयार करण्यासाठी अ‍ॅक्टिव्हेट करा</translation>
 <translation id="8769662576926275897">कार्ड तपशील</translation>
+<translation id="8769858749286369844">टॅन २</translation>
 <translation id="8770286973007342895">गवत कापणीची यंत्रे</translation>
 <translation id="8772387130037509473">योग आणि पिलाटेज</translation>
 <translation id="877348612833018844">{0,plural, =1{गोपनीय फाइल हलवायची आहे का?}other{गोपनीय फाइल हलवायच्या आहेत का?}}</translation>
@@ -4402,6 +4416,7 @@
 <translation id="8956124158020778855">तुम्ही हे सेटिंग सुरू केल्यानंतर, लिहिणे सुरू करण्यासाठी या टॅबवर परत या.</translation>
 <translation id="8957210676456822347">बंद पोर्टल प्राधिकृतता</translation>
 <translation id="8959282183248574156"><ph name="NICKNAME_COUNT" />/<ph name="NICKNAME_MAX" /></translation>
+<translation id="8959288490306482616">टॅन ३</translation>
 <translation id="8963117664422609631">साइट सेटिंग्जवर जा</translation>
 <translation id="8963213021028234748"><ph name="MARKUP_1" />सूचना:<ph name="MARKUP_2" />आपल्याकडे डेटा कनेक्शन असल्याचे निश्चित करा<ph name="MARKUP_3" />हे वेबपेज नंतर रीलोड करा<ph name="MARKUP_4" />तुम्ही एंटर केलेला ॲड्रेस तपासा<ph name="MARKUP_5" /></translation>
 <translation id="8968766641738584599">कार्ड सेव्ह करा</translation>
@@ -4464,6 +4479,7 @@
 <translation id="90695670378604968">प्लॅस्टिक (मॅट)</translation>
 <translation id="9069693763241529744">एक एक्स्टेंशनने ब्लॉक केलेले</translation>
 <translation id="9073799351042754113">तुम्ही या साइटसाठी सुरक्षा चेतावण्या बंद करणे निवडले आहे.</translation>
+<translation id="9075717835386447447">टॅन १</translation>
 <translation id="9076283476770535406">कदाचित तिच्यामध्ये प्रौढ आशय असू शकते</translation>
 <translation id="9078912659001679888">ब्लेंडर आणि ज्यूसर</translation>
 <translation id="9078964945751709336">अधिक माहिती आवश्यक आहे</translation>
@@ -4534,6 +4550,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" /> असमर्थित प्रोटोकॉल वापरतो.</translation>
 <translation id="918454845714257218"><ph name="SIDE_OF_CARD" /> येथील कोड तपासा आणि पुन्हा प्रयत्न करा</translation>
 <translation id="9186203289258525843">Chrome ला डीफॉल्ट ब्राउझर म्हणून सेट करा बटण, Chrome ला सिस्टीमचा डीफॉल्ट ब्राउझर म्हणून सेट करण्यासाठी अ‍ॅक्टिव्हेट करा</translation>
+<translation id="9189789270972826888">कार्ड भरले नसल्यास कॉपी आणि पेस्ट करण्यासाठी खालील कार्ड तपशिलांवर क्लिक करा. <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">४ आठवड्यांहून जुने विषय ऑटो-डिलीट केले जातात</translation>
 <translation id="9191834167571392248">पंच बॉटम लेफ्ट</translation>
 <translation id="9192361865877479444">मेटल (मॅट)</translation>
@@ -4572,6 +4589,7 @@
 <translation id="949314938206378263">तुम्हाला या साइटला भेट देण्यास सांगितले आहे. तुमचे पालक Family Link मध्ये उत्तर देऊ शकतात.</translation>
 <translation id="950736567201356821">ट्रिपल पंच टॉप</translation>
 <translation id="950926967802086924">पासकी • Google Password Manager</translation>
+<translation id="95721182352849470">पिवळा २</translation>
 <translation id="961663415146723894">बाइंड बॉटम</translation>
 <translation id="961856697154696964">ब्राउझिंग डेटा हटवा</translation>
 <translation id="961930410699694996">यावेळी स्थानाला अनुमती दिली आहे</translation>
diff --git a/components/strings/components_strings_ms.xtb b/components/strings/components_strings_ms.xtb
index a4dd07b..554aa8d 100644
--- a/components/strings/components_strings_ms.xtb
+++ b/components/strings/components_strings_ms.xtb
@@ -169,6 +169,7 @@
 <translation id="129553762522093515">Ditutup baru-baru ini</translation>
 <translation id="1296930489679394997">Jualan</translation>
 <translation id="1297814096526086484">Kunci papan kekunci dan tetikus anda?</translation>
+<translation id="1297832388362139384">Hijau 1</translation>
 <translation id="1301227606947843452">Perundangan Tambahan</translation>
 <translation id="1301324364792935241">Semak tetapan DNS Selamat anda</translation>
 <translation id="1302418742166945866"><ph name="URL" /> mahu mengawal dan mengatur cara semula peranti MIDI anda</translation>
@@ -228,6 +229,7 @@
 <translation id="1384725838384960382">Helaian pengesahan bukti kelayakan pembayaran selamat</translation>
 <translation id="1386623374109090026">Anotasi</translation>
 <translation id="138810468159004008">Benarkan semasa laman dilawati</translation>
+<translation id="139161720020179799">Kelabu Gelap 1</translation>
 <translation id="1391625539203220400">Simpan IBAN pada peranti ini?</translation>
 <translation id="139305205187523129"><ph name="HOST_NAME" /> tidak menghantar sebarang data.</translation>
 <translation id="1393071644879491291">Penyerang pada laman yang cuba anda lawati mungkin memperdaya anda untuk memasang perisian atau mendedahkan perkara seperti kata laluan, telefon atau nombor kad kredit anda. Chrome amat mengesyorkan untuk kembali ke tempat selamat. <ph name="BEGIN_LEARN_MORE_LINK" />Ketahui lebih lanjut tentang amaran ini<ph name="END_LEARN_MORE_LINK" /></translation>
@@ -703,6 +705,7 @@
 <translation id="2227758700723188171">Geran &amp; Biasiswa Pendidikan</translation>
 <translation id="2228057197024893428">Alamat ini disimpan dalam Chrome pada masa ini. Untuk menggunakan alamat ini pada seluruh produk Google, simpan alamat ini dalam Google Account anda, <ph name="ACCOUNT" />.</translation>
 <translation id="2229456043301340598">Pintasan tidak unik diabaikan: <ph name="SHORTCUT_NAME" /></translation>
+<translation id="222962001646502673">Kelabu Gelap 2</translation>
 <translation id="2233041017768270281">{COUNT,plural, =1{1 tab}other{# tab}}</translation>
 <translation id="2233745931693710080">Cakera Padat</translation>
 <translation id="2235344399760031203">Kuki pihak ketiga disekat</translation>
@@ -1731,6 +1734,7 @@
 <translation id="4084219288110917128">Sampul C1</translation>
 <translation id="4085326869263783566">Bantu saya tulis. Tab dan tekan enter untuk buka</translation>
 <translation id="4085769736382018559">Bandingkan produk</translation>
+<translation id="4085778582400064057">Biru 2</translation>
 <translation id="4088981014127559358">Anjakan Y sisi 1 imej</translation>
 <translation id="4089152113577680600">Dulang 14</translation>
 <translation id="4092349052316400070">Isikan alamat</translation>
@@ -1974,6 +1978,7 @@
 <translation id="4509074745930862522"><ph name="TRANSLATE_FOCUSED_FRIENDLY_MATCH_TEXT" />, tekan Tab kemudian Enter untuk menterjemahkan halaman ini dengan Google Translate</translation>
 <translation id="4515275063822566619">Kad dan alamat adalah daripada Chrome dan Google Account anda (<ph name="ACCOUNT_EMAIL" />). Anda boleh mengurus kad dan alamat ini dalam <ph name="BEGIN_LINK" />Tetapan<ph name="END_LINK" />.</translation>
 <translation id="4515847625438516456">Kereta Mikro &amp; Subkompak</translation>
+<translation id="451601984112574365">Hijau 3</translation>
 <translation id="4519245469315452746">Peranti anda terganggu semasa proses pengemaskinian.</translation>
 <translation id="4520048001084013693">Pemuatan turun fail ini disekat oleh dasar pentadbir</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> mm (<ph name="ORIENTATION" />)</translation>
@@ -2182,6 +2187,7 @@
 <translation id="4901952598169637881">Kasut Kasual</translation>
 <translation id="4905659621780993806">Pentadbir anda akan memulakan semula peranti anda pada <ph name="DATE" /> jam <ph name="TIME" /> secara automatik. Simpan sebarang item terbuka sebelum peranti anda dimulakan semula.</translation>
 <translation id="4913987521957242411">Tebukan atas sebelah kiri</translation>
+<translation id="4914727764832832057">Biru 1</translation>
 <translation id="4916389289686916969">Rancangan Realiti TV</translation>
 <translation id="4917064667437236721">Silinder pengimejan</translation>
 <translation id="4918221908152712722">Pasang <ph name="APP_NAME" /> (tidak perlu dimuat turun)</translation>
@@ -2255,6 +2261,7 @@
 <translation id="5039804452771397117">Benarkan</translation>
 <translation id="5040262127954254034">Privasi</translation>
 <translation id="5043480802608081735">Pautan yang Anda Salin</translation>
+<translation id="5043753287208271200">Kuning 3</translation>
 <translation id="5045550434625856497">Kata laluan tidak sah</translation>
 <translation id="5048293684454354469">Topik iklan adalah antara ciri yang boleh digunakan oleh laman untuk memeribadikan iklan. Walaupun tanpa topik iklan, laman masih boleh memaparkan iklan kepada anda tetapi iklan tersebut mungkin kurang diperibadikan. Ketahui lebih lanjut tentang <ph name="BEGIN_LINK" />pengurusan privasi iklan anda<ph name="LINK_END" />.</translation>
 <translation id="5052517576853118371">Topik aktif</translation>
@@ -2561,6 +2568,7 @@
 <translation id="5593640815048812868">Komputer Riba</translation>
 <translation id="5595485650161345191">Edit alamat</translation>
 <translation id="5596939519753369075">2 x 3.5 in</translation>
+<translation id="5597254438174353289">Biru 3</translation>
 <translation id="560412284261940334">Pengurusan tidak disokong</translation>
 <translation id="5605249000617390290">Ketahui lebih lanjut tentang penjejakan harga</translation>
 <translation id="5605670050355397069">Lejar</translation>
@@ -2616,6 +2624,7 @@
 <translation id="5701381305118179107">Tengah</translation>
 <translation id="5707154300732650394">Sambung semula perjalanan anda</translation>
 <translation id="57094364128775171">Cadangkan kata laluan yang kukuh…</translation>
+<translation id="570953204696852961">Merah 3</translation>
 <translation id="571403275720188526">(arm64)</translation>
 <translation id="571510845185711675">Doktor haiwan</translation>
 <translation id="5715150588940290235">Padamkan kod keselamatan yang disimpan?</translation>
@@ -2816,6 +2825,7 @@
 <translation id="6085149458302186532">Label (Berwarna)</translation>
 <translation id="6087312102907839798">Carian berkaitan</translation>
 <translation id="6089505343295765444">Tab yang anda padamkan daripada sejarah Chrome anda akan tetap dipaparkan dalam jadual perbandingan anda</translation>
+<translation id="6093599771645355227">Kuning 1</translation>
 <translation id="6093795393556121384">Kad anda disahkan</translation>
 <translation id="6094273045989040137">Anotasi</translation>
 <translation id="6094290315941448991">Dasar pentadbir melumpuhkan rakaman skrin apabila kandungan sulit kelihatan</translation>
@@ -3354,6 +3364,7 @@
 <translation id="7058774143982824355">Perkhidmatan Penghurai Kata Laluan CSV</translation>
 <translation id="7062635574500127092">Hijau kebiruan</translation>
 <translation id="706295145388601875">Tambah dan urus alamat dalam tetapan Chrome</translation>
+<translation id="7063157783216323487">Hijau 2</translation>
 <translation id="7064443976734085921">Kereta Kompak</translation>
 <translation id="7064851114919012435">Maklumat hubungan</translation>
 <translation id="7067633076996245366">Soul &amp; R&amp;B</translation>
@@ -3906,6 +3917,7 @@
 <translation id="8028698320761417183"><ph name="CREATE_GOOGLE_FORM_FOCUSED_FRIENDLY_MATCH_TEXT" />, tekan kekunci Tab kemudian Enter untuk membuat borang baharu dalam Google Forms dengan pantas</translation>
 <translation id="8028892419725165118">Permainan Kasual</translation>
 <translation id="8028960012888758725">Pangkas selepas tugasan</translation>
+<translation id="8029829038322015001">Merah 1</translation>
 <translation id="8030729864112325446">Pendidikan Vokasional &amp; Berterusan</translation>
 <translation id="8032546467100845887">Kelutsinaran</translation>
 <translation id="8035152190676905274">Pen</translation>
@@ -3913,6 +3925,7 @@
 <translation id="8037117624646282037">Orang yang menggunakan peranti ini baru-baru ini</translation>
 <translation id="8037357227543935929">Tanya (lalai)</translation>
 <translation id="803771048473350947">Fail</translation>
+<translation id="8038182528865038593">Merah 2</translation>
 <translation id="8041089156583427627">Hantar Maklum Balas</translation>
 <translation id="8041940743680923270">Gunakan lalai global (Tanya)</translation>
 <translation id="8043255123207491407">Lihat terma dan syarat penjual</translation>
@@ -4313,6 +4326,7 @@
 <translation id="8767881944435256294">{COUNT,plural, =1{1 kaedah pembayaran}other{# kaedah pembayaran}}</translation>
 <translation id="8768225988514678921">Butang buat pembentangan, aktifkan untuk membuat pembentangan Google dalam Slides dengan pantas</translation>
 <translation id="8769662576926275897">Butiran kad</translation>
+<translation id="8769858749286369844">Perang 2</translation>
 <translation id="8770286973007342895">Pemotong Rumput</translation>
 <translation id="8772387130037509473">Yoga &amp; Pilates</translation>
 <translation id="877348612833018844">{0,plural, =1{Alihkan fail sulit?}other{Alihkan fail sulit?}}</translation>
@@ -4404,6 +4418,7 @@
 <translation id="8956124158020778855">Selepas anda menghidupkan tetapan ini, kembali kepada tab ini untuk mula menulis.</translation>
 <translation id="8957210676456822347">Keizinan Portal Tawanan</translation>
 <translation id="8959282183248574156"><ph name="NICKNAME_COUNT" />/<ph name="NICKNAME_MAX" /></translation>
+<translation id="8959288490306482616">Perang 3</translation>
 <translation id="8963117664422609631">Pergi ke tetapan laman</translation>
 <translation id="8963213021028234748"><ph name="MARKUP_1" />Cadangan:<ph name="MARKUP_2" />Pastikan anda mempunyai sambungan data<ph name="MARKUP_3" />Muatkan semula halaman web ini kemudian<ph name="MARKUP_4" />Semak alamat yang anda masukkan<ph name="MARKUP_5" /></translation>
 <translation id="8968766641738584599">Simpan kad</translation>
@@ -4466,6 +4481,7 @@
 <translation id="90695670378604968">Plastik (Kusam)</translation>
 <translation id="9069693763241529744">Disekat oleh sambungan</translation>
 <translation id="9073799351042754113">Anda telah memilih untuk mematikan amaran keselamatan untuk laman ini.</translation>
+<translation id="9075717835386447447">Perang 1</translation>
 <translation id="9076283476770535406">Tapak mungkin mengandungi kandungan dewasa</translation>
 <translation id="9078912659001679888">Pengisar &amp; Pemerah Jus</translation>
 <translation id="9078964945751709336">Maklumat lanjut diperlukan</translation>
@@ -4575,6 +4591,7 @@
 <translation id="949314938206378263">Anda meminta untuk melawat laman ini. Ibu bapa anda boleh membalas dalam Family Link.</translation>
 <translation id="950736567201356821">Tiga tebukan atas</translation>
 <translation id="950926967802086924">Kunci laluan • Google Password Manager</translation>
+<translation id="95721182352849470">Kuning 2</translation>
 <translation id="961663415146723894">Ikatan bawah</translation>
 <translation id="961856697154696964">Padamkan data semakan imbas</translation>
 <translation id="961930410699694996">Lokasi dibenarkan pada masa ini</translation>
diff --git a/components/strings/components_strings_my.xtb b/components/strings/components_strings_my.xtb
index 0628d9c8..f37f868 100644
--- a/components/strings/components_strings_my.xtb
+++ b/components/strings/components_strings_my.xtb
@@ -169,6 +169,7 @@
 <translation id="129553762522093515">မကြာသေးခင်က ပိတ်ထားခဲ့သည်</translation>
 <translation id="1296930489679394997">လျှော့ဈေး</translation>
 <translation id="1297814096526086484">ကီးဘုတ်နှင့် မောက်စ်ကို လော့ခ်ချမလား။</translation>
+<translation id="1297832388362139384">အစိမ်း ၁</translation>
 <translation id="1301227606947843452">လီဂယ်ဆိုဒ်ကြီး</translation>
 <translation id="1301324364792935241">သင်၏ 'လုံခြုံသော DNS' ဆက်တင်များကို စစ်ဆေးပါ</translation>
 <translation id="1302418742166945866"><ph name="URL" /> က သင့် MIDI စက်များကို စီမံပြီး ပရိုဂရမ်ပြန်လုပ်လိုသည်</translation>
@@ -228,6 +229,7 @@
 <translation id="1384725838384960382">လုံခြုံသောပေးချေမှု အထောက်အထား စိစစ်ခြင်းစာရွက်</translation>
 <translation id="1386623374109090026">မှတ်ချက်များ</translation>
 <translation id="138810468159004008">ဝဘ်ဆိုက်ဝင်ကြည့်နေစဉ် ခွင့်ပြုရန်</translation>
+<translation id="139161720020179799">မီးခိုးရင့် ၁</translation>
 <translation id="1391625539203220400">ဤစက်တွင် IBAN သိမ်းမလား။</translation>
 <translation id="139305205187523129"><ph name="HOST_NAME" /> သည်မည်သည့် ဒေတာမျှ မပို့ခဲ့ပါ။</translation>
 <translation id="1393071644879491291">သင်ဝင်ကြည့်ရန်ကြိုးပမ်းသည့် ဝဘ်ဆိုက်ရှိ တိုက်ခိုက်သူများသည် ဆော့ဖ်ဝဲထည့်သွင်းရန် သို့မဟုတ် စကားဝှက်၊ ဖုန်း (သို့) ခရက်ဒစ်ကတ်နံပါတ်ကဲ့သို့သော အရာများပြရန် သင့်ကိုလှည့်စားနိုင်သည်။ ဘေးကင်းရာသို့ ပြန်သွားရန် Chrome က အထူးအကြံပြုပါသည်။ <ph name="BEGIN_LEARN_MORE_LINK" />ဤသတိပေးချက်အကြောင်း ပိုမိုလေ့လာရန်<ph name="END_LEARN_MORE_LINK" /></translation>
@@ -704,6 +706,7 @@
 <translation id="2227758700723188171">ပညာသင်ထောက်ပံ့ကြေး၊ ပညာသင်ဆု</translation>
 <translation id="2228057197024893428">ဤလိပ်စာကို Chrome တွင် လောလောဆယ် သိမ်းထားသည်။ Google ထုတ်ကုန်များတွင် ၎င်းကိုသုံးရန် သင်၏ Google Account ဖြစ်သော <ph name="ACCOUNT" /> တွင်သိမ်းပါ။</translation>
 <translation id="2229456043301340598">လျစ်လျူရှုထားသော သီးသန့်မဟုတ်သည့် ဖြတ်လမ်းလင့်ခ်- <ph name="SHORTCUT_NAME" /></translation>
+<translation id="222962001646502673">မီးခိုးရင့် ၂</translation>
 <translation id="2233041017768270281">{COUNT,plural, =1{တဘ် ၁ ခု}other{တဘ် # ခု}}</translation>
 <translation id="2233745931693710080">စီဒီခွေ</translation>
 <translation id="2235344399760031203">ပြင်ပအဖွဲ့အစည်း၏ ကွတ်ကီးများကို ပိတ်ထားသည်</translation>
@@ -1730,6 +1733,7 @@
 <translation id="4084219288110917128">C1 စာအိတ်</translation>
 <translation id="4085326869263783566">ကူရေးပေးပါ။ ဖွင့်ရန် ‘တဘ်’ နှင့် ‘Enter ခလုတ်’ နှိပ်ပါ</translation>
 <translation id="4085769736382018559">ထုတ်ကုန်များ နှိုင်းယှဉ်ခြင်း</translation>
+<translation id="4085778582400064057">အပြာ ၂</translation>
 <translation id="4088981014127559358">ဘေး ၁ ပုံ ဒေါင်လိုက် အရွှေ့</translation>
 <translation id="4089152113577680600">ဗန်း ၁၄</translation>
 <translation id="4092349052316400070">လိပ်စာ ဖြည့်ရန်</translation>
@@ -1974,6 +1978,7 @@
 <translation id="4509074745930862522"><ph name="TRANSLATE_FOCUSED_FRIENDLY_MATCH_TEXT" />၊ ဤစာမျက်နှာကို Google Translate ဖြင့်ဘာသာပြန်ရန် Tab နှိပ်ပြီးနောက် Enter နှိပ်ပါ</translation>
 <translation id="4515275063822566619">ကဒ်နှင့် လိပ်စာများသည် Chrome နှင့် သင်၏ Google အကောင့် (<ph name="ACCOUNT_EMAIL" />) မှဖြစ်သည်။ ၎င်းတို့ကို <ph name="BEGIN_LINK" />ဆက်တင်များ<ph name="END_LINK" /> တွင် စီမံခန့်ခွဲနိုင်သည်။</translation>
 <translation id="4515847625438516456">ကားသေး၊ ကားငယ်</translation>
+<translation id="451601984112574365">အစိမ်း ၃</translation>
 <translation id="4519245469315452746">အပ်ဒိတ်လုပ်ငန်းစဉ်အတွင်း သင့်စက် ရပ်တန့်သွားသည်။</translation>
 <translation id="4520048001084013693">ဤဖိုင် ဒေါင်းလုဒ်လုပ်ခြင်းကို စီမံခန့်ခွဲသူမူဝါဒက ပိတ်ထားသည်</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> mm (<ph name="ORIENTATION" />)</translation>
@@ -2182,6 +2187,7 @@
 <translation id="4901952598169637881">ထသွားထလာ ရှူးဖိနပ်</translation>
 <translation id="4905659621780993806">သင့်စီမံခန့်ခွဲသူက စက်ကို <ph name="DATE" />၊ <ph name="TIME" /> တွင် အလိုအလျောက်ပြန်စမည်။ ဖွင့်ထားသောဖိုင်အားလုံး သင့်စက်ပြန်မစမီ သိမ်းပါ။</translation>
 <translation id="4913987521957242411">ဘယ်ဘက်ထိပ်တွင် ဖောက်ရန်</translation>
+<translation id="4914727764832832057">အပြာ ၁</translation>
 <translation id="4916389289686916969">ဖြစ်ရပ်မှန် TV ရှိုး</translation>
 <translation id="4917064667437236721">ပုံထုတ်သည့် ဆလင်ဒါ</translation>
 <translation id="4918221908152712722"><ph name="APP_NAME" /> ကို ထည့်သွင်းပါ (ဒေါင်းလုဒ်လုပ်ရန် မလိုပါ)</translation>
@@ -2255,6 +2261,7 @@
 <translation id="5039804452771397117">ခွင့်ပြုရန်</translation>
 <translation id="5040262127954254034">ကိုယ်ရေးအချက်အလက်လုံခြုံမှု</translation>
 <translation id="5043480802608081735">သင် မိတ္တူကူးထားသော လင့်ခ်</translation>
+<translation id="5043753287208271200">အဝါ ၃</translation>
 <translation id="5045550434625856497">စကားဝှက် မမှန်ပါ</translation>
 <translation id="5048293684454354469">ကြော်ငြာအကြောင်းအရာများသည် ကြော်ငြာများ ပုဂ္ဂိုလ်ရေးသီးသန့်ပြုလုပ်ရာတွင် ဝဘ်ဆိုက်က သုံးနိုင်သည့် အရာများထဲမှ တစ်ခုဖြစ်သည်။ ကြော်ငြာအကြောင်းအရာများ မရှိသည့်တိုင် ဝဘ်ဆိုက်များက သင့်အား ကြော်ငြာပြနိုင်သော်လည်း ၎င်းတို့ကို ပုဂ္ဂိုလ်ရေးသီးသန့်သိပ်လုပ်မထားပါ။ <ph name="BEGIN_LINK" />သင့်ကြော်ငြာဆိုင်ရာ အချက်အလက်လုံခြုံမှုကို စီမံခြင်း<ph name="LINK_END" /> အကြောင်း ပိုမိုလေ့လာနိုင်သည်။</translation>
 <translation id="5052517576853118371">ဖွင့်ထားသည့် အကြောင်းအရာများ</translation>
@@ -2561,6 +2568,7 @@
 <translation id="5593640815048812868">လက်ပ်တော့၊ နုတ်ဘုတ်ကွန်ပျူတာ</translation>
 <translation id="5595485650161345191">လိပ်စာ တည်းဖြတ်ရန်</translation>
 <translation id="5596939519753369075">၂ x ၃.၅ လက်မ</translation>
+<translation id="5597254438174353289">အပြာ ၃</translation>
 <translation id="560412284261940334">စီမံရေးရာမှ အကူအညီမရနိုင်ပါ။</translation>
 <translation id="5605249000617390290">ဈေးနှုန်းခြေရာခံခြင်းအကြောင်း ပိုမိုလေ့လာရန်</translation>
 <translation id="5605670050355397069">လယ်ဂျာ</translation>
@@ -2616,6 +2624,7 @@
 <translation id="5701381305118179107">အလယ်</translation>
 <translation id="5707154300732650394">သင့်ခရီးစဉ်ကို ဆက်လုပ်ရန်</translation>
 <translation id="57094364128775171">ခိုင်မာသည့် စကားဝှက် အကြံပြုရန်…</translation>
+<translation id="570953204696852961">အနီ ၃</translation>
 <translation id="571403275720188526">(arm64)</translation>
 <translation id="571510845185711675">တိရစ္ဆာန်ကုဆရာဝန်များ</translation>
 <translation id="5715150588940290235">သိမ်းထားသော လုံခြုံရေးကုဒ်များကို ဖျက်မလား။</translation>
@@ -2816,6 +2825,7 @@
 <translation id="6085149458302186532">လေဘယ်လ် (အရောင်)</translation>
 <translation id="6087312102907839798">ဆက်စပ်သော ရှာဖွေမှုများ</translation>
 <translation id="6089505343295765444">သင့် Chrome မှတ်တမ်းမှ ဖျက်လိုက်သော တဘ်များကို သင်၏နှိုင်းယှဉ်မှုဇယားများတွင် ဆက်ပြပါမည်</translation>
+<translation id="6093599771645355227">အဝါ ၁</translation>
 <translation id="6093795393556121384">သင့်ကဒ်အား အတည်ပြုစိစစ်ပြီးဖြစ်၏</translation>
 <translation id="6094273045989040137">မှတ်ချက်ပေးရန်</translation>
 <translation id="6094290315941448991">လျှို့ဝှက်အကြောင်းအရာများကို မြင်နိုင်ချိန်တွင် ဖန်သားပြင်ရိုက်ကူးခြင်းကို စီမံခန့်ခွဲသူမူဝါဒက ပိတ်ထားသည်</translation>
@@ -3353,6 +3363,7 @@
 <translation id="7058774143982824355">CSV စကားဝှက် ပါဆာ ဝန်ဆောင်မှု</translation>
 <translation id="7062635574500127092">စိမ်းပြာရင့်</translation>
 <translation id="706295145388601875">Chrome ဆက်တင်များတွင် လိပ်စာများထည့်ရန်နှင့် စီမံရန်</translation>
+<translation id="7063157783216323487">အစိမ်း ၂</translation>
 <translation id="7064443976734085921">ကားသေး</translation>
 <translation id="7064851114919012435">ဆက်သွယ်ရန်အချက်အလက်</translation>
 <translation id="7067633076996245366">ဆိုးလ်နှင့် R&amp;B</translation>
@@ -3906,6 +3917,7 @@
 <translation id="8028698320761417183"><ph name="CREATE_GOOGLE_FORM_FOCUSED_FRIENDLY_MATCH_TEXT" />၊ Google Forms တွင် ဖောင်အသစ် အမြန်ပြုလုပ်ရန် ‘တဘ်’ နှိပ်ပြီးနောက် Enter ခလုတ် နှိပ်ပါ</translation>
 <translation id="8028892419725165118">ရိုးရိုး ဂိမ်း</translation>
 <translation id="8028960012888758725">အလုပ်ပြီးလျှင် ဖြတ်ထုတ်ရန်</translation>
+<translation id="8029829038322015001">အနီ ၁</translation>
 <translation id="8030729864112325446">အသက်မွေးမှု၊ စဉ်ဆက်မပြတ်ပညာရေး</translation>
 <translation id="8032546467100845887">အလင်းပေါက်</translation>
 <translation id="8035152190676905274">ဘောပင်</translation>
@@ -3913,6 +3925,7 @@
 <translation id="8037117624646282037">ဤစက်ပစ္စည်းကို လတ်တလော အသုံးပြုထားသူများ</translation>
 <translation id="8037357227543935929">မေးရန် (မူရင်း)</translation>
 <translation id="803771048473350947">ဖိုင်</translation>
+<translation id="8038182528865038593">အနီ ၂</translation>
 <translation id="8041089156583427627">အကြံပြုချက် ပို့ရန်</translation>
 <translation id="8041940743680923270">အထွေထွေ ပုံသေကို သုံးပါ(မေးရန်)</translation>
 <translation id="8043255123207491407">ရောင်းသူ၏ ဝန်ဆောင်မှုစည်းမျဉ်းများကို ကြည့်ပါ</translation>
@@ -4312,6 +4325,7 @@
 <translation id="8767881944435256294">{COUNT,plural, =1{ငွေပေးချေနည်းလမ်း ၁ ခု}other{ငွေပေးချေနည်းလမ်း # ခု}}</translation>
 <translation id="8768225988514678921">Slides တွင် Google တင်ပြမှုအသစ် အမြန်ပြုလုပ်ရန်အတွက် ‘တင်ပြမှု ပြုလုပ်ရန်’ ခလုတ်ကို နှိပ်နိုင်သည်</translation>
 <translation id="8769662576926275897">ကဒ်အသေးစိတ်</translation>
+<translation id="8769858749286369844">အညို ၂</translation>
 <translation id="8770286973007342895">မြက်ရိတ်စက်</translation>
 <translation id="8772387130037509473">ယောဂနှင့် ပီလတိစ်</translation>
 <translation id="877348612833018844">{0,plural, =1{လျှို့ဝှက်ဖိုင်ကို ရွှေ့မလား။}other{လျှို့ဝှက်ဖိုင်များကို ရွှေ့မလား။}}</translation>
@@ -4403,6 +4417,7 @@
 <translation id="8956124158020778855">ဤဆက်တင်ကို ဖွင့်ပြီးနောက် စရေးရန် ဤတဘ်သို့ ပြန်လာပါ။</translation>
 <translation id="8957210676456822347">ထွက်ပေါက်မရှိသော မူလအင်တာနက်စာမျက်နှာ ခွင့်ပြူချက်</translation>
 <translation id="8959282183248574156"><ph name="NICKNAME_COUNT" />/<ph name="NICKNAME_MAX" /></translation>
+<translation id="8959288490306482616">အညို ၃</translation>
 <translation id="8963117664422609631">ဝဘ်ဆိုက်ဆက်တင်များသို့ သွားရန်</translation>
 <translation id="8963213021028234748"><ph name="MARKUP_1" />အကြံပေးချက်များ:<ph name="MARKUP_2" />သင့်ဆီတွင် ဒေတာ ချိတ်ဆက်မှု ရှိနေတာ စစ်ကြည့်ပါ<ph name="MARKUP_3" />ဒီဝက်ဘ်စာမျက်နှာကို နောက်မှာ ပြန်တင်ပါ<ph name="MARKUP_4" />သင် ထည့်ပေးခဲ့တဲ့ လိပ်စာကို စစ်ကြည့်ပါ<ph name="MARKUP_5" /></translation>
 <translation id="8968766641738584599">ကတ်သိမ်းရန်</translation>
@@ -4465,6 +4480,7 @@
 <translation id="90695670378604968">ပလတ်စတစ် (မှိုင်းပျပျ)</translation>
 <translation id="9069693763241529744">နောက်ဆက်တွဲတစ်ခုက ပိတ်ဆို့ထားခြင်းဖြစ်သည်</translation>
 <translation id="9073799351042754113">ဤဝဘ်ဆိုက်အတွက် လုံခြုံရေးသတိပေးချက်များကို ပိတ်ရန် သင်ရွေးချယ်ထားပါသည်။</translation>
+<translation id="9075717835386447447">အညို ၁</translation>
 <translation id="9076283476770535406">၎င်းတွင် အရွယ်ရောက်ပြီးသူများသာ ကြည့်နိုင်သည့် အကြောင်းအရာများ ပါဝင်နိုင်ပါသည်</translation>
 <translation id="9078912659001679888">မွှေစက်နှင့် သစ်သီးညှစ်စက်</translation>
 <translation id="9078964945751709336">နောက်ထပ် အချက်အလက်များ လိုအပ်ပါသည်</translation>
@@ -4574,6 +4590,7 @@
 <translation id="949314938206378263">ဤဝဘ်ဆိုက်သို့ ဝင်ကြည့်ရန် သင်တောင်းဆိုထားသည်။ Family Link တွင် သင့်မိဘက စာပြန်နိုင်သည်။</translation>
 <translation id="950736567201356821">ထိပ်တွင် သုံးချက်ဖောက်ရန်</translation>
 <translation id="950926967802086924">လျှို့ဝှက်ကီး • Google Password Manager</translation>
+<translation id="95721182352849470">အဝါ ၂</translation>
 <translation id="961663415146723894">အောက်ခြေတွင် တွဲချုပ်ရန်</translation>
 <translation id="961856697154696964">ဖွင့်ကြည့်ထားသည့်မှတ်တမ်းဒေတာ ဖျက်ရန်</translation>
 <translation id="961930410699694996">ဤတစ်ကြိမ်အတွက် တည်နေရာ ခွင့်ပြုထားသည်</translation>
diff --git a/components/strings/components_strings_ne.xtb b/components/strings/components_strings_ne.xtb
index 3b7365c..c9a49d8 100644
--- a/components/strings/components_strings_ne.xtb
+++ b/components/strings/components_strings_ne.xtb
@@ -4531,6 +4531,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" /> ले असमर्थित प्रोटोकल प्रयोग गर्दछ।</translation>
 <translation id="918454845714257218"><ph name="SIDE_OF_CARD" /> मा भएको कोड जाँच गर्नुहोस् र फेरि प्रयास गर्नुहोस्</translation>
 <translation id="9186203289258525843">Chrome लाई सिस्टमको डिफल्ट ब्राउजर बनाउने बटन, Chrome लाई सिस्टमको डिफल्ट ब्राउजर बनाउन यो बटन थिच्नुहोस्</translation>
+<translation id="9189789270972826888">कार्डका विवरणहरू स्वतः भरिएको छैन भने तल दिइएका विवरणहरूमा क्लिक गरी तिनलाई कपी र पेस्ट गर्नुहोस्। <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">४ हप्ताभन्दा पुराना विषयहरू स्वतः मेटाइन्छन्</translation>
 <translation id="9191834167571392248">फेदको बायाँपट्टि प्वाल</translation>
 <translation id="9192361865877479444">मेटल (म्याट)</translation>
diff --git a/components/strings/components_strings_pa.xtb b/components/strings/components_strings_pa.xtb
index df283c141..7d7442a 100644
--- a/components/strings/components_strings_pa.xtb
+++ b/components/strings/components_strings_pa.xtb
@@ -169,6 +169,7 @@
 <translation id="129553762522093515">ਹਾਲ ਵਿੱਚ ਹੀ ਬੰਦ ਕੀਤੇ</translation>
 <translation id="1296930489679394997">ਸੇਲਾਂ</translation>
 <translation id="1297814096526086484">ਕੀ ਤੁਹਾਡੇ ਕੀ-ਬੋਰਡ ਅਤੇ ਮਾਊਸ ਨੂੰ ਲਾਕ ਕਰਨਾ ਹੈ?</translation>
+<translation id="1297832388362139384">ਹਰਾ 1</translation>
 <translation id="1301227606947843452">ਲੀਗਲ ਐਕਸਟਰਾ</translation>
 <translation id="1301324364792935241">ਆਪਣੀਆਂ ਸੁਰੱਖਿਅਤ DNS ਸੈਟਿੰਗਾਂ ਦੀ ਜਾਂਚ ਕਰੋ</translation>
 <translation id="1302418742166945866"><ph name="URL" /> ਤੁਹਾਡੇ MIDI ਡੀਵਾਈਸਾਂ ਨੂੰ ਕੰਟਰੋਲ ਅਤੇ ਰੀ-ਪ੍ਰੋਗਰਾਮ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ</translation>
@@ -228,6 +229,7 @@
 <translation id="1384725838384960382">ਸੁਰੱਖਿਅਤ ਭੁਗਤਾਨ ਕ੍ਰੀਡੈਂਸ਼ੀਅਲ ਪ੍ਰਮਾਣੀਕਰਨ ਸ਼ੀਟ</translation>
 <translation id="1386623374109090026">ਐਨੋਟੇਸ਼ਨਾਂ</translation>
 <translation id="138810468159004008">ਸਾਈਟ 'ਤੇ ਜਾਣ ਵੇਲੇ ਆਗਿਆ ਦਿਓ</translation>
+<translation id="139161720020179799">ਗੂੜ੍ਹਾ ਸਲੇਟੀ 1</translation>
 <translation id="1391625539203220400">ਕੀ IBAN ਨੂੰ ਇਸ ਡੀਵਾਈਸ 'ਤੇ ਰੱਖਿਅਤ ਕਰਨਾ ਹੈ?</translation>
 <translation id="139305205187523129"><ph name="HOST_NAME" /> ਨੇ ਕੋਈ ਵੀ  ਡਾਟਾ  ਨਹੀਂ ਭੇਜਿਆ।</translation>
 <translation id="1393071644879491291">ਜਿਸ ਸਾਈਟ 'ਤੇ ਤੁਸੀਂ ਜਾਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ, ਉਸ 'ਤੇ ਹਮਲਾਵਰ ਤੁਹਾਨੂੰ ਸਾਫ਼ਟਵੇਅਰ ਸਥਾਪਤ ਕਰਨ ਜਾਂ ਤੁਹਾਡੇ ਪਾਸਵਰਡਾਂ, ਫ਼ੋਨ ਜਾਂ ਕ੍ਰੈਡਿਟ ਕਾਰਡ ਨੰਬਰਾਂ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਨੂੰ ਜ਼ਾਹਰ ਕਰਨ ਲਈ ਭਰਮਾ ਸਕਦੇ ਹਨ। Chrome ਤੁਹਾਨੂੰ ਇਸ ਸਾਈਟ 'ਤੇ ਨਾ ਜਾਣ ਦੀ ਜ਼ੋਰਦਾਰ ਸਿਫ਼ਾਰਸ਼ ਕਰਦਾ ਹੈ। <ph name="BEGIN_LEARN_MORE_LINK" />ਇਸ ਚਿਤਾਵਨੀ ਬਾਰੇ ਹੋਰ ਜਾਣੋ<ph name="END_LEARN_MORE_LINK" /></translation>
@@ -703,6 +705,7 @@
 <translation id="2227758700723188171">ਪੜ੍ਹਾਈ ਲਈ ਅਨੁਦਾਨ ਅਤੇ ਵਜ਼ੀਫ਼ੇ</translation>
 <translation id="2228057197024893428">ਇਹ ਪਤਾ ਫ਼ਿਲਹਾਲ Chrome 'ਤੇ ਰੱਖਿਅਤ ਹੈ। ਇਸਨੂੰ ਸਾਰੇ Google ਉਤਪਾਦਾਂ ਵਿੱਚ ਵਰਤਣ ਲਈ, ਇਸਨੂੰ ਆਪਣੇ Google ਖਾਤੇ, <ph name="ACCOUNT" /> ਵਿੱਚ ਰੱਖਿਅਤ ਕਰੋ।</translation>
 <translation id="2229456043301340598">ਗੈਰ-ਵਿਲੱਖਣ ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਅਣਡਿੱਠ ਕੀਤਾ ਗਿਆ: <ph name="SHORTCUT_NAME" /></translation>
+<translation id="222962001646502673">ਗੂੜ੍ਹਾ ਸਲੇਟੀ 2</translation>
 <translation id="2233041017768270281">{COUNT,plural, =1{1 ਟੈਬ}one{# ਟੈਬ}other{# ਟੈਬਾਂ}}</translation>
 <translation id="2233745931693710080">ਕੌਮਪੈਕਟ ਡਿਸਕ</translation>
 <translation id="2235344399760031203">ਤੀਜੀ-ਧਿਰ ਦੀਆਂ ਕੁਕੀਜ਼ ਨੂੰ ਬਲਾਕ ਕੀਤਾ ਗਿਆ ਹੈ</translation>
@@ -1727,6 +1730,7 @@
 <translation id="4084219288110917128">C1 ਆਕਾਰ ਦਾ ਲਿਫ਼ਾਫ਼ਾ</translation>
 <translation id="4085326869263783566">ਲਿਖਣ ਵਿੱਚ ਮੇਰੀ ਮਦਦ ਕਰੋ। ਖੋਲ੍ਹਣ ਲਈ ਟੈਬ ਕਰੋ ਅਤੇ Enter ਦਬਾਓ</translation>
 <translation id="4085769736382018559">ਉਤਪਾਦਾਂ ਦੀ ਤੁਲਨਾ ਕਰੋ</translation>
+<translation id="4085778582400064057">ਨੀਲਾ 2</translation>
 <translation id="4088981014127559358">ਸਾਈਡ 1 ਚਿੱਤਰ Y ਸ਼ਿਫਟ</translation>
 <translation id="4089152113577680600">ਟ੍ਰੇਅ 14</translation>
 <translation id="4092349052316400070">ਪਤਾ ਭਰੋ</translation>
@@ -1970,6 +1974,7 @@
 <translation id="4509074745930862522"><ph name="TRANSLATE_FOCUSED_FRIENDLY_MATCH_TEXT" />, Tab ਦਬਾਓ, ਫਿਰ Google Translate ਨਾਲ ਇਸ ਪੰਨੇ ਦਾ ਅਨੁਵਾਦ ਕਰਨ ਲਈ Enter ਦਬਾਓ</translation>
 <translation id="4515275063822566619">ਕਾਰਡ ਅਤੇ ਪਤੇ Chrome ਅਤੇ ਤੁਹਾਡੇ Google ਖਾਤੇ (<ph name="ACCOUNT_EMAIL" />) ਤੋਂ ਹਨ। ਤੁਸੀਂ ਉਹਨਾਂ ਦਾ ਪ੍ਰਬੰਧਨ <ph name="BEGIN_LINK" />ਸੈਟਿੰਗਾਂ<ph name="END_LINK" /> ਵਿੱਚ ਕਰ ਸਕਦੇ ਹੋ।</translation>
 <translation id="4515847625438516456">ਮਾਈਕ੍ਰੋਕਾਰਾਂ ਅਤੇ ਸਬਕੰਪੈਕਟ</translation>
+<translation id="451601984112574365">ਹਰਾ 3</translation>
 <translation id="4519245469315452746">ਅੱਪਡੇਟ ਪ੍ਰਕਿਰਿਆ ਦੌਰਾਨ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਵਿੱਚ ਕੋਈ ਰੁਕਾਵਟ ਆਈ ਸੀ।</translation>
 <translation id="4520048001084013693">ਪ੍ਰਸ਼ਾਸਕ ਨੀਤੀ ਵੱਲੋਂ ਇਸ ਫ਼ਾਈਲ ਨੂੰ ਡਾਊਨਲੋਡ ਕਰਨ ਦੀ ਸੁਵਿਧਾ ਨੂੰ ਬਲਾਕ ਕੀਤਾ ਗਿਆ ਹੈ</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> ਮਿ.ਮੀ. (<ph name="ORIENTATION" />)</translation>
@@ -2178,6 +2183,7 @@
 <translation id="4901952598169637881">ਆਮ ਜੁੱਤੇ</translation>
 <translation id="4905659621780993806">ਤੁਹਾਡਾ ਪ੍ਰਸ਼ਾਸਕ <ph name="DATE" /> ਨੂੰ <ph name="TIME" /> ਵਜੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨੂੰ ਸਵੈਚਲਿਤ ਤੌਰ 'ਤੇ ਮੁੜ-ਸ਼ੁਰੂ ਕਰੇਗਾ। ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਮੁੜ-ਸ਼ੁਰੂ ਹੋਣ ਤੋਂ ਪਹਿਲਾਂ, ਖੁੱਲੀ ਹੋਈ ਕਿਸੇ ਵੀ ਆਈਟਮ ਨੂੰ ਰੱਖਿਅਤ ਕਰੋ।</translation>
 <translation id="4913987521957242411">ਉੱਪਰ ਖੱਬੇ ਪਾਸੇ ਮੋਰੀ</translation>
+<translation id="4914727764832832057">ਨੀਲਾ 1</translation>
 <translation id="4916389289686916969">ਟੀਵੀ ਰਿਐਲਟੀ ਸ਼ੋਅ</translation>
 <translation id="4917064667437236721">ਇਮੇਜਿੰਗ ਸਿਲੰਡਰ</translation>
 <translation id="4918221908152712722"><ph name="APP_NAME" /> ਸਥਾਪਤ ਕਰੋ (ਕੋਈ ਡਾਊਨਲੋਡ ਲੋੜੀਂਦਾ ਨਹੀਂ ਹੈ)</translation>
@@ -2251,6 +2257,7 @@
 <translation id="5039804452771397117">ਆਗਿਆ ਦਿਓ</translation>
 <translation id="5040262127954254034">ਪਰਦੇਦਾਰੀ</translation>
 <translation id="5043480802608081735">ਤੁਹਾਡੇ ਵੱਲੋਂ ਕਾਪੀ ਕੀਤਾ ਲਿੰਕ</translation>
+<translation id="5043753287208271200">ਪੀਲਾ 3</translation>
 <translation id="5045550434625856497">ਗਲਤ ਪਾਸਵਰਡ</translation>
 <translation id="5048293684454354469">ਵਿਗਿਆਪਨ ਦੇ ਵਿਸ਼ੇ ਕਈ ਚੀਜ਼ਾਂ ਵਿੱਚੋਂ ਬਸ ਇੱਕ ਹਨ, ਜਿਨ੍ਹਾਂ ਦੀ ਵਰਤੋਂ ਸਾਈਟ ਵਿਗਿਆਪਨਾਂ ਨੂੰ ਵਿਅਕਤੀਗਤ ਬਣਾਉਣ ਲਈ ਕਰ ਸਕਦੀ ਹੈ। ਵਿਗਿਆਪਨ ਦੇ ਵਿਸ਼ਿਆਂ ਦੇ ਬਿਨਾਂ ਵੀ, ਸਾਈਟਾਂ ਤੁਹਾਨੂੰ ਹਾਲੇ ਵੀ ਵਿਗਿਆਪਨ ਦਿਖਾ ਸਕਦੀਆਂ ਹਨ, ਪਰ ਉਹ ਘੱਟ ਵਿਅਕਤੀਗਤ ਹੋ ਸਕਦੇ ਹਨ। <ph name="BEGIN_LINK" />ਆਪਣੀ ਵਿਗਿਆਪਨ ਪਰਦੇਦਾਰੀ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ<ph name="LINK_END" /> ਬਾਰੇ ਹੋਰ ਜਾਣੋ।</translation>
 <translation id="5052517576853118371">ਕਿਰਿਆਸ਼ੀਲ ਵਿਸ਼ੇ</translation>
@@ -2557,6 +2564,7 @@
 <translation id="5593640815048812868">ਲੈਪਟਾਪ ਅਤੇ ਨੋਟਬੁੱਕ</translation>
 <translation id="5595485650161345191">ਪਤਾ ਸੰਪਾਦਿਤ ਕਰੋ</translation>
 <translation id="5596939519753369075">2 x 3.5 ਇੰਚ</translation>
+<translation id="5597254438174353289">ਨੀਲਾ 3</translation>
 <translation id="560412284261940334">ਪ੍ਰਬੰਧਨ ਸਮਰਥਿਤ ਨਹੀਂ</translation>
 <translation id="5605249000617390290">ਕੀਮਤ ਦੀ ਟਰੈਕਿੰਗ ਬਾਰੇ ਹੋਰ ਜਾਣੋ</translation>
 <translation id="5605670050355397069">ਵਹੀ-ਖਾਤਾ</translation>
@@ -2612,6 +2620,7 @@
 <translation id="5701381305118179107">ਕੇਂਦਰ</translation>
 <translation id="5707154300732650394">ਆਪਣਾ ਖੋਜ ਸਫ਼ਰ ਨੂੰ ਮੁੜ-ਚਾਲੂ ਕਰੋ</translation>
 <translation id="57094364128775171">ਮਜ਼ਬੂਤ ਪਾਸਵਰਡ ਸੁਝਾਓ…</translation>
+<translation id="570953204696852961">ਲਾਲ 3</translation>
 <translation id="571403275720188526">(arm64)</translation>
 <translation id="571510845185711675">ਪਸ਼ੂ ਚਿਕਿਤਸਕ</translation>
 <translation id="5715150588940290235">ਕੀ ਰੱਖਿਅਤ ਕੀਤੇ ਸੁਰੱਖਿਆ ਕੋਡਾਂ ਨੂੰ ਮਿਟਾਉਣਾ ਹੈ?</translation>
@@ -2812,6 +2821,7 @@
 <translation id="6085149458302186532">ਲੇਬਲ (ਰੰਗੀਨ)</translation>
 <translation id="6087312102907839798">ਸੰਬੰਧਿਤ ਖੋਜਾਂ</translation>
 <translation id="6089505343295765444">ਜਿਨ੍ਹਾਂ ਟੈਬਾਂ ਨੂੰ ਤੁਸੀਂ ਆਪਣੇ Chrome ਇਤਿਹਾਸ ਤੋਂ ਮਿਟਾਉਂਦੇ ਹੋ, ਉਹ ਹਾਲੇ ਵੀ ਤੁਹਾਡੀਆਂ ਤੁਲਨਾ ਸਾਰਨੀਆਂ ਵਿੱਚ ਦਿਖਾਈ ਦੇਣਗੀਆਂ</translation>
+<translation id="6093599771645355227">ਪੀਲਾ 1</translation>
 <translation id="6093795393556121384">ਤੁਹਾਡਾ ਕਾਰਡ ਪ੍ਰਮਾਣਿਤ ਕੀਤਾ ਗਿਆ ਹੈ</translation>
 <translation id="6094273045989040137">ਐਨੋਟੇਟ ਕਰੋ</translation>
 <translation id="6094290315941448991">ਗੁਪਤ ਸਮੱਗਰੀ ਦੇ ਦਿਸਣਯੋਗ ਹੋਣ 'ਤੇ ਪ੍ਰਸ਼ਾਸਕ ਨੀਤੀ ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਬੰਦ ਕਰ ਦਿੰਦੀ ਹੈ</translation>
@@ -3349,6 +3359,7 @@
 <translation id="7058774143982824355">CSV ਪਾਸਵਰਡ ਪਾਰਸਰ ਸੇਵਾ</translation>
 <translation id="7062635574500127092">ਹਰਾ-ਨੀਲਾ</translation>
 <translation id="706295145388601875">Chrome ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਪਤੇ ਸ਼ਾਮਲ ਕਰੋ ਅਤੇ ਉਹਨਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ</translation>
+<translation id="7063157783216323487">ਹਰਾ 2</translation>
 <translation id="7064443976734085921">ਛੋਟੀਆਂ ਕਾਰਾਂ</translation>
 <translation id="7064851114919012435">ਸੰਪਰਕ ਜਾਣਕਾਰੀ</translation>
 <translation id="7067633076996245366">ਸੋਲ ਅਤੇ R&amp;B</translation>
@@ -3900,6 +3911,7 @@
 <translation id="8028698320761417183"><ph name="CREATE_GOOGLE_FORM_FOCUSED_FRIENDLY_MATCH_TEXT" />, Google Forms ਵਿੱਚ ਤੇਜ਼ੀ ਨਾਲ ਨਵਾਂ ਫ਼ਾਰਮ ਬਣਾਉਣ ਲਈ Tab ਦਬਾ ਕੇ ਫਿਰ Enter ਦਬਾਓ</translation>
 <translation id="8028892419725165118">ਬੇਕਾਇਦਾ ਗੇਮਾਂ</translation>
 <translation id="8028960012888758725">ਜੌਬ ਤੋਂ ਬਾਅਦ ਕਟਾਈ</translation>
+<translation id="8029829038322015001">ਲਾਲ 1</translation>
 <translation id="8030729864112325446">ਵੋਕੇਸ਼ਨਲ ਅਤੇ ਅਗਲੇਰੀ ਸਿੱਖਿਆ</translation>
 <translation id="8032546467100845887">ਪਾਰਦਰਸ਼ਤਾ</translation>
 <translation id="8035152190676905274">ਪੈੱਨ</translation>
@@ -3907,6 +3919,7 @@
 <translation id="8037117624646282037">ਹਾਲ ਵਿੱਚ ਹੀ ਇਹ ਡੀਵਾਈਸ ਕਿਸ ਨੇ ਵਰਤਿਆ ਹੈ</translation>
 <translation id="8037357227543935929">ਪੁੱਛੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)</translation>
 <translation id="803771048473350947">ਫਾਈਲ</translation>
+<translation id="8038182528865038593">ਲਾਲ 2</translation>
 <translation id="8041089156583427627">ਵਿਚਾਰ ਭੇਜੋ</translation>
 <translation id="8041940743680923270">ਗਲੋਬਲ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਸੈਟਿੰਗ ਵਰਤੋ (ਪੁੱਛੋ)</translation>
 <translation id="8043255123207491407">ਵਿਕਰੇਤਾ ਦੇ ਨਿਯਮ ਅਤੇ ਸ਼ਰਤਾਂ ਦੇਖੋ</translation>
@@ -4306,6 +4319,7 @@
 <translation id="8767881944435256294">{COUNT,plural, =1{1 ਭੁਗਤਾਨ ਵਿਧੀ}one{# ਭੁਗਤਾਨ ਵਿਧੀ}other{# ਭੁਗਤਾਨ ਵਿਧੀਆਂ}}</translation>
 <translation id="8768225988514678921">'ਪੇਸ਼ਕਾਰੀ ਬਣਾਓ' ਬਟਨ, Slides ਵਿੱਚ ਤੇਜ਼ੀ ਨਾਲ ਨਵੀਂ Google ਪੇਸ਼ਕਾਰੀ ਬਣਾਉਣ ਲਈ ਇਸਨੂੰ ਕਿਰਿਆਸ਼ੀਲ ਕਰੋ</translation>
 <translation id="8769662576926275897">ਕਾਰਡ ਵੇਰਵੇ</translation>
+<translation id="8769858749286369844">ਹਲਕਾ ਭੂਰਾ 2</translation>
 <translation id="8770286973007342895">ਘਾਹ ਕੱਟਣ ਵਾਲੀਆਂ ਮਸ਼ੀਨਾਂ</translation>
 <translation id="8772387130037509473">ਯੋਗਾ ਅਤੇ ਪਾਇਲੇਟ</translation>
 <translation id="877348612833018844">{0,plural, =1{ਕੀ ਗੁਪਤ ਫ਼ਾਈਲ ਨੂੰ ਲਿਜਾਉਣਾ ਹੈ?}one{ਕੀ ਗੁਪਤ ਫ਼ਾਈਲ ਨੂੰ ਲਿਜਾਉਣਾ ਹੈ?}other{ਕੀ ਗੁਪਤ ਫ਼ਾਈਲਾਂ ਨੂੰ ਲਿਜਾਉਣਾ ਹੈ?}}</translation>
@@ -4397,6 +4411,7 @@
 <translation id="8956124158020778855">ਇਸ ਸੈਟਿੰਗ ਨੂੰ ਚਾਲੂ ਕਰਨ ਤੋਂ ਬਾਅਦ, ਲਿਖਣਾ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਇਸ ਟੈਬ 'ਤੇ ਵਾਪਸ ਆਓ।</translation>
 <translation id="8957210676456822347">ਕੈਪਟਿਵ ਪੋਰਟਲ ਇਖਤਿਆਰੀਕਰਨ</translation>
 <translation id="8959282183248574156"><ph name="NICKNAME_COUNT" />/<ph name="NICKNAME_MAX" /></translation>
+<translation id="8959288490306482616">ਹਲਕਾ ਭੂਰਾ 3</translation>
 <translation id="8963117664422609631">ਸਾਈਟ ਦੀਆਂ ਸੈਟਿੰਗਾਂ 'ਤ ਜਾਓ</translation>
 <translation id="8963213021028234748"><ph name="MARKUP_1" />ਸੁਝਾਅ:<ph name="MARKUP_2" />ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਤੁਹਾਡੇ ਕੋਲ ਇੱਕ ਡਾਟਾ ਕਨੈਕਸ਼ਨ ਹੈ<ph name="MARKUP_3" />ਬਾਅਦ ਵਿੱਚ ਇਹ ਵੈਬਸਫ਼ਾ ਰੀਲੋਡ ਕਰੋ<ph name="MARKUP_4" />ਉਸ ਪਤੇ ਦੀ ਜਾਂਚ ਕਰੋ, ਜੋ ਤੁਸੀਂ ਦਰਜ ਕੀਤਾ ਸੀ<ph name="MARKUP_5" /></translation>
 <translation id="8968766641738584599">ਕਾਰਡ ਰੱਖਿਅਤ ਕਰੋ</translation>
@@ -4459,6 +4474,7 @@
 <translation id="90695670378604968">ਪਲਾਸਟਿਕ (ਮੈਟ)</translation>
 <translation id="9069693763241529744">ਕਿਸੇ ਐਕਸਟੈਂਸ਼ਨ ਵੱਲੋਂ ਬਲਾਕ ਕੀਤਾ ਗਿਆ</translation>
 <translation id="9073799351042754113">ਤੁਸੀਂ ਇਸ ਸਾਈਟ ਲਈ ਸੁਰੱਖਿਆ ਚਿਤਾਵਨੀਆਂ ਨੂੰ ਬੰਦ ਕਰਨ ਦੀ ਚੋਣ ਕੀਤੀ ਹੈ।</translation>
+<translation id="9075717835386447447">ਹਲਕਾ ਭੂਰਾ 1</translation>
 <translation id="9076283476770535406">ਇਸ ਵਿੱਚ ਬਾਲਗ ਸਮੱਗਰੀ ਹੋ ਸਕਦੀ ਹੈ</translation>
 <translation id="9078912659001679888">ਬਲੈਂਡਰ ਅਤੇ ਜੂਸਰ</translation>
 <translation id="9078964945751709336">ਹੋਰ ਜਾਣਕਾਰੀ ਲੋੜੀਂਦੀ ਹੈ</translation>
@@ -4567,6 +4583,7 @@
 <translation id="949314938206378263">ਤੁਸੀਂ ਇਸ ਸਾਈਟ 'ਤੇ ਜਾਣ ਲਈ ਕਿਹਾ ਹੈ। ਤੁਹਾਡੇ ਮਾਂ-ਪਿਓ Family Link ਵਿੱਚ ਜਵਾਬ ਦੇ ਸਕਦੇ ਹਨ।</translation>
 <translation id="950736567201356821">ਉੱਪਰ ਤਿੰਨ ਮੋਰੀਆਂ</translation>
 <translation id="950926967802086924">ਪਾਸਕੀ • Google Password Manager</translation>
+<translation id="95721182352849470">ਪੀਲਾ 2</translation>
 <translation id="961663415146723894">ਹੇਠਾਂ ਜਿਲਦਬੰਦ</translation>
 <translation id="961856697154696964">ਬ੍ਰਾਊਜ਼ਿੰਗ ਡਾਟਾ ਮਿਟਾਓ</translation>
 <translation id="961930410699694996">ਇਸ ਸਮੇਂ ਟਿਕਾਣੇ ਦੀ ਆਗਿਆ ਹੈ</translation>
diff --git a/components/strings/components_strings_pl.xtb b/components/strings/components_strings_pl.xtb
index ce01383..16e335d7 100644
--- a/components/strings/components_strings_pl.xtb
+++ b/components/strings/components_strings_pl.xtb
@@ -4533,6 +4533,7 @@
 <translation id="9183425211371246419">Serwer <ph name="HOST_NAME" /> używa nieobsługiwanego protokołu.</translation>
 <translation id="918454845714257218">Sprawdź kod <ph name="SIDE_OF_CARD" /> i spróbuj ponownie</translation>
 <translation id="9186203289258525843">Przycisk Ustaw Chrome jako przeglądarkę domyślną; aktywuj, aby ustawić Chrome jako domyślną przeglądarkę w systemie</translation>
+<translation id="9189789270972826888">Jeśli dane karty nie zostały uzupełnione, kliknij je poniżej, aby je skopiować i wkleić. <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">Tematy starsze niż 4 tygodnie są automatycznie usuwane</translation>
 <translation id="9191834167571392248">Otwór w lewym dolnym rogu</translation>
 <translation id="9192361865877479444">Metal (matowy)</translation>
diff --git a/components/strings/components_strings_ro.xtb b/components/strings/components_strings_ro.xtb
index be7c7f6f..91b8cd55 100644
--- a/components/strings/components_strings_ro.xtb
+++ b/components/strings/components_strings_ro.xtb
@@ -4535,6 +4535,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" /> folosește un protocol neacceptat.</translation>
 <translation id="918454845714257218">Caută codul de pe <ph name="SIDE_OF_CARD" /> și încearcă din nou</translation>
 <translation id="9186203289258525843">Butonul Setează Chrome ca browser prestabilit, activează ca să setezi Chrome ca browser prestabilit pentru sistem</translation>
+<translation id="9189789270972826888">Dă clic pe detaliile cardului de mai jos pentru a le copia și a le insera în cazul în care datele cardului nu au fost completate. <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">Subiectele mai vechi de patru săptămâni se șterg automat</translation>
 <translation id="9191834167571392248">Perforare în stânga jos</translation>
 <translation id="9192361865877479444">Metal (mat)</translation>
diff --git a/components/strings/components_strings_ru.xtb b/components/strings/components_strings_ru.xtb
index 6f80d16..985ec65 100644
--- a/components/strings/components_strings_ru.xtb
+++ b/components/strings/components_strings_ru.xtb
@@ -4533,6 +4533,7 @@
 <translation id="9183425211371246419">На сайте <ph name="HOST_NAME" /> используется неподдерживаемый протокол.</translation>
 <translation id="918454845714257218">Проверьте код <ph name="SIDE_OF_CARD" /> и повторите попытку</translation>
 <translation id="9186203289258525843">Кнопка "Сделать Chrome браузером по умолчанию". Нажмите ее, чтобы сделать Chrome браузером по умолчанию.</translation>
+<translation id="9189789270972826888">Если реквизиты карты не были заполнены, нажмите на поля ниже, чтобы скопировать и подставить указанные в них данные. <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">Темы, добавленные более 4 недель назад, автоматически удаляются</translation>
 <translation id="9191834167571392248">Отверстие в левом нижнем углу</translation>
 <translation id="9192361865877479444">Металл (матовый)</translation>
diff --git a/components/strings/components_strings_sl.xtb b/components/strings/components_strings_sl.xtb
index c6d35262..f62075a 100644
--- a/components/strings/components_strings_sl.xtb
+++ b/components/strings/components_strings_sl.xtb
@@ -705,7 +705,7 @@
 <translation id="2229456043301340598">Prezrta bližnjica, ki ni enolična: <ph name="SHORTCUT_NAME" /></translation>
 <translation id="2233041017768270281">{COUNT,plural, =1{1 zavihek}one{# zavihek}two{# zavihka}few{# zavihki}other{# zavihkov}}</translation>
 <translation id="2233745931693710080">Compact Disc</translation>
-<translation id="2235344399760031203">Piškotki drugih spletnih mest so blokirani</translation>
+<translation id="2235344399760031203">Piškotki tretjih oseb so blokirani</translation>
 <translation id="2239100178324503013">Pošlji</translation>
 <translation id="2241693394036365668">Datoteka je prenesena</translation>
 <translation id="2242389809734574253">Shranjevanje številke IBAN je zaprto.</translation>
@@ -1359,7 +1359,7 @@
 <translation id="3441653493275994384">Zaslon</translation>
 <translation id="3443504041532578451">Optical Disc (Satin)</translation>
 <translation id="344449859752187052">Piškotki tretjih oseb so blokirani</translation>
-<translation id="3447644283769633681">Blokiraj vse piškotke drugih spletnih mest</translation>
+<translation id="3447644283769633681">Blokiraj vse piškotke tretjih oseb</translation>
 <translation id="3447661539832366887">Lastnik te naprave je izklopil igro z dinozavri</translation>
 <translation id="3447884698081792621">Prikaz potrdila (izdal: <ph name="ISSUER" />)</translation>
 <translation id="3450323514459570273">Lahko zahteva nadzor in vnovično programiranje naprav MIDI</translation>
@@ -2874,7 +2874,7 @@
 <translation id="6195163219142236913">Piškotki tretjih oseb so omejeni</translation>
 <translation id="6195371403461054755">Geologija</translation>
 <translation id="6195418151868446719">Potrošniška elektronika</translation>
-<translation id="6196640612572343990">Blokiraj piškotke drugih spletnih mest</translation>
+<translation id="6196640612572343990">Blokiraj piškotke tretjih oseb</translation>
 <translation id="6197648101609735209">89 x 89 mm</translation>
 <translation id="6198480336395236519">Full Cut Tabs</translation>
 <translation id="6203231073485539293">Preverite internetno povezavo</translation>
@@ -4534,6 +4534,7 @@
 <translation id="9183425211371246419">Spletno mesto <ph name="HOST_NAME" /> uporablja nepodprt protokol.</translation>
 <translation id="918454845714257218">Preverite kodo tukaj: <ph name="SIDE_OF_CARD" />, nato poskusite znova.</translation>
 <translation id="9186203289258525843">Gumb za nastavite Chroma kot privzeti brskalnik, aktivirajte, če želite nastaviti Chrome kot privzeti brskalnik sistema</translation>
+<translation id="9189789270972826888">Kliknite podrobnosti kartice spodaj, če želite kopirati in prilepiti, če ni bila izpolnjena. <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">Teme, starejše od 4 tednov, so samodejno izbrisane</translation>
 <translation id="9191834167571392248">Luknjanje spodaj levo</translation>
 <translation id="9192361865877479444">Metal (Matte)</translation>
diff --git a/components/strings/components_strings_sw.xtb b/components/strings/components_strings_sw.xtb
index 4ea2093d..df7a346 100644
--- a/components/strings/components_strings_sw.xtb
+++ b/components/strings/components_strings_sw.xtb
@@ -4531,6 +4531,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" /> hutumia itifaki isiyokubalika.</translation>
 <translation id="918454845714257218">Angalia msimbo kwenye <ph name="SIDE_OF_CARD" /> kisha ujaribu tena</translation>
 <translation id="9186203289258525843">Kitufe cha 'Fanya Chrome iwe kivinjari chaguomsingi', washa ili uifanye Chrome iwe kivinjari chaguomsingi cha mfumo</translation>
+<translation id="9189789270972826888">Bofya maelezo ya kadi hapa chini ili unakili na ubandike iwapo kadi haikujazwa. <ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">Mada ambazo zimekuwepo kwa zaidi ya wiki 4 hufutwa kiotomatiki</translation>
 <translation id="9191834167571392248">Toboa chini kushoto</translation>
 <translation id="9192361865877479444">Chuma (Kisichong'aa)</translation>
diff --git a/components/strings/components_strings_uk.xtb b/components/strings/components_strings_uk.xtb
index 2c4689d..d79f43569 100644
--- a/components/strings/components_strings_uk.xtb
+++ b/components/strings/components_strings_uk.xtb
@@ -169,6 +169,7 @@
 <translation id="129553762522093515">Нещодавно закриті</translation>
 <translation id="1296930489679394997">Продажі</translation>
 <translation id="1297814096526086484">Заблокувати клавіатуру й мишу?</translation>
+<translation id="1297832388362139384">Зелений 1</translation>
 <translation id="1301227606947843452">Legal Extra</translation>
 <translation id="1301324364792935241">Перевірте налаштування безпеки DNS</translation>
 <translation id="1302418742166945866">Сайт <ph name="URL" /> хоче керувати вашими пристроями MIDI й перепрограмовувати їх</translation>
@@ -228,6 +229,7 @@
 <translation id="1384725838384960382">Екран автентифікації облікових даних для безпечних платежів</translation>
 <translation id="1386623374109090026">Примітки</translation>
 <translation id="138810468159004008">Дозволити під час відвідування сайту</translation>
+<translation id="139161720020179799">Темно-сірий 1</translation>
 <translation id="1391625539203220400">Зберегти номер IBAN на цьому пристрої?</translation>
 <translation id="139305205187523129">Хост <ph name="HOST_NAME" /> не надіслав дані.</translation>
 <translation id="1393071644879491291">На сайті, який ви намагалися відвідати, зловмисники можуть обманом змусити вас установити програмне забезпечення або розкрити вашу інформацію, зокрема паролі, номер телефону чи кредитної картки. Chrome радить повернутися на безпечну сторінку. <ph name="BEGIN_LEARN_MORE_LINK" />Докладніше про це попередження<ph name="END_LEARN_MORE_LINK" /></translation>
@@ -703,6 +705,7 @@
 <translation id="2227758700723188171">Гранти на навчання й стипендії</translation>
 <translation id="2228057197024893428">Ця адреса зараз зберігається в Chrome. Збережіть її у своєму обліковому записі Google (<ph name="ACCOUNT" />), щоб використовувати в усіх продуктах Google.</translation>
 <translation id="2229456043301340598">Повторювана швидка команда ігнорується: "<ph name="SHORTCUT_NAME" />"</translation>
+<translation id="222962001646502673">Темно-сірий 2</translation>
 <translation id="2233041017768270281">{COUNT,plural, =1{1 вкладка}one{# вкладка}few{# вкладки}many{# вкладок}other{# вкладки}}</translation>
 <translation id="2233745931693710080">Компакт-диск</translation>
 <translation id="2235344399760031203">Сторонні файли cookie блокуються</translation>
@@ -1730,6 +1733,7 @@
 <translation id="4084219288110917128">Конверт C1</translation>
 <translation id="4085326869263783566">Допомога з текстом. Щоб відкрити, натисніть Tab і Enter.</translation>
 <translation id="4085769736382018559">Порівнюйте товари</translation>
+<translation id="4085778582400064057">Синій 2</translation>
 <translation id="4088981014127559358">Вертикальний зсув сторони 1 зображення</translation>
 <translation id="4089152113577680600">Лоток 14</translation>
 <translation id="4092349052316400070">Введіть адресу</translation>
@@ -1973,6 +1977,7 @@
 <translation id="4509074745930862522"><ph name="TRANSLATE_FOCUSED_FRIENDLY_MATCH_TEXT" />; натисніть Tab, а потім – Enter, щоб перекласти цю сторінку в Google Перекладачі</translation>
 <translation id="4515275063822566619">Дані картки та список адрес містяться в Chrome і вашому обліковому записі Google (<ph name="ACCOUNT_EMAIL" />). Ними можна керувати в <ph name="BEGIN_LINK" />Налаштуваннях<ph name="END_LINK" />.</translation>
 <translation id="4515847625438516456">Мікрокари й малогабаритні автомобілі</translation>
+<translation id="451601984112574365">Зелений 3</translation>
 <translation id="4519245469315452746">Під час оновлення роботу пристрою було перервано.</translation>
 <translation id="4520048001084013693">Адміністратор заборонив завантажувати цей файл</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> мм (<ph name="ORIENTATION" />)</translation>
@@ -2181,6 +2186,7 @@
 <translation id="4901952598169637881">Повсякденне взуття</translation>
 <translation id="4905659621780993806">Адміністратор автоматично перезапустить пристрій <ph name="DATE" /> о <ph name="TIME" />. Збережіть усі відкриті файли до цього часу.</translation>
 <translation id="4913987521957242411">Пробити отвір угорі ліворуч</translation>
+<translation id="4914727764832832057">Синій 1</translation>
 <translation id="4916389289686916969">Телевізійні реаліті-шоу</translation>
 <translation id="4917064667437236721">Формний циліндр</translation>
 <translation id="4918221908152712722">Установіть додаток <ph name="APP_NAME" /> (його не потрібно завантажувати)</translation>
@@ -2254,6 +2260,7 @@
 <translation id="5039804452771397117">Дозволити</translation>
 <translation id="5040262127954254034">Конфіденційність</translation>
 <translation id="5043480802608081735">Скопійоване посилання</translation>
+<translation id="5043753287208271200">Жовтий 3</translation>
 <translation id="5045550434625856497">Неправильний пароль</translation>
 <translation id="5048293684454354469">Теми оголошень – це лише один із багатьох параметрів, які сайт може використовувати для персоналізації реклами. Навіть без них сайти все одно можуть показувати оголошення, але не такі персоналізовані. <ph name="BEGIN_LINK" />Докладніше про керування конфіденційністю в рекламі.<ph name="LINK_END" /></translation>
 <translation id="5052517576853118371">Активні теми</translation>
@@ -2560,6 +2567,7 @@
 <translation id="5593640815048812868">Портативні комп’ютери й ноутбуки</translation>
 <translation id="5595485650161345191">Редагувати адресу</translation>
 <translation id="5596939519753369075">2 x 3,5 дюйм.</translation>
+<translation id="5597254438174353289">Синій 3</translation>
 <translation id="560412284261940334">Керування не підтримується</translation>
 <translation id="5605249000617390290">Докладніше про відстеження цін</translation>
 <translation id="5605670050355397069">Ledger</translation>
@@ -2615,6 +2623,7 @@
 <translation id="5701381305118179107">По центру</translation>
 <translation id="5707154300732650394">Відновити сеанс</translation>
 <translation id="57094364128775171">Запропонувати надійний пароль…</translation>
+<translation id="570953204696852961">Червоний 3</translation>
 <translation id="571403275720188526">(arm64)</translation>
 <translation id="571510845185711675">Ветеринари</translation>
 <translation id="5715150588940290235">Видалити збережені коди безпеки?</translation>
@@ -2815,6 +2824,7 @@
 <translation id="6085149458302186532">Етикетки (кольорові)</translation>
 <translation id="6087312102907839798">Пов’язані пошукові запити</translation>
 <translation id="6089505343295765444">Вкладки, які ви видалите з історії Chrome, усе одно відображатимуться в порівняльних таблицях</translation>
+<translation id="6093599771645355227">Жовтий 1</translation>
 <translation id="6093795393556121384">Картку підтверджено</translation>
 <translation id="6094273045989040137">Додати примітку</translation>
 <translation id="6094290315941448991">Адміністратор заборонив запис екрана, якщо видно конфіденційний контент</translation>
@@ -3353,6 +3363,7 @@
 <translation id="7058774143982824355">Сервіс для синтаксичного аналізу файлу CSV з паролями</translation>
 <translation id="7062635574500127092">Бірюзовий</translation>
 <translation id="706295145388601875">Додайте адреси та керуйте ними в налаштуваннях Chrome</translation>
+<translation id="7063157783216323487">Зелений 2</translation>
 <translation id="7064443976734085921">Компактні автомобілі</translation>
 <translation id="7064851114919012435">Контактна інформація</translation>
 <translation id="7067633076996245366">Соул і R&amp;B</translation>
@@ -3905,6 +3916,7 @@
 <translation id="8028698320761417183"><ph name="CREATE_GOOGLE_FORM_FOCUSED_FRIENDLY_MATCH_TEXT" />; натисніть Tab, а потім – Enter, щоб швидко створити нову форму в Google Формах</translation>
 <translation id="8028892419725165118">Казуальні ігри</translation>
 <translation id="8028960012888758725">Обрізати після завдання</translation>
+<translation id="8029829038322015001">Червоний 1</translation>
 <translation id="8030729864112325446">Професійно-технічна й післядипломна освіта</translation>
 <translation id="8032546467100845887">Прозорість</translation>
 <translation id="8035152190676905274">Перо</translation>
@@ -3912,6 +3924,7 @@
 <translation id="8037117624646282037">Хто нещодавно користувався пристроєм</translation>
 <translation id="8037357227543935929">Запитувати (за умовчанням)</translation>
 <translation id="803771048473350947">Файл</translation>
+<translation id="8038182528865038593">Червоний 2</translation>
 <translation id="8041089156583427627">Надіслати відгук</translation>
 <translation id="8041940743680923270">Використовувати глобальне налаштування за умовчанням (Запитувати)</translation>
 <translation id="8043255123207491407">Переглянути умови використання продавця</translation>
@@ -4312,6 +4325,7 @@
 <translation id="8767881944435256294">{COUNT,plural, =1{1 спосіб оплати}one{# спосіб оплати}few{# способи оплати}many{# способів оплати}other{# способу оплати}}</translation>
 <translation id="8768225988514678921">Кнопка "Створити презентацію"; активуйте, щоб швидко створити нову презентацію в Google Презентаціях</translation>
 <translation id="8769662576926275897">Дані картки</translation>
+<translation id="8769858749286369844">Бежевий 2</translation>
 <translation id="8770286973007342895">Газонокосарки</translation>
 <translation id="8772387130037509473">Йога й пілатес</translation>
 <translation id="877348612833018844">{0,plural, =1{Перемістити конфіденційний файл?}one{Перемістити конфіденційні файли?}few{Перемістити конфіденційні файли?}many{Перемістити конфіденційні файли?}other{Перемістити конфіденційні файли?}}</translation>
@@ -4403,6 +4417,7 @@
 <translation id="8956124158020778855">Увімкнувши це налаштування, поверніться на поточну вкладку, щоб почати писати.</translation>
 <translation id="8957210676456822347">Авторизація приєднаного порталу</translation>
 <translation id="8959282183248574156"><ph name="NICKNAME_COUNT" />/<ph name="NICKNAME_MAX" /></translation>
+<translation id="8959288490306482616">Бежевий 3</translation>
 <translation id="8963117664422609631">Перейти до налаштувань сайту</translation>
 <translation id="8963213021028234748"><ph name="MARKUP_1" />Пропозиції.<ph name="MARKUP_2" />Переконайтеся, що пристрій під’єднано до мобільного Інтернету.<ph name="MARKUP_3" />Оновіть цю веб-сторінку пізніше<ph name="MARKUP_4" />Перевірне адресу, яку ви ввели<ph name="MARKUP_5" /></translation>
 <translation id="8968766641738584599">Зберегти картку</translation>
@@ -4465,6 +4480,7 @@
 <translation id="90695670378604968">Пластик (матовий)</translation>
 <translation id="9069693763241529744">Заблоковано розширенням</translation>
 <translation id="9073799351042754113">Ви вимкнули попередження про небезпеку для цього сайту.</translation>
+<translation id="9075717835386447447">Бежевий 1</translation>
 <translation id="9076283476770535406">На ньому може бути вміст для дорослих</translation>
 <translation id="9078912659001679888">Блендери й соковижималки</translation>
 <translation id="9078964945751709336">Потрібно більше інформації</translation>
@@ -4573,6 +4589,7 @@
 <translation id="949314938206378263">Запит на дозвіл для перегляду сайту надіслано. Твої батько чи мати можуть відповісти на нього у Family Link.</translation>
 <translation id="950736567201356821">Пробити три отвори вгорі</translation>
 <translation id="950926967802086924">Ключ доступу • Google Менеджер паролів</translation>
+<translation id="95721182352849470">Жовтий 2</translation>
 <translation id="961663415146723894">Зшити внизу</translation>
 <translation id="961856697154696964">Видалити дані вебперегляду</translation>
 <translation id="961930410699694996">Надано разовий доступ до місцезнаходження</translation>
diff --git a/components/strings/components_strings_zh-CN.xtb b/components/strings/components_strings_zh-CN.xtb
index e74bed6..88b05c7 100644
--- a/components/strings/components_strings_zh-CN.xtb
+++ b/components/strings/components_strings_zh-CN.xtb
@@ -3422,7 +3422,7 @@
 <translation id="718872491229180389">啦啦队</translation>
 <translation id="7188840756966467339">重启浏览器并应用政策</translation>
 <translation id="7192188280913829296">还必须指定“vendor_id”属性。</translation>
-<translation id="7192203810768312527">释放了 <ph name="SIZE" />。当您下次访问时,某些网站的加载速度可能会更慢。</translation>
+<translation id="7192203810768312527">释放 <ph name="SIZE" />。当您下次访问某些网站时,加载速度可能会变慢。</translation>
 <translation id="7192537357091279678">计算机驱动器和存储设备</translation>
 <translation id="7193661028827781021">参考资料</translation>
 <translation id="719464814642662924">Visa</translation>
diff --git a/components/strings/components_strings_zh-HK.xtb b/components/strings/components_strings_zh-HK.xtb
index c0134b6..56e9f6578 100644
--- a/components/strings/components_strings_zh-HK.xtb
+++ b/components/strings/components_strings_zh-HK.xtb
@@ -169,6 +169,7 @@
 <translation id="129553762522093515">最近關閉的分頁</translation>
 <translation id="1296930489679394997">銷售</translation>
 <translation id="1297814096526086484">要鎖定鍵盤和滑鼠嗎?</translation>
+<translation id="1297832388362139384">綠色 1</translation>
 <translation id="1301227606947843452">Legal Extra</translation>
 <translation id="1301324364792935241">請檢查您的安全 DNS 設定</translation>
 <translation id="1302418742166945866"><ph name="URL" /> 要求控制及重設 MIDI 裝置的程式</translation>
@@ -228,6 +229,7 @@
 <translation id="1384725838384960382">安全付款憑證驗證工作表</translation>
 <translation id="1386623374109090026">註解</translation>
 <translation id="138810468159004008">瀏覽此網站時允許</translation>
+<translation id="139161720020179799">深灰色 1</translation>
 <translation id="1391625539203220400">要將 IBAN 儲存至此裝置嗎?</translation>
 <translation id="139305205187523129"><ph name="HOST_NAME" /> 沒有傳送任何資料。</translation>
 <translation id="1393071644879491291">如果你嘗試瀏覽的網站被攻擊,攻擊者可能會誘騙你安裝軟件或提供資料,例如密碼、電話號碼或信用卡號碼等資料。Chrome 強烈建議你不要瀏覽這類網站。<ph name="BEGIN_LEARN_MORE_LINK" />進一步瞭解此警告訊息<ph name="END_LEARN_MORE_LINK" /></translation>
@@ -703,6 +705,7 @@
 <translation id="2227758700723188171">助學金和獎學金</translation>
 <translation id="2228057197024893428">此地址目前儲存在 Chrome 中。如要在各項 Google 產品中使用此資料,請儲存至 Google 帳戶 (<ph name="ACCOUNT" />)。</translation>
 <translation id="2229456043301340598">已忽略非專屬快速指令:<ph name="SHORTCUT_NAME" /></translation>
+<translation id="222962001646502673">深灰色 2</translation>
 <translation id="2233041017768270281">{COUNT,plural, =1{1 個分頁}other{# 個分頁}}</translation>
 <translation id="2233745931693710080">光碟</translation>
 <translation id="2235344399760031203">已封鎖第三方 Cookie</translation>
@@ -1729,6 +1732,7 @@
 <translation id="4084219288110917128">C1 信封</translation>
 <translation id="4085326869263783566">幫我寫。㩒一下 Tab 鍵,然後㩒一下 Enter 鍵就可以打開</translation>
 <translation id="4085769736382018559">比較產品</translation>
+<translation id="4085778582400064057">藍色 2</translation>
 <translation id="4088981014127559358">側邊 1 圖片 Y 軸移動</translation>
 <translation id="4089152113577680600">紙匣 14</translation>
 <translation id="4092349052316400070">填入地址</translation>
@@ -1972,6 +1976,7 @@
 <translation id="4509074745930862522"><ph name="TRANSLATE_FOCUSED_FRIENDLY_MATCH_TEXT" />,㩒一下 Tab 鍵,然後㩒一下 Enter 鍵就可以透過 Google 翻譯翻譯呢個頁面</translation>
 <translation id="4515275063822566619">信用卡和地址選項均來自 Chrome 和您的 Google 帳戶 (<ph name="ACCOUNT_EMAIL" />)。您可在「<ph name="BEGIN_LINK" />設定<ph name="END_LINK" />」中管理這些選項。</translation>
 <translation id="4515847625438516456">迷你車和小型車</translation>
+<translation id="451601984112574365">綠色 3</translation>
 <translation id="4519245469315452746">裝置在更新過程中被中斷。</translation>
 <translation id="4520048001084013693">管理員政策已禁止下載此檔案</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> 毫米 (<ph name="ORIENTATION" />)</translation>
@@ -2180,6 +2185,7 @@
 <translation id="4901952598169637881">休閒鞋</translation>
 <translation id="4905659621780993806">管理員將於 <ph name="DATE" /><ph name="TIME" /> 自動重新啟動您的裝置。請在裝置重新啟動前儲存任何開啟的項目。</translation>
 <translation id="4913987521957242411">打孔 (左上方)</translation>
+<translation id="4914727764832832057">藍色 1</translation>
 <translation id="4916389289686916969">電視真人騷</translation>
 <translation id="4917064667437236721">圖像滾筒</translation>
 <translation id="4918221908152712722">安裝「<ph name="APP_NAME" />」(無需下載)</translation>
@@ -2253,6 +2259,7 @@
 <translation id="5039804452771397117">允許</translation>
 <translation id="5040262127954254034">私隱權</translation>
 <translation id="5043480802608081735">您複製的連結</translation>
+<translation id="5043753287208271200">黃色 3</translation>
 <translation id="5045550434625856497">密碼不正確</translation>
 <translation id="5048293684454354469">廣告主題只是網站在放送個人化廣告時的其中一項依據。即使你未開啟此設定,網站仍可放送廣告,但可能會放送較不相關的廣告。進一步瞭解如何<ph name="BEGIN_LINK" />管理廣告私隱權<ph name="LINK_END" />。</translation>
 <translation id="5052517576853118371">有效主題</translation>
@@ -2559,6 +2566,7 @@
 <translation id="5593640815048812868">手提電腦</translation>
 <translation id="5595485650161345191">編輯地址</translation>
 <translation id="5596939519753369075">2 x 3.5 吋</translation>
+<translation id="5597254438174353289">藍色 3</translation>
 <translation id="560412284261940334">系統不支援管理</translation>
 <translation id="5605249000617390290">進一步瞭解追蹤價格</translation>
 <translation id="5605670050355397069">Ledger</translation>
@@ -2614,6 +2622,7 @@
 <translation id="5701381305118179107">置中</translation>
 <translation id="5707154300732650394">恢復瀏覽過程</translation>
 <translation id="57094364128775171">建議安全性強的密碼…</translation>
+<translation id="570953204696852961">紅色 3</translation>
 <translation id="571403275720188526">(arm64)</translation>
 <translation id="571510845185711675">獸醫</translation>
 <translation id="5715150588940290235">要刪除已儲存的安全碼嗎?</translation>
@@ -2814,6 +2823,7 @@
 <translation id="6085149458302186532">標籤 (彩色)</translation>
 <translation id="6087312102907839798">相關搜尋</translation>
 <translation id="6089505343295765444">你從 Chrome 記錄刪除的分頁仍會在比較表格中顯示</translation>
+<translation id="6093599771645355227">黃色 1</translation>
 <translation id="6093795393556121384">您的卡片已驗證</translation>
 <translation id="6094273045989040137">加入註釋</translation>
 <translation id="6094290315941448991">當畫面上出現機密內容時,管理員政策就會停用螢幕錄影功能</translation>
@@ -3352,6 +3362,7 @@
 <translation id="7058774143982824355">CSV 密碼剖析器服務</translation>
 <translation id="7062635574500127092">藍綠色</translation>
 <translation id="706295145388601875">在 Chrome 設定中新增並管理地址</translation>
+<translation id="7063157783216323487">綠色 2</translation>
 <translation id="7064443976734085921">小型車</translation>
 <translation id="7064851114919012435">聯絡人資訊</translation>
 <translation id="7067633076996245366">騷靈音樂和 R&amp;B</translation>
@@ -3483,6 +3494,7 @@
 <translation id="7304030187361489308">高</translation>
 <translation id="7304562222803846232">管理 Google 帳戶私隱設定</translation>
 <translation id="7305756307268530424">啟用慢速模式</translation>
+<translation id="7307063504147610123">地址已儲存到這部裝置</translation>
 <translation id="7308436126008021607">背景同步處理</translation>
 <translation id="7309058266849426521">進一步了解點樣喺 Chrome 度管理廣告私隱權。</translation>
 <translation id="7310392214323165548">裝置即將重新啟動</translation>
@@ -3904,6 +3916,7 @@
 <translation id="8028698320761417183"><ph name="CREATE_GOOGLE_FORM_FOCUSED_FRIENDLY_MATCH_TEXT" />,㩒一下 Tab 鍵,然後㩒一下 Enter 鍵就可以喺 Google 表格度快速建立新表格</translation>
 <translation id="8028892419725165118">休閒遊戲</translation>
 <translation id="8028960012888758725">完成工作後修剪</translation>
+<translation id="8029829038322015001">紅色 1</translation>
 <translation id="8030729864112325446">職業和持續進修教育</translation>
 <translation id="8032546467100845887">透明</translation>
 <translation id="8035152190676905274">筆</translation>
@@ -3911,6 +3924,7 @@
 <translation id="8037117624646282037">最近使用過裝置的使用者</translation>
 <translation id="8037357227543935929">要求 (預設)</translation>
 <translation id="803771048473350947">檔案</translation>
+<translation id="8038182528865038593">紅色 2</translation>
 <translation id="8041089156583427627">提供意見</translation>
 <translation id="8041940743680923270">使用全域預設值 (要求確認)</translation>
 <translation id="8043255123207491407">查看賣家的條款及細則</translation>
@@ -4158,6 +4172,7 @@
 <translation id="8473626140772740486">300 x 450 毫米</translation>
 <translation id="8473863474539038330">地址及其他資料</translation>
 <translation id="8474910779563686872">顯示開發人員詳情</translation>
+<translation id="8476959635632921417">如要儲存這個地址並在所有裝置上使用,請驗證身分</translation>
 <translation id="8479754468255770962">釘裝 (左下方)</translation>
 <translation id="8483229036294884935">此地址將從您的 Google 帳戶 (<ph name="ACCOUNT" />) 中刪除</translation>
 <translation id="8488350697529856933">適用對象</translation>
@@ -4310,6 +4325,7 @@
 <translation id="8767881944435256294">{COUNT,plural, =1{1 種付款方法}other{# 種付款方法}}</translation>
 <translation id="8768225988514678921">建立簡報按鈕,啟動之後就可以喺簡報度快速建立新嘅 Google 簡報</translation>
 <translation id="8769662576926275897">卡片詳情</translation>
+<translation id="8769858749286369844">棕褐色 2</translation>
 <translation id="8770286973007342895">除草機</translation>
 <translation id="8772387130037509473">瑜珈和普拉提</translation>
 <translation id="877348612833018844">{0,plural, =1{要移動機密檔案嗎?}other{要移動機密檔案嗎?}}</translation>
@@ -4401,6 +4417,7 @@
 <translation id="8956124158020778855">開啟此設定後,請返回此分頁開始輸入內容。</translation>
 <translation id="8957210676456822347">網頁驗證入口授權</translation>
 <translation id="8959282183248574156"><ph name="NICKNAME_COUNT" />/<ph name="NICKNAME_MAX" /></translation>
+<translation id="8959288490306482616">棕褐色 3</translation>
 <translation id="8963117664422609631">前往網站設定</translation>
 <translation id="8963213021028234748"><ph name="MARKUP_1" />建議:<ph name="MARKUP_2" />請確保您已建立數據連線<ph name="MARKUP_3" />請稍後重新載入此網頁<ph name="MARKUP_4" />請檢查您輸入的網址<ph name="MARKUP_5" /></translation>
 <translation id="8968766641738584599">儲存付款卡</translation>
@@ -4463,6 +4480,7 @@
 <translation id="90695670378604968">塑膠 (啞面)</translation>
 <translation id="9069693763241529744">根據擴充程式設定封鎖</translation>
 <translation id="9073799351042754113">您已選擇關閉此網站的安全性警告。</translation>
+<translation id="9075717835386447447">棕褐色 1</translation>
 <translation id="9076283476770535406">此網站可能含有成人內容</translation>
 <translation id="9078912659001679888">攪拌器和榨汁機</translation>
 <translation id="9078964945751709336">必須提供更多資料</translation>
@@ -4532,6 +4550,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" /> 使用不支援的通訊協定。</translation>
 <translation id="918454845714257218">請檢查<ph name="SIDE_OF_CARD" />的安全碼,並再試一次</translation>
 <translation id="9186203289258525843">將 Chrome 設定做預設瀏覽器按鈕,啟動之後就可以將 Chrome 設定做系統嘅預設瀏覽器</translation>
+<translation id="9189789270972826888">如果系統尚未自動填寫資料,按一下下方的信用卡詳情即可複製並貼上。<ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">系統會自動刪除 4 週前的主題</translation>
 <translation id="9191834167571392248">打孔 (左下方)</translation>
 <translation id="9192361865877479444">金屬 (啞面)</translation>
@@ -4570,6 +4589,7 @@
 <translation id="949314938206378263">您已要求瀏覽此網站。家長可透過 Family Link 回覆要求。</translation>
 <translation id="950736567201356821">三孔 (頂端)</translation>
 <translation id="950926967802086924">密鑰 • Google 密碼管理工具</translation>
+<translation id="95721182352849470">黃色 2</translation>
 <translation id="961663415146723894">釘裝 (底部)</translation>
 <translation id="961856697154696964">刪除瀏覽資料</translation>
 <translation id="961930410699694996">呢次批准存取位置</translation>
diff --git a/components/strings/components_strings_zh-TW.xtb b/components/strings/components_strings_zh-TW.xtb
index e74f25bb..5192be5 100644
--- a/components/strings/components_strings_zh-TW.xtb
+++ b/components/strings/components_strings_zh-TW.xtb
@@ -169,6 +169,7 @@
 <translation id="129553762522093515">最近關閉的分頁</translation>
 <translation id="1296930489679394997">銷售</translation>
 <translation id="1297814096526086484">要鎖定鍵盤和滑鼠嗎?</translation>
+<translation id="1297832388362139384">綠色 1</translation>
 <translation id="1301227606947843452">Legal Extra</translation>
 <translation id="1301324364792935241">請檢查你的安全 DNS 設定</translation>
 <translation id="1302418742166945866"><ph name="URL" /> 想控制 MIDI 裝置及重設程式</translation>
@@ -228,6 +229,7 @@
 <translation id="1384725838384960382">安全付款憑證驗證表</translation>
 <translation id="1386623374109090026">註解</translation>
 <translation id="138810468159004008">造訪這個網站時允許</translation>
+<translation id="139161720020179799">深灰色 1</translation>
 <translation id="1391625539203220400">要將 IBAN 儲存到這部裝置嗎?</translation>
 <translation id="139305205187523129"><ph name="HOST_NAME" /> 未傳送任何資料。</translation>
 <translation id="1393071644879491291">你嘗試前往的網站可能有攻擊者,會誘騙你安裝軟體或提供資訊,例如密碼、電話號碼或信用卡號碼。Chrome 強烈建議你不要造訪這個網站。<ph name="BEGIN_LEARN_MORE_LINK" />進一步瞭解這項警告<ph name="END_LEARN_MORE_LINK" /></translation>
@@ -702,6 +704,7 @@
 <translation id="2227758700723188171">研究津貼與獎學金</translation>
 <translation id="2228057197024893428">這個地址目前儲存在 Chrome 中。如要在各項 Google 產品中使用這項資訊,請儲存到你的 Google 帳戶 (<ph name="ACCOUNT" />)。</translation>
 <translation id="2229456043301340598">已忽略的重複搜尋捷徑:<ph name="SHORTCUT_NAME" /></translation>
+<translation id="222962001646502673">深灰色 2</translation>
 <translation id="2233041017768270281">{COUNT,plural, =1{1 個分頁}other{# 個分頁}}</translation>
 <translation id="2233745931693710080">光碟</translation>
 <translation id="2235344399760031203">已封鎖第三方 Cookie</translation>
@@ -1728,6 +1731,7 @@
 <translation id="4084219288110917128">Envelope C1</translation>
 <translation id="4085326869263783566">幫我寫。按下 Tab 鍵和 Enter 鍵即可開啟</translation>
 <translation id="4085769736382018559">比較產品</translation>
+<translation id="4085778582400064057">藍色 2</translation>
 <translation id="4088981014127559358">側邊 1 圖片 Y 批次</translation>
 <translation id="4089152113577680600">紙匣 14</translation>
 <translation id="4092349052316400070">填入地址</translation>
@@ -1971,6 +1975,7 @@
 <translation id="4509074745930862522"><ph name="TRANSLATE_FOCUSED_FRIENDLY_MATCH_TEXT" />,按下 Tab 鍵再按下 Enter 鍵即可使用 Google 翻譯來翻譯這個網頁</translation>
 <translation id="4515275063822566619">信用卡和地址資訊皆來自 Chrome 和你的 Google 帳戶 (<ph name="ACCOUNT_EMAIL" />)。你可以在<ph name="BEGIN_LINK" />設定<ph name="END_LINK" />頁面管理這些資訊。</translation>
 <translation id="4515847625438516456">迷你車與微型車</translation>
+<translation id="451601984112574365">綠色 3</translation>
 <translation id="4519245469315452746">裝置在更新作業期間遭中斷。</translation>
 <translation id="4520048001084013693">根據系統管理員政策,你無法下載這個檔案</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> 公釐 (<ph name="ORIENTATION" />)</translation>
@@ -2179,6 +2184,7 @@
 <translation id="4901952598169637881">休閒鞋</translation>
 <translation id="4905659621780993806">管理員將自動於 <ph name="DATE" /><ph name="TIME" />重新啟動你的裝置。在裝置重新啟動前,請記得儲存開啟的項目。</translation>
 <translation id="4913987521957242411">打孔 (左上方)</translation>
+<translation id="4914727764832832057">藍色 1</translation>
 <translation id="4916389289686916969">電視真人實境秀</translation>
 <translation id="4917064667437236721">成像柱面</translation>
 <translation id="4918221908152712722">安裝「<ph name="APP_NAME" />」(無須下載)</translation>
@@ -2252,6 +2258,7 @@
 <translation id="5039804452771397117">允許</translation>
 <translation id="5040262127954254034">隱私權</translation>
 <translation id="5043480802608081735">你複製的連結</translation>
+<translation id="5043753287208271200">黃色 3</translation>
 <translation id="5045550434625856497">密碼不正確</translation>
 <translation id="5048293684454354469">廣告主題只是網站在放送個人化廣告時的其中一項依據。即使沒有廣告主題,網站仍可放送廣告,但廣告內容可能較不貼近你的需求。進一步瞭解如何<ph name="BEGIN_LINK" />管理廣告隱私權<ph name="LINK_END" />。</translation>
 <translation id="5052517576853118371">有效主題</translation>
@@ -2558,6 +2565,7 @@
 <translation id="5593640815048812868">筆記型電腦</translation>
 <translation id="5595485650161345191">編輯地址</translation>
 <translation id="5596939519753369075">2 x 3.5 吋</translation>
+<translation id="5597254438174353289">藍色 3</translation>
 <translation id="560412284261940334">系統不支援管理</translation>
 <translation id="5605249000617390290">進一步瞭解價格追蹤功能</translation>
 <translation id="5605670050355397069">Ledger</translation>
@@ -2613,6 +2621,7 @@
 <translation id="5701381305118179107">置中</translation>
 <translation id="5707154300732650394">繼續瀏覽歷程</translation>
 <translation id="57094364128775171">建議高強度密碼…</translation>
+<translation id="570953204696852961">紅色 3</translation>
 <translation id="571403275720188526">(arm64)</translation>
 <translation id="571510845185711675">獸醫</translation>
 <translation id="5715150588940290235">要刪除已儲存的安全碼嗎?</translation>
@@ -2813,6 +2822,7 @@
 <translation id="6085149458302186532">標籤 (彩色)</translation>
 <translation id="6087312102907839798">相關搜尋</translation>
 <translation id="6089505343295765444">你從 Chrome 歷史記錄中刪除的分頁仍會顯示在比較表中</translation>
+<translation id="6093599771645355227">黃色 1</translation>
 <translation id="6093795393556121384">已成功驗證您的信用卡</translation>
 <translation id="6094273045989040137">註解</translation>
 <translation id="6094290315941448991">當畫面上出現機密內容,系統管理員政策就會停用螢幕畫面錄製功能</translation>
@@ -3351,6 +3361,7 @@
 <translation id="7058774143982824355">CSV 密碼剖析器服務</translation>
 <translation id="7062635574500127092">藍綠色</translation>
 <translation id="706295145388601875">在 Chrome 設定中新增及管理地址</translation>
+<translation id="7063157783216323487">綠色 2</translation>
 <translation id="7064443976734085921">小型車</translation>
 <translation id="7064851114919012435">聯絡資訊</translation>
 <translation id="7067633076996245366">靈魂樂與節奏藍調</translation>
@@ -3482,6 +3493,7 @@
 <translation id="7304030187361489308">高</translation>
 <translation id="7304562222803846232">管理 Google 帳戶隱私權設定</translation>
 <translation id="7305756307268530424">啟用慢速模式</translation>
+<translation id="7307063504147610123">地址已儲存到這部裝置</translation>
 <translation id="7308436126008021607">背景同步處理</translation>
 <translation id="7309058266849426521">進一步瞭解如何在 Chrome 中管理廣告隱私權。</translation>
 <translation id="7310392214323165548">裝置很快就會重新啟動</translation>
@@ -3903,6 +3915,7 @@
 <translation id="8028698320761417183"><ph name="CREATE_GOOGLE_FORM_FOCUSED_FRIENDLY_MATCH_TEXT" />;按下 Tab 鍵再按下 Enter 鍵即可在 Google 表單中快速建立新表單</translation>
 <translation id="8028892419725165118">休閒遊戲</translation>
 <translation id="8028960012888758725">完成工作後裁切</translation>
+<translation id="8029829038322015001">紅色 1</translation>
 <translation id="8030729864112325446">技職與進修教育</translation>
 <translation id="8032546467100845887">透明</translation>
 <translation id="8035152190676905274">畫筆</translation>
@@ -3910,6 +3923,7 @@
 <translation id="8037117624646282037">最近使用過裝置的使用者</translation>
 <translation id="8037357227543935929">詢問 (預設)</translation>
 <translation id="803771048473350947">檔案</translation>
+<translation id="8038182528865038593">紅色 2</translation>
 <translation id="8041089156583427627">提供意見</translation>
 <translation id="8041940743680923270">使用全域預設值 (要求確認)</translation>
 <translation id="8043255123207491407">查看賣家的條款及細則</translation>
@@ -4157,6 +4171,7 @@
 <translation id="8473626140772740486">300 x 450 公釐</translation>
 <translation id="8473863474539038330">地址和其他資訊</translation>
 <translation id="8474910779563686872">顯示開發人員詳細資料</translation>
+<translation id="8476959635632921417">如要儲存這個地址並在所有裝置上使用,請驗證身分</translation>
 <translation id="8479754468255770962">釘裝 (左下方)</translation>
 <translation id="8483229036294884935">這個地址將從 Google 帳戶 (<ph name="ACCOUNT" />) 中刪除</translation>
 <translation id="8488350697529856933">適用對象</translation>
@@ -4309,6 +4324,7 @@
 <translation id="8767881944435256294">{COUNT,plural, =1{1 種付款方式}other{# 種付款方式}}</translation>
 <translation id="8768225988514678921">「建立簡報」按鈕,啟動後即可在 Google 簡報中快速建立新簡報</translation>
 <translation id="8769662576926275897">信用卡詳細資料</translation>
+<translation id="8769858749286369844">棕褐色 2</translation>
 <translation id="8770286973007342895">除草機</translation>
 <translation id="8772387130037509473">瑜珈與彼拉提斯</translation>
 <translation id="877348612833018844">{0,plural, =1{要移動機密檔案嗎?}other{要移動機密檔案嗎?}}</translation>
@@ -4400,6 +4416,7 @@
 <translation id="8956124158020778855">開啟這項設定後,請返回這個分頁開始輸入內容。</translation>
 <translation id="8957210676456822347">監控式入口網站授權</translation>
 <translation id="8959282183248574156"><ph name="NICKNAME_COUNT" />/<ph name="NICKNAME_MAX" /></translation>
+<translation id="8959288490306482616">棕褐色 3</translation>
 <translation id="8963117664422609631">前往網站設定</translation>
 <translation id="8963213021028234748"><ph name="MARKUP_1" />建議:<ph name="MARKUP_2" />確認您的數據連線狀態正常<ph name="MARKUP_3" />稍後再重新載入這個網頁<ph name="MARKUP_4" />檢查您輸入的網址是否正確<ph name="MARKUP_5" /></translation>
 <translation id="8968766641738584599">儲存卡片</translation>
@@ -4462,6 +4479,7 @@
 <translation id="90695670378604968">塑膠 (霧面)</translation>
 <translation id="9069693763241529744">依據擴充功能設定封鎖</translation>
 <translation id="9073799351042754113">你已選擇關閉這個網站的安全性警告。</translation>
+<translation id="9075717835386447447">棕褐色 1</translation>
 <translation id="9076283476770535406">這個網站可能含有成人內容</translation>
 <translation id="9078912659001679888">食物調理機和榨汁機</translation>
 <translation id="9078964945751709336">請提供詳細資訊</translation>
@@ -4531,6 +4549,7 @@
 <translation id="9183425211371246419"><ph name="HOST_NAME" /> 使用了不支援的通訊協定。</translation>
 <translation id="918454845714257218">請確認<ph name="SIDE_OF_CARD" />的安全碼,然後再試一次</translation>
 <translation id="9186203289258525843">「將 Chrome 設為預設瀏覽器」按鈕,啟動後即可將 Chrome 設為系統預設瀏覽器</translation>
+<translation id="9189789270972826888">點選下方的卡片資料,即可複製及貼上 (如果系統未自動填入)。<ph name="IDS_AUTOFILL_FILLED_CARD_INFORMATION_BUBBLE_LEARN_MORE_LINK_LABEL" /></translation>
 <translation id="9190557999028587593">系統會自動刪除 4 週前的主題</translation>
 <translation id="9191834167571392248">打孔 (左下方)</translation>
 <translation id="9192361865877479444">金屬 (霧面)</translation>
@@ -4569,6 +4588,7 @@
 <translation id="949314938206378263">你已要求造訪這個網站,家長可以透過 Family Link 回覆要求。</translation>
 <translation id="950736567201356821">三孔 (頂端)</translation>
 <translation id="950926967802086924">密碼金鑰 • Google 密碼管理工具</translation>
+<translation id="95721182352849470">黃色 2</translation>
 <translation id="961663415146723894">裝訂 (底部)</translation>
 <translation id="961856697154696964">刪除瀏覽資料</translation>
 <translation id="961930410699694996">這次允許存取位置資訊</translation>
diff --git a/components/update_client/component.cc b/components/update_client/component.cc
index 0b1cc94..92b22dd5 100644
--- a/components/update_client/component.cc
+++ b/components/update_client/component.cc
@@ -12,8 +12,6 @@
 #include <vector>
 
 #include "base/check_op.h"
-#include "base/debug/alias.h"
-#include "base/debug/dump_without_crashing.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/functional/bind.h"
@@ -59,14 +57,7 @@
     : id_(id),
       state_(std::make_unique<StateNew>(this)),
       update_context_(update_context) {
-  // TODO(crbug.com/345250525) - remove when the bug is fixed. We are
-  // seeing dumps where the app id is empty in the state change
-  // callbacks. This code verifies the invariant that the component
-  // instance always has an id.
-  if (id_.empty()) {
-    DEBUG_ALIAS_FOR_CSTR(dbg_id, id_.c_str(), 64);
-    base::debug::DumpWithoutCrashing();
-  }
+  CHECK(!id_.empty());
 }
 
 Component::~Component() = default;
@@ -109,13 +100,7 @@
 CrxUpdateItem Component::GetCrxUpdateItem() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  // TODO(crbug.com/345250525) - remove when the bug is fixed. We are seeing
-  // dumps where the app id is empty in the state change callbacks. This code
-  // verifies the invariant that the id is always valid.
-  if (id_.empty()) {
-    DEBUG_ALIAS_FOR_CSTR(dbg_id, id_.c_str(), 64);
-    base::debug::DumpWithoutCrashing();
-  }
+  CHECK(!id_.empty());
 
   CrxUpdateItem crx_update_item;
   crx_update_item.state = state_->state();
diff --git a/components/update_client/update_client_unittest.cc b/components/update_client/update_client_unittest.cc
index a0d5da3..d964e37c 100644
--- a/components/update_client/update_client_unittest.cc
+++ b/components/update_client/update_client_unittest.cc
@@ -7223,9 +7223,10 @@
   update_client->AddObserver(&observer);
   const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
   update_client->CheckForUpdate(
-      "",
+      id,
       base::BindOnce(
-          [](const std::vector<std::string>&, /*ids*/ base::OnceCallback<void(
+          [](const std::vector<std::string>& /*ids*/,
+             base::OnceCallback<void(
                  const std::vector<std::optional<CrxComponent>>&)> callback) {
             std::move(callback).Run({});
           }),
diff --git a/components/variations/net/BUILD.gn b/components/variations/net/BUILD.gn
index 28e2ec99..ee3372e 100644
--- a/components/variations/net/BUILD.gn
+++ b/components/variations/net/BUILD.gn
@@ -31,6 +31,10 @@
     "//components/variations/proto",
   ]
 
+  if (!is_chromeos) {
+    deps += [ "//third_party/boringssl" ]
+  }
+
   if (use_blink) {
     sources += [
       "variations_url_loader_throttle.cc",
diff --git a/components/variations/net/DEPS b/components/variations/net/DEPS
index 8ed566a..7a61cae 100644
--- a/components/variations/net/DEPS
+++ b/components/variations/net/DEPS
@@ -5,4 +5,5 @@
   "+services/network/public/cpp",
   "+services/network/public/mojom",
   "+third_party/blink/public/common/loader/url_loader_throttle.h",
+  "+third_party/boringssl/src/include/openssl",
 ]
diff --git a/components/variations/net/variations_command_line.cc b/components/variations/net/variations_command_line.cc
index 3779f2d..ecee6c3 100644
--- a/components/variations/net/variations_command_line.cc
+++ b/components/variations/net/variations_command_line.cc
@@ -21,6 +21,20 @@
 #include "components/variations/net/variations_command_line.h"
 #include "components/variations/variations_switches.h"
 
+#if !BUILDFLAG(IS_CHROMEOS)
+#include "base/check_is_test.h"
+#include "third_party/boringssl/src/include/openssl/hpke.h"
+#endif
+
+#if !BUILDFLAG(IS_CHROMEOS)
+// Prod key for feedback encryption.
+// TODO(svenzheng): Update to a real prod key.
+const std::array<uint8_t, X25519_PUBLIC_VALUE_LEN> kFeedbackEncryptionPublicKey{
+    0x3c, 0x68, 0xe8, 0x54, 0xdf, 0x8c, 0xde, 0x15, 0x63, 0xb5, 0xa0,
+    0x24, 0xcc, 0x7b, 0xab, 0x77, 0xbe, 0x55, 0x19, 0x28, 0x26, 0x0f,
+    0xc0, 0xcf, 0x62, 0x2e, 0xce, 0x97, 0x29, 0xff, 0xe7, 0x2f};
+#endif
+
 // Exits the browser with a helpful error message.
 void ExitWithMessage(const std::string& message) {
   puts(message.c_str());
@@ -29,6 +43,12 @@
 
 namespace variations {
 
+#if !BUILDFLAG(IS_CHROMEOS)
+BASE_FEATURE(kFeedbackIncludeVariations,
+             "FeedbackIncludeVariations",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+#endif
+
 void MaybeUnpackVariationsStateFile() {
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   if (!command_line->HasSwitch(variations::switches::kVariationsStateFile)) {
@@ -98,6 +118,69 @@
   return s ? *s : std::string();
 }
 
+#if !BUILDFLAG(IS_CHROMEOS)
+// Encrypt `plaintext` with the `public_key` and save the result to
+// `ciphertext`. Also if `enc_len` is not null, update the length of enc
+// which is stored in `ciphertext`.
+VariationsStateEncryptionStatus EncryptStringWithPublicKey(
+    const std::string& plaintext,
+    std::vector<uint8_t>* ciphertext,
+    base::span<const uint8_t> public_key,
+    size_t* enc_len = nullptr) {
+  if (plaintext.empty()) {
+    return VariationsStateEncryptionStatus::kEmptyInput;
+  }
+  bssl::ScopedEVP_HPKE_CTX sender_context;
+
+  // The vector will hold the encapsulated shared secret "enc" followed by the
+  // symmetrically encrypted ciphertext "ct". Start with a size big enough for
+  // the shared secret.
+  ciphertext->resize(EVP_HPKE_MAX_ENC_LENGTH);
+  size_t encapsulated_shared_secret_len;
+
+  if (!EVP_HPKE_CTX_setup_sender(
+          /*ctx=*/sender_context.get(),
+          /*out_enc=*/ciphertext->data(),
+          /*out_enc_len=*/&encapsulated_shared_secret_len,
+          /*max_enc=*/ciphertext->size(),
+          /*kem=*/EVP_hpke_x25519_hkdf_sha256(),
+          /*kdf=*/EVP_hpke_hkdf_sha256(),
+          /*aead=*/EVP_hpke_aes_256_gcm(),
+          /*peer_public_key=*/public_key.data(),
+          /*peer_public_key_len=*/public_key.size(),
+          /*info=*/nullptr,
+          /*info_len=*/0)) {
+    DVLOG(1) << "hpke setup failed";
+    return VariationsStateEncryptionStatus::kHpkeSetupFailure;
+  }
+  if (enc_len != nullptr) {
+    *enc_len = encapsulated_shared_secret_len;
+  }
+  // This vector holds encapsulated shared secret and encrypted text.
+  // The encrypted text can be longer so we need to reserve enough length.
+  ciphertext->resize(encapsulated_shared_secret_len + plaintext.length() +
+                     EVP_HPKE_CTX_max_overhead(sender_context.get()));
+  auto ciphertext_span =
+      base::span(*ciphertext).subspan(encapsulated_shared_secret_len);
+  size_t ciphertext_len;
+
+  if (!EVP_HPKE_CTX_seal(
+          /*ctx=*/sender_context.get(),
+          /*out=*/ciphertext_span.data(),
+          /*out_len=*/&ciphertext_len,
+          /*max_out_len=*/ciphertext_span.size(),
+          /*in=*/reinterpret_cast<const uint8_t*>(plaintext.c_str()),
+          /*in_len=*/plaintext.length(),
+          /*ad=*/nullptr,
+          /*ad_len=*/0)) {
+    DVLOG(1) << "hpke seal failed";
+    return VariationsStateEncryptionStatus::kHpkeSealFailure;
+  }
+  ciphertext->resize(encapsulated_shared_secret_len + ciphertext_len);
+  return VariationsStateEncryptionStatus::kSuccess;
+}
+#endif
+
 }  // namespace
 
 VariationsCommandLine::VariationsCommandLine() = default;
@@ -130,7 +213,7 @@
   return result;
 }
 
-std::string VariationsCommandLine::ToString() {
+std::string VariationsCommandLine::ToString() const {
   std::string output;
   output.append(
       GenerateParam(::switches::kForceFieldTrials, field_trial_states));
@@ -229,4 +312,22 @@
   return serializer.Serialize(dict);
 }
 
+#if !BUILDFLAG(IS_CHROMEOS)
+VariationsStateEncryptionStatus VariationsCommandLine::EncryptToString(
+    std::vector<uint8_t>* ciphertext) const {
+  return EncryptStringWithPublicKey(ToString(), ciphertext,
+                                    kFeedbackEncryptionPublicKey);
+}
+
+VariationsStateEncryptionStatus
+VariationsCommandLine::EncryptToStringForTesting(
+    std::vector<uint8_t>* ciphertext,
+    base::span<const uint8_t> public_key,
+    size_t* enc_len) const {
+  CHECK_IS_TEST();
+  return EncryptStringWithPublicKey(ToString(), ciphertext, public_key,
+                                    enc_len);
+}
+#endif
+
 }  // namespace variations
diff --git a/components/variations/net/variations_command_line.h b/components/variations/net/variations_command_line.h
index 1079771..3cb5e39 100644
--- a/components/variations/net/variations_command_line.h
+++ b/components/variations/net/variations_command_line.h
@@ -8,6 +8,13 @@
 #include <optional>
 #include <string>
 
+#include "build/build_config.h"
+#include "build/buildflag.h"
+
+#if !BUILDFLAG(IS_CHROMEOS)
+#include "base/feature_list.h"
+#endif
+
 namespace base {
 class CommandLine;
 class FeatureList;
@@ -16,6 +23,23 @@
 
 namespace variations {
 
+#if !BUILDFLAG(IS_CHROMEOS)
+BASE_DECLARE_FEATURE(kFeedbackIncludeVariations);
+
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+//
+// LINT.IfChange(VariationsStateEncryptionStatus)
+enum class VariationsStateEncryptionStatus {
+  kSuccess = 0,
+  kEmptyInput = 1,
+  kHpkeSetupFailure = 2,
+  kHpkeSealFailure = 3,
+  kMaxValue = kHpkeSealFailure,
+};
+// LINT.ThenChange(//tools/metrics/histograms/metadata/variations/enums.xml:VariationsStateEncryptionStatus)
+#endif
+
 // Parses the content of `variations::switches::kVariationsStateFile` and
 // modifies the command-line arguments of the running process by setting the
 // switches contained in that file. The function will exit the process with
@@ -45,7 +69,7 @@
       const base::CommandLine& command_line);
 
   // Returns the state in command-line format.
-  std::string ToString();
+  std::string ToString() const;
 
   // Applies the state to the given `command_line`.
   void ApplyToCommandLine(base::CommandLine& command_line) const;
@@ -72,6 +96,26 @@
   // loaded back in with `ReadFromString`. Returns false if saving failed for
   // some reason.
   bool WriteToString(std::string* serialized_json) const;
+
+#if !BUILDFLAG(IS_CHROMEOS)
+  // Serializes and encrypts the state to `ciphertext` with a public key.
+  // Encryption is needed for security and privacy purpose. This is used by
+  // the feedback component.
+  // The `ciphertext` is a combination of:
+  //   The encapsulated shared secret + encrypted bytes.
+  VariationsStateEncryptionStatus EncryptToString(
+      std::vector<uint8_t>* ciphertext) const;
+
+  // Test the internal function `EncryptStringWithPublicKey`.
+  // The `ciphertext` is a combination of:
+  //   The encapsulated shared secret + encrypted bytes.
+  // If `enc_len` is not null, it will store the length of the
+  // encapsulated shared secret.
+  VariationsStateEncryptionStatus EncryptToStringForTesting(
+      std::vector<uint8_t>* ciphertext,
+      base::span<const uint8_t> public_key,
+      size_t* enc_len) const;
+#endif
 };
 
 }  // namespace variations
diff --git a/components/variations/net/variations_command_line_unittest.cc b/components/variations/net/variations_command_line_unittest.cc
index 759f829c..6a0b94e 100644
--- a/components/variations/net/variations_command_line_unittest.cc
+++ b/components/variations/net/variations_command_line_unittest.cc
@@ -20,6 +20,10 @@
 #include "components/variations/variations_switches.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if !BUILDFLAG(IS_CHROMEOS)
+#include "third_party/boringssl/src/include/openssl/hpke.h"
+#endif
+
 namespace variations {
 
 TEST(VariationsCommandLineTest, TestGetVariationsCommandLine) {
@@ -141,4 +145,79 @@
   BASE_EXPECT_DEATH(MaybeUnpackVariationsStateFile(), "");
 }
 
+#if !BUILDFLAG(IS_CHROMEOS)
+// This test verify the prod key can encrypt. But it doesn't check if the
+// ciphertext can be decoded or not on the server side.
+TEST(VariationsCommandLineTest, EncryptToString_ProdKey) {
+  VariationsCommandLine vc;
+  vc.field_trial_states = "trial1/group1/*trial2/group2";
+  vc.field_trial_params = "trial1.group1:p1/v1/p2/2";
+  vc.enable_features = "feature1<trial1";
+  vc.disable_features = "feature2<trial2";
+  std::vector<uint8_t> ciphertext;
+  auto status = vc.EncryptToString(&ciphertext);
+  EXPECT_EQ(status, VariationsStateEncryptionStatus::kSuccess);
+}
+
+// This test use a randomly generated public/private key pair and verify the
+// ciphertext can be decoded.
+// Note that in prod, the keyset was not generated in this way. So this test
+// passing doesn't necessary mean that in prod the server can decrypt the
+// reports.
+TEST(VariationsCommandLineTest, EncryptToString_EncryptAndDecryptUsingTestKey) {
+  EVP_HPKE_KEY* hpke_key = EVP_HPKE_KEY_new();
+  int result = EVP_HPKE_KEY_generate(hpke_key, EVP_hpke_x25519_hkdf_sha256());
+  EXPECT_EQ(result, 1);
+
+  std::vector<uint8_t> public_key(EVP_HPKE_MAX_PUBLIC_KEY_LENGTH, 0);
+  size_t public_key_len;
+  result = EVP_HPKE_KEY_public_key(hpke_key, public_key.data(), &public_key_len,
+                                   EVP_HPKE_MAX_PUBLIC_KEY_LENGTH);
+  EXPECT_EQ(result, 1);
+  public_key.resize(public_key_len);
+
+  VariationsCommandLine vc;
+  vc.field_trial_states = "trial1/group1/*trial2/group2";
+  vc.field_trial_params = "trial1.group1:p1/v1/p2/2";
+  vc.enable_features = "feature1<trial1";
+  vc.disable_features = "feature2<trial2";
+  std::vector<uint8_t> ciphertext;
+  size_t enc_len;
+  auto status = vc.EncryptToStringForTesting(&ciphertext, public_key, &enc_len);
+  EXPECT_EQ(status, VariationsStateEncryptionStatus::kSuccess);
+  EXPECT_GT(enc_len, 0u);
+
+  base::span<uint8_t> enc_span = base::span(ciphertext).subspan(0u, enc_len);
+  base::span<uint8_t> ciphertext_span = base::span(ciphertext).subspan(enc_len);
+  bssl::ScopedEVP_HPKE_CTX ctx;
+  result = EVP_HPKE_CTX_setup_recipient(
+      /*ctx=*/ctx.get(),
+      /*key=*/hpke_key,
+      /*kdf=*/EVP_hpke_hkdf_sha256(),
+      /*aead=*/EVP_hpke_aes_256_gcm(),
+      /*enc=*/enc_span.data(),
+      /*enc_len=*/enc_len,
+      /*info=*/nullptr,
+      /*info_len=*/0);
+  EXPECT_EQ(result, 1);
+  std::vector<uint8_t> decrypted(ciphertext_span.size(), 0);
+  size_t decrypted_len;
+
+  result = EVP_HPKE_CTX_open(
+      /*ctx=*/ctx.get(),
+      /*out=*/decrypted.data(),
+      /*out_len=*/&decrypted_len,
+      /*max_out_len=*/decrypted.size(),
+      /*in=*/ciphertext_span.data(),
+      /*in_len=*/ciphertext_span.size(),
+      /*ad=*/nullptr,
+      /*ad_len=*/0);
+  EXPECT_EQ(result, 1);
+  decrypted.resize(decrypted_len);
+
+  EXPECT_EQ(std::string(decrypted.begin(), decrypted.end()), vc.ToString());
+  EVP_HPKE_KEY_free(hpke_key);
+}
+#endif
+
 }  // namespace variations
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index 2fa9063bb..51ef96b3 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -421,6 +421,8 @@
       "frame_sinks/external_begin_frame_source_android.h",
       "gl/throw_uncaught_exception.cc",
       "gl/throw_uncaught_exception.h",
+      "input/fling_scheduler_android.cc",
+      "input/fling_scheduler_android.h",
       "input/render_input_router_support_android.cc",
       "input/render_input_router_support_android.h",
     ]
@@ -686,6 +688,7 @@
       "display/overlay_processor_surface_control_unittest.cc",
       "display/overlay_unittest.cc",
       "frame_sinks/external_begin_frame_source_android_unittest.cc",
+      "frame_sinks/fling_scheduler_android_unittest.cc",
     ]
   }
 
diff --git a/components/viz/service/frame_sinks/fling_scheduler_android_unittest.cc b/components/viz/service/frame_sinks/fling_scheduler_android_unittest.cc
new file mode 100644
index 0000000..f258268e
--- /dev/null
+++ b/components/viz/service/frame_sinks/fling_scheduler_android_unittest.cc
@@ -0,0 +1,206 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/service/input/fling_scheduler_android.h"
+
+#include "base/test/scoped_feature_list.h"
+#include "build/build_config.h"
+#include "components/input/features.h"
+#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
+#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "components/viz/service/input/input_manager.h"
+#include "components/viz/test/mock_compositor_frame_sink_client.h"
+#include "components/viz/test/test_output_surface_provider.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace viz {
+namespace {
+constexpr FrameSinkId kFrameSinkIdA(1, 1);
+}
+
+class FakeInputManager : public InputManager {
+ public:
+  explicit FakeInputManager(FrameSinkManagerImpl* frame_sink_manager)
+      : InputManager(frame_sink_manager) {}
+
+  FakeInputManager(const FakeInputManager&) = delete;
+  FakeInputManager& operator=(const FakeInputManager&) = delete;
+
+  ~FakeInputManager() override = default;
+
+  BeginFrameSource* GetBeginFrameSourceForFrameSink(
+      const FrameSinkId& id) override {
+    return &begin_frame_source_;
+  }
+
+ private:
+  StubBeginFrameSource begin_frame_source_;
+};
+
+class FlingSchedulerTest : public testing::Test,
+                           public input::FlingControllerEventSenderClient {
+ public:
+  FlingSchedulerTest()
+      : frame_sink_manager_(
+            FrameSinkManagerImpl::InitParams(&shared_bitmap_manager_,
+                                             &output_surface_provider_)) {
+    scoped_feature_list_.InitWithFeatures(
+        /* enabled_features */ {input::features::kInputOnViz},
+        /* disabled_features */ {});
+  }
+
+  FlingSchedulerTest(const FlingSchedulerTest&) = delete;
+  FlingSchedulerTest& operator=(const FlingSchedulerTest&) = delete;
+
+  void SetUp() override {
+    frame_sink_manager_.SetInputManagerForTesting(
+        std::make_unique<FakeInputManager>(&frame_sink_manager_));
+
+    // Create a CompositorFrameSinkImpl.
+    frame_sink_manager_.RegisterFrameSinkId(kFrameSinkIdA,
+                                            true /* report_activation */);
+    CreateCompositorFrameSink(kFrameSinkIdA,
+                              CreateRIRConfig(/*grouping_id=*/1));
+  }
+
+  void TearDown() override {
+    frame_sink_manager_.InvalidateFrameSinkId(kFrameSinkIdA);
+    fling_controller_.reset();
+  }
+
+  void SetupFlingController() {
+    auto* rir = GetFakeInputManager()->GetRenderInputRouterFromFrameSinkId(
+        kFrameSinkIdA);
+    fling_controller_ = std::make_unique<input::FlingController>(
+        this, rir->GetFlingSchedulerForTesting(),
+        input::FlingController::Config());
+  }
+
+  void SimulateFlingStart(const gfx::Vector2dF& velocity) {
+    blink::WebGestureEvent fling_start(
+        blink::WebInputEvent::Type::kGestureFlingStart, 0,
+        base::TimeTicks::Now(), blink::WebGestureDevice::kTouchscreen);
+    fling_start.data.fling_start.velocity_x = velocity.x();
+    fling_start.data.fling_start.velocity_y = velocity.y();
+    input::GestureEventWithLatencyInfo fling_start_with_latency(fling_start);
+    fling_controller_->ObserveAndMaybeConsumeGestureEvent(
+        fling_start_with_latency);
+  }
+
+  void SimulateFlingCancel() {
+    blink::WebGestureEvent fling_cancel(
+        blink::WebInputEvent::Type::kGestureFlingCancel, 0,
+        base::TimeTicks::Now(), blink::WebGestureDevice::kTouchscreen);
+    fling_cancel.data.fling_cancel.prevent_boosting = true;
+    input::GestureEventWithLatencyInfo fling_cancel_with_latency(fling_cancel);
+    fling_controller_->ObserveAndMaybeConsumeGestureEvent(
+        fling_cancel_with_latency);
+  }
+
+  // FlingControllerEventSenderClient
+  void SendGeneratedWheelEvent(
+      const input::MouseWheelEventWithLatencyInfo& wheel_event) override {}
+  void SendGeneratedGestureScrollEvents(
+      const input::GestureEventWithLatencyInfo& gesture_event) override {}
+  gfx::Size GetRootWidgetViewportSize() override {
+    return gfx::Size(1920, 1080);
+  }
+
+  input::FlingController* fling_controller() { return fling_controller_.get(); }
+  FlingSchedulerAndroid* fling_scheduler() {
+    auto* rir = GetFakeInputManager()->GetRenderInputRouterFromFrameSinkId(
+        kFrameSinkIdA);
+    return static_cast<FlingSchedulerAndroid*>(
+        rir->GetFlingSchedulerForTesting());
+  }
+
+  bool InputManagerExists() { return GetFakeInputManager(); }
+  bool ExpectedInputManagerCreation() {
+    return input::IsTransferInputToVizSupported();
+  }
+
+  FakeInputManager* GetFakeInputManager() {
+    return static_cast<FakeInputManager*>(
+        frame_sink_manager_.GetInputManager());
+  }
+
+ private:
+  input::mojom::RenderInputRouterConfigPtr CreateRIRConfig(int grouping_id) {
+    auto config = input::mojom::RenderInputRouterConfig::New();
+    mojo::PendingRemote<blink::mojom::RenderInputRouterClient> rir_client;
+    config->rir_client = std::move(rir_client);
+    config->grouping_id = grouping_id;
+    return config;
+  }
+
+  // Checks if a [Root]CompositorFrameSinkImpl exists for |frame_sink_id|.
+  bool CompositorFrameSinkExists(const FrameSinkId& frame_sink_id) {
+    return base::Contains(frame_sink_manager_.sink_map_, frame_sink_id) ||
+           base::Contains(frame_sink_manager_.root_sink_map_, frame_sink_id);
+  }
+
+  // Creates a CompositorFrameSinkImpl.
+  void CreateCompositorFrameSink(
+      const FrameSinkId& frame_sink_id,
+      input::mojom::RenderInputRouterConfigPtr config) {
+    MockCompositorFrameSinkClient compositor_frame_sink_client;
+    mojo::Remote<mojom::CompositorFrameSink> compositor_frame_sink;
+
+    frame_sink_manager_.CreateCompositorFrameSink(
+        frame_sink_id, /*bundle_id=*/std::nullopt,
+        compositor_frame_sink.BindNewPipeAndPassReceiver(),
+        compositor_frame_sink_client.BindInterfaceRemote(), std::move(config));
+    EXPECT_TRUE(CompositorFrameSinkExists(frame_sink_id));
+  }
+
+  std::unique_ptr<input::FlingController> fling_controller_;
+  ServerSharedBitmapManager shared_bitmap_manager_;
+  TestOutputSurfaceProvider output_surface_provider_;
+  FrameSinkManagerImpl frame_sink_manager_;
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+TEST_F(FlingSchedulerTest, ScheduleNextFlingProgress) {
+  EXPECT_EQ(InputManagerExists(), ExpectedInputManagerCreation());
+  if (!InputManagerExists()) {
+    // FlingSchedulerAndroid's implementation depends on InputManager creation.
+    // Exit if InputManager is not present.
+    return;
+  }
+
+  SetupFlingController();
+  ASSERT_EQ(
+      fling_scheduler()->GetBeginFrameSource(),
+      GetFakeInputManager()->GetBeginFrameSourceForFrameSink(kFrameSinkIdA));
+
+  SimulateFlingStart(gfx::Vector2dF(1000, 0));
+  EXPECT_EQ(fling_controller(), fling_scheduler()->fling_controller_.get());
+  EXPECT_EQ(fling_scheduler()->GetBeginFrameSource(),
+            fling_scheduler()->observed_begin_frame_source_);
+}
+
+TEST_F(FlingSchedulerTest, FlingCancelled) {
+  EXPECT_EQ(InputManagerExists(), ExpectedInputManagerCreation());
+  if (!InputManagerExists()) {
+    // FlingSchedulerAndroid's implementation depends on InputManager creation.
+    // Exit if InputManager is not present.
+    return;
+  }
+
+  SetupFlingController();
+  ASSERT_EQ(
+      fling_scheduler()->GetBeginFrameSource(),
+      GetFakeInputManager()->GetBeginFrameSourceForFrameSink(kFrameSinkIdA));
+
+  SimulateFlingStart(gfx::Vector2dF(1000, 0));
+  EXPECT_EQ(fling_controller(), fling_scheduler()->fling_controller_.get());
+  EXPECT_EQ(fling_scheduler()->GetBeginFrameSource(),
+            fling_scheduler()->observed_begin_frame_source_);
+
+  SimulateFlingCancel();
+  EXPECT_EQ(nullptr, fling_scheduler()->fling_controller_.get());
+  EXPECT_EQ(nullptr, fling_scheduler()->observed_begin_frame_source_);
+}
+
+}  // namespace viz
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.h b/components/viz/service/frame_sinks/frame_sink_manager_impl.h
index 93f0a42..ba98ee4 100644
--- a/components/viz/service/frame_sinks/frame_sink_manager_impl.h
+++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.h
@@ -392,6 +392,7 @@
  private:
   friend class FrameSinkManagerTest;
   friend class CompositorFrameSinkSupportTestBase;
+  friend class FlingSchedulerTest;
 
   // Metadata for a CompositorFrameSink.
   struct FrameSinkData {
diff --git a/components/viz/service/input/fling_scheduler_android.cc b/components/viz/service/input/fling_scheduler_android.cc
new file mode 100644
index 0000000..50c7fbef
--- /dev/null
+++ b/components/viz/service/input/fling_scheduler_android.cc
@@ -0,0 +1,114 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/service/input/fling_scheduler_android.h"
+
+#include "components/input/fling_controller.h"
+#include "components/input/render_input_router.h"
+
+namespace viz {
+
+FlingSchedulerAndroid::FlingSchedulerAndroid(input::RenderInputRouter* rir,
+                                             Delegate* delegate,
+                                             const FrameSinkId& frame_sink_id)
+    : rir_(*rir), delegate_(*delegate), frame_sink_id_(frame_sink_id) {}
+
+FlingSchedulerAndroid::~FlingSchedulerAndroid() {
+  StopObservingBeginFrames();
+}
+
+void FlingSchedulerAndroid::ScheduleFlingProgress(
+    base::WeakPtr<input::FlingController> fling_controller) {
+  DCHECK(fling_controller);
+  fling_controller_ = fling_controller;
+  if (observed_begin_frame_source_) {
+    return;
+  }
+  StartObservingBeginFrames();
+}
+
+void FlingSchedulerAndroid::DidStopFlingingOnBrowser(
+    base::WeakPtr<input::FlingController> fling_controller) {
+  DCHECK(fling_controller);
+  StopObservingBeginFrames();
+  fling_controller_ = nullptr;
+  rir_->DidStopFlinging();
+}
+
+bool FlingSchedulerAndroid::NeedsBeginFrameForFlingProgress() {
+  // Viz never receives an OnAnimate call since it don't have access to
+  // WindowAndroid. Hence, it always fall back to BeginFrames notifications
+  // coming from corresponding CompositorFrameSinkSupport's BeginFrameSource in
+  // Viz.
+  return true;
+}
+
+bool FlingSchedulerAndroid::ShouldUseMobileFlingCurve() {
+  return true;
+}
+
+gfx::Vector2dF FlingSchedulerAndroid::GetPixelsPerInch(
+    const gfx::PointF& position_in_screen) {
+  return gfx::Vector2dF(input::kDefaultPixelsPerInch,
+                        input::kDefaultPixelsPerInch);
+}
+
+void FlingSchedulerAndroid::ProgressFlingOnBeginFrameIfneeded(
+    base::TimeTicks current_time) {
+  // Called from synchronous compositor, which is used by WebView, which is not
+  // covered by InputVizard currently.
+  NOTREACHED();
+}
+
+BeginFrameSource* FlingSchedulerAndroid::GetBeginFrameSource() {
+  return delegate_->GetBeginFrameSourceForFrameSink(frame_sink_id_);
+}
+
+void FlingSchedulerAndroid::StartObservingBeginFrames() {
+  if (!fling_controller_) {
+    return;
+  }
+
+  if (observed_begin_frame_source_) {
+    return;
+  }
+
+  auto* begin_frame_provider = GetBeginFrameSource();
+  if (!begin_frame_provider) {
+    return;
+  }
+
+  begin_frame_provider->AddObserver(this);
+  observed_begin_frame_source_ = begin_frame_provider;
+}
+
+void FlingSchedulerAndroid::StopObservingBeginFrames() {
+  if (!observed_begin_frame_source_) {
+    return;
+  }
+  observed_begin_frame_source_->RemoveObserver(this);
+  observed_begin_frame_source_ = nullptr;
+}
+
+bool FlingSchedulerAndroid::OnBeginFrameDerivedImpl(
+    const BeginFrameArgs& args) {
+  DCHECK(observed_begin_frame_source_);
+  if (!fling_controller_) {
+    StopObservingBeginFrames();
+    return false;
+  }
+
+  if (args.type == BeginFrameArgs::MISSED) {
+    return false;
+  }
+
+  fling_controller_->ProgressFling(args.frame_time);
+  return true;
+}
+
+bool FlingSchedulerAndroid::IsRoot() const {
+  return false;
+}
+
+}  // namespace viz
diff --git a/components/viz/service/input/fling_scheduler_android.h b/components/viz/service/input/fling_scheduler_android.h
new file mode 100644
index 0000000..1499bac
--- /dev/null
+++ b/components/viz/service/input/fling_scheduler_android.h
@@ -0,0 +1,79 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_SERVICE_INPUT_FLING_SCHEDULER_ANDROID_H_
+#define COMPONENTS_VIZ_SERVICE_INPUT_FLING_SCHEDULER_ANDROID_H_
+
+#include "base/memory/raw_ptr.h"
+#include "components/input/fling_controller.h"
+#include "components/input/fling_scheduler_base.h"
+#include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h"
+#include "components/viz/service/viz_service_export.h"
+
+namespace input {
+class FlingController;
+class RenderInputRouter;
+}  // namespace input
+
+namespace viz {
+
+class VIZ_SERVICE_EXPORT FlingSchedulerAndroid
+    : public input::FlingSchedulerBase,
+      public BeginFrameObserverBase {
+ public:
+  class Delegate {
+   public:
+    virtual BeginFrameSource* GetBeginFrameSourceForFrameSink(
+        const FrameSinkId& id) = 0;
+  };
+
+  FlingSchedulerAndroid(input::RenderInputRouter* rir,
+                        Delegate* delegate,
+                        const FrameSinkId& frame_sink_id);
+
+  FlingSchedulerAndroid(const FlingSchedulerAndroid&) = delete;
+  FlingSchedulerAndroid& operator=(const FlingSchedulerAndroid&) = delete;
+
+  ~FlingSchedulerAndroid() override;
+
+  // FlingControllerSchedulerClient
+  void ScheduleFlingProgress(
+      base::WeakPtr<input::FlingController> fling_controller) override;
+  void DidStopFlingingOnBrowser(
+      base::WeakPtr<input::FlingController> fling_controller) override;
+  bool NeedsBeginFrameForFlingProgress() override;
+  bool ShouldUseMobileFlingCurve() override;
+  gfx::Vector2dF GetPixelsPerInch(
+      const gfx::PointF& position_in_screen) override;
+
+  // FlingSchedulerBase
+  void ProgressFlingOnBeginFrameIfneeded(base::TimeTicks current_time) override;
+
+ protected:
+  BeginFrameSource* GetBeginFrameSource();
+
+  raw_ref<input::RenderInputRouter> rir_;
+  base::WeakPtr<input::FlingController> fling_controller_;
+  raw_ptr<BeginFrameSource> observed_begin_frame_source_ = nullptr;
+
+ private:
+  FRIEND_TEST_ALL_PREFIXES(FlingSchedulerTest, ScheduleNextFlingProgress);
+  FRIEND_TEST_ALL_PREFIXES(FlingSchedulerTest, FlingCancelled);
+
+  void StartObservingBeginFrames();
+  void StopObservingBeginFrames();
+
+  // BeginFrameObserverBase implementation.
+  bool OnBeginFrameDerivedImpl(const BeginFrameArgs& args) override;
+  void OnBeginFrameSourcePausedChanged(bool paused) override {}
+  bool IsRoot() const override;
+
+  raw_ref<Delegate> delegate_;
+  const FrameSinkId frame_sink_id_;
+};
+
+}  // namespace viz
+
+#endif  // COMPONENTS_VIZ_SERVICE_INPUT_FLING_SCHEDULER_ANDROID_H_
diff --git a/components/viz/service/input/input_manager.cc b/components/viz/service/input/input_manager.cc
index 9cc31310..051f71b8 100644
--- a/components/viz/service/input/input_manager.cc
+++ b/components/viz/service/input/input_manager.cc
@@ -22,6 +22,7 @@
 #include "components/input/android/scoped_input_receiver.h"
 #include "components/input/android/scoped_input_receiver_callbacks.h"
 #include "components/input/android/scoped_input_transfer_token.h"
+#include "components/viz/service/input/fling_scheduler_android.h"
 #include "components/viz/service/input/render_input_router_support_android.h"
 #include "gpu/ipc/common/gpu_surface_lookup.h"
 #include "ui/gfx/android/android_surface_control_compat.h"
@@ -106,6 +107,27 @@
   frame_sink_manager_->AddObserver(this);
 }
 
+std::unique_ptr<input::FlingSchedulerBase> InputManager::MakeFlingScheduler(
+    input::RenderInputRouter* rir,
+    const FrameSinkId& frame_sink_id) {
+#if BUILDFLAG(IS_ANDROID)
+  return std::make_unique<FlingSchedulerAndroid>(rir, this, frame_sink_id);
+#else
+  NOTREACHED();
+#endif
+}
+
+void InputManager::SetupRenderInputRouter(
+    input::RenderInputRouter* render_input_router,
+    const FrameSinkId& frame_sink_id) {
+  // TODO(382291983): Setup RenderInputRouter's mojo connections to renderer.
+  render_input_router->SetFlingScheduler(
+      MakeFlingScheduler(render_input_router, frame_sink_id));
+
+  render_input_router->SetupInputRouter(
+      GetDeviceScaleFactorForId(frame_sink_id));
+}
+
 void InputManager::OnCreateCompositorFrameSink(
     const FrameSinkId& frame_sink_id,
     bool is_root,
@@ -158,8 +180,7 @@
       /* fling_scheduler */ nullptr,
       /* delegate */ rir_delegate.get(),
       base::SingleThreadTaskRunner::GetCurrentDefault());
-  render_input_router->SetupInputRouter(
-      GetDeviceScaleFactorForId(frame_sink_id));
+  SetupRenderInputRouter(render_input_router.get(), frame_sink_id);
 
   frame_sink_metadata_map_.emplace(std::make_pair(
       frame_sink_id,
@@ -517,6 +538,11 @@
   return true;
 }
 
+BeginFrameSource* InputManager::GetBeginFrameSourceForFrameSink(
+    const FrameSinkId& id) {
+  return frame_sink_manager_->GetFrameSinkForId(id)->begin_frame_source();
+}
+
 #endif  // BUILDFLAG(IS_ANDROID)
 
 }  // namespace viz
diff --git a/components/viz/service/input/input_manager.h b/components/viz/service/input/input_manager.h
index 21c8fbdb..5739e91 100644
--- a/components/viz/service/input/input_manager.h
+++ b/components/viz/service/input/input_manager.h
@@ -23,6 +23,7 @@
 #if BUILDFLAG(IS_ANDROID)
 #include "components/input/android/android_input_callback.h"
 #include "components/input/android/input_receiver_data.h"
+#include "components/viz/service/input/fling_scheduler_android.h"
 #endif
 
 namespace input {
@@ -55,6 +56,7 @@
       public input::RenderWidgetHostInputEventRouter::Delegate,
 #if BUILDFLAG(IS_ANDROID)
       public input::AndroidInputCallbackClient,
+      public FlingSchedulerAndroid::Delegate,
 #endif
       public RenderInputRouterSupportBase::Delegate,
       public RenderInputRouterDelegateImpl::Delegate {
@@ -98,6 +100,10 @@
   // AndroidInputCallbackClient implementation.
   bool OnMotionEvent(base::android::ScopedInputEvent input_event,
                      const FrameSinkId& root_frame_sink_id) override;
+
+  // FlingSchedulerAndroid::Delegate implementation.
+  BeginFrameSource* GetBeginFrameSourceForFrameSink(
+      const FrameSinkId& id) override;
 #endif
 
   // RenderInputRouterDelegateImpl::Delegate implementation.
@@ -134,6 +140,13 @@
 
   void OnRIRDelegateClientDisconnected(uint32_t grouping_id);
 
+  void SetupRenderInputRouter(input::RenderInputRouter* render_input_router,
+                              const FrameSinkId& frame_sink_id);
+
+  std::unique_ptr<input::FlingSchedulerBase> MakeFlingScheduler(
+      input::RenderInputRouter* rir,
+      const FrameSinkId& frame_sink_id);
+
 #if BUILDFLAG(IS_ANDROID)
   // Android input receiver is created only for the very first root compositor
   // frame sink creation notification that InputManager receives.
diff --git a/components/viz/service/input/mock_input_manager.cc b/components/viz/service/input/mock_input_manager.cc
index 9152292..201f89d 100644
--- a/components/viz/service/input/mock_input_manager.cc
+++ b/components/viz/service/input/mock_input_manager.cc
@@ -21,4 +21,13 @@
   return frame_sink_metadata_map_.find(id)->second.rir_support.get();
 }
 
+input::RenderInputRouter* MockInputManager::GetRenderInputRouterForId(
+    const FrameSinkId& id) {
+  auto itr = rir_map_.find(id);
+  if (itr == rir_map_.end()) {
+    return nullptr;
+  }
+  return itr->second.get();
+}
+
 }  // namespace viz
diff --git a/components/viz/service/input/mock_input_manager.h b/components/viz/service/input/mock_input_manager.h
index c60997a5..d5f3a6d 100644
--- a/components/viz/service/input/mock_input_manager.h
+++ b/components/viz/service/input/mock_input_manager.h
@@ -30,6 +30,8 @@
 
   RenderInputRouterSupportBase* GetSupportForFrameSink(const FrameSinkId& id);
 
+  input::RenderInputRouter* GetRenderInputRouterForId(const FrameSinkId& id);
+
   int GetInputEventRouterMapSize() { return rwhier_map_.size(); }
 };
 
diff --git a/components/viz/test/test_gpu_service_holder.cc b/components/viz/test/test_gpu_service_holder.cc
index 644d4a2..c1aa9c46 100644
--- a/components/viz/test/test_gpu_service_holder.cc
+++ b/components/viz/test/test_gpu_service_holder.cc
@@ -138,8 +138,7 @@
   }
 
   if (!g_holder) {
-    g_holder = new TestGpuServiceHolder(gpu::gles2::ParseGpuPreferences(
-        base::CommandLine::ForCurrentProcess()));
+    g_holder = new TestGpuServiceHolder();
   }
   return g_holder;
 }
@@ -180,6 +179,10 @@
   g_disallow_feature_list_overrides = true;
 }
 
+TestGpuServiceHolder::TestGpuServiceHolder()
+    : TestGpuServiceHolder(gpu::gles2::ParseGpuPreferences(
+          base::CommandLine::ForCurrentProcess())) {}
+
 TestGpuServiceHolder::TestGpuServiceHolder(
     const gpu::GpuPreferences& gpu_preferences)
     : gpu_main_thread_("GPUMainThread"), io_thread_("GPUIOThread") {
diff --git a/components/viz/test/test_gpu_service_holder.h b/components/viz/test/test_gpu_service_holder.h
index ceda4e4..c4f3e61 100644
--- a/components/viz/test/test_gpu_service_holder.h
+++ b/components/viz/test/test_gpu_service_holder.h
@@ -93,6 +93,7 @@
   // GetInstance().
   static void DoNotResetOnTestExit();
 
+  TestGpuServiceHolder();
   explicit TestGpuServiceHolder(const gpu::GpuPreferences& preferences);
 
   TestGpuServiceHolder(const TestGpuServiceHolder&) = delete;
diff --git a/components/webapps/browser/android/translations/android_webapps_strings_zh-CN.xtb b/components/webapps/browser/android/translations/android_webapps_strings_zh-CN.xtb
index 9275250..c18eddc 100644
--- a/components/webapps/browser/android/translations/android_webapps_strings_zh-CN.xtb
+++ b/components/webapps/browser/android/translations/android_webapps_strings_zh-CN.xtb
@@ -4,7 +4,7 @@
 <translation id="1213425325105380833">恢复您最近在与此账号相关联的设备上使用过的 Web 应用</translation>
 <translation id="1344914278748983512">已安装此应用</translation>
 <translation id="1353513225130339633">正在检查应用是否可以安装…</translation>
-<translation id="1786044937610313874">在 Chrome 中打开快捷方式</translation>
+<translation id="1786044937610313874">快捷方式会在 Chrome 中打开</translation>
 <translation id="204914487372604757">创建快捷方式</translation>
 <translation id="2065911435109240297">恢复 Web 应用</translation>
 <translation id="2111649875343992405">查看要恢复的 Web 应用</translation>
diff --git a/components/webcrypto/algorithms/aes_cbc_unittest.cc b/components/webcrypto/algorithms/aes_cbc_unittest.cc
index ae066f2..ab0c7db6 100644
--- a/components/webcrypto/algorithms/aes_cbc_unittest.cc
+++ b/components/webcrypto/algorithms/aes_cbc_unittest.cc
@@ -11,6 +11,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <array>
 #include <memory>
 #include <utility>
 
@@ -140,7 +141,7 @@
   const char* ciphertext;
 };
 
-const AesCbcKnownAnswer kAesCbcKnownAnswers[] = {
+const auto kAesCbcKnownAnswers = std::to_array<AesCbcKnownAnswer>({
     // F.2.1 (CBC-AES128.Encrypt)
     // http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
     {"2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090a0b0c0d0e0f",
@@ -168,7 +169,8 @@
 
     // Taken from encryptor_unittest.cc (EncryptorTest.EmptyEncrypt())
     {"3132383d5369787465656e4279746573", "5377656574205369787465656e204956", "",
-     "8518b8878d34e7185e300d0fcc426396"}};
+     "8518b8878d34e7185e300d0fcc426396"},
+});
 
 TEST_F(WebCryptoAesCbcTest, KnownAnswers) {
   for (const auto& test : kAesCbcKnownAnswers) {
diff --git a/components/webcrypto/algorithms/aes_ctr_unittest.cc b/components/webcrypto/algorithms/aes_ctr_unittest.cc
index 59cfd7ea..59a423a8 100644
--- a/components/webcrypto/algorithms/aes_ctr_unittest.cc
+++ b/components/webcrypto/algorithms/aes_ctr_unittest.cc
@@ -5,6 +5,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <array>
+
 #include "base/containers/span.h"
 #include "components/webcrypto/algorithm_dispatch.h"
 #include "components/webcrypto/algorithms/test_helpers.h"
@@ -47,7 +49,7 @@
 const char k256BitTestKey[] =
     "F6D66D6BD52D59BB0796365879EFF886C66DD51A5B6A99744B50590C87A23884";
 
-const AesCtrKnownAnswer kAesCtrKnownAnswers[] = {
+const auto kAesCtrKnownAnswers = std::to_array<AesCtrKnownAnswer>({
     // RFC 3686 test vector #3:
     {k128BitTestKey,
      "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223",
@@ -94,7 +96,7 @@
      "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE", 128,
      "D2C49B275BC73814DC90ECE98959041C9A3481F2247E08B0AF5D8DE3F521C9DAF535B0A81"
      "56DF9D2370EE7328103C8AD"},
-};
+});
 
 TEST_F(WebCryptoAesCtrTest, EncryptDecryptKnownAnswer) {
   for (const auto& test : kAesCtrKnownAnswers) {
diff --git a/components/webcrypto/algorithms/aes_gcm_unittest.cc b/components/webcrypto/algorithms/aes_gcm_unittest.cc
index 1627992..dada7aa1 100644
--- a/components/webcrypto/algorithms/aes_gcm_unittest.cc
+++ b/components/webcrypto/algorithms/aes_gcm_unittest.cc
@@ -5,6 +5,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <array>
+
 #include "base/test/gmock_expected_support.h"
 #include "base/types/expected.h"
 #include "components/webcrypto/algorithm_dispatch.h"
@@ -114,7 +116,7 @@
 
 // NIST GCM test vectors:
 // http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
-const AesGcmKnownAnswer kAesGcmKnownAnswers[] = {
+const auto kAesGcmKnownAnswers = std::to_array<AesGcmKnownAnswer>({
     {"cf063a34d4a9a76c2c86787d3f96db71", "113b9785971864c83b01c787", "", "",
      "72ac8493e3a5228b5d130a69d2510e42", 128},
     {"6dfa1a07c14f978020ace450ad663d18", "34edfa462a14c6969a680ec1", "",
@@ -135,7 +137,7 @@
      "fda718aa1ec163487e21afc34f5a3a34795a9ee71dd3e7ee9a18fdb24181dc982b29c6ec7"
      "23294a130ca2234952bb0ef68c0f34795fbe0",
      32},
-};
+});
 
 // TODO(eroman):
 //   * Test decryption when the tag length exceeds input size
diff --git a/components/webcrypto/algorithms/aes_kw_unittest.cc b/components/webcrypto/algorithms/aes_kw_unittest.cc
index 1fe8e33e..4f650b2 100644
--- a/components/webcrypto/algorithms/aes_kw_unittest.cc
+++ b/components/webcrypto/algorithms/aes_kw_unittest.cc
@@ -5,6 +5,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <array>
 #include <memory>
 
 #include "base/values.h"
@@ -31,7 +32,7 @@
   const char* ciphertext;
 };
 
-const AesKwKnownAnswer kAesKwKnownAnswers[] = {
+const auto kAesKwKnownAnswers = std::to_array<AesKwKnownAnswer>({
     // AES-KW test vectors from http://www.ietf.org/rfc/rfc3394.txt
     // 4.1 Wrap 128 bits of Key Data with a 128-bit KEK
     {"000102030405060708090A0B0C0D0E0F", "00112233445566778899AABBCCDDEEFF",
@@ -48,7 +49,8 @@
     {"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
      "00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F",
      "28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43BFB988B9B7"
-     "A02DD21"}};
+     "A02DD21"},
+});
 
 TEST_F(WebCryptoAesKwTest, GenerateKeyBadLength) {
   blink::WebCryptoKey key;
diff --git a/components/webcrypto/algorithms/hmac_unittest.cc b/components/webcrypto/algorithms/hmac_unittest.cc
index 2df6aeb..1af2fa8 100644
--- a/components/webcrypto/algorithms/hmac_unittest.cc
+++ b/components/webcrypto/algorithms/hmac_unittest.cc
@@ -11,6 +11,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <array>
 #include <memory>
 #include <utility>
 
@@ -73,7 +74,7 @@
   const char* hmac;
 };
 
-const HmacKnownAnswer kHmacKnownAnswers[] = {
+const auto kHmacKnownAnswers = std::to_array<HmacKnownAnswer>({
     // A single byte key with an empty message, generated with:
     //   openssl dgst -sha{1,256} -hmac "" < /dev/null
     {blink::kWebCryptoAlgorithmIdSha1, "00", "",
@@ -139,7 +140,8 @@
      "b191d5cf3fc3e8da95a0f9f4a2a7964289c3129b512bd890de8700a9205420f28a8965b6c"
      "67be28ba7fe278e5fcd16f0f22cf2b2eacbb9",
      "4459066109cb11e6870fa9c6bfd251adfa304c0a2928ca915049704972edc560cc7c0bc38"
-     "249e9101aae2f7d4da62eaff83fb07134efc277de72b9e4ab360425"}};
+     "249e9101aae2f7d4da62eaff83fb07134efc277de72b9e4ab360425"},
+});
 
 blink::WebCryptoKey HmacKeyFromHexBytes(blink::WebCryptoAlgorithmId hash,
                                         const char* key) {
diff --git a/components/webcrypto/algorithms/rsa_oaep_unittest.cc b/components/webcrypto/algorithms/rsa_oaep_unittest.cc
index 11a9de1..0e11d8af 100644
--- a/components/webcrypto/algorithms/rsa_oaep_unittest.cc
+++ b/components/webcrypto/algorithms/rsa_oaep_unittest.cc
@@ -5,6 +5,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <array>
 #include <string_view>
 
 #include "base/base64url.h"
@@ -150,7 +151,7 @@
   const char* plaintext;
 };
 
-const RsaOaepKnownAnswer kRsaOaepKnownAnswers[] = {
+const auto kRsaOaepKnownAnswers = std::to_array<RsaOaepKnownAnswer>({
     // Tests for RSA-OAEP Encrypt/Decrypt without a label (the empty string).
     {"30819f300d06092a864886f70d010101050003818d0030818902818100a56e4a0e7010175"
      "89a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283"
@@ -357,7 +358,7 @@
      "0D620F00CFA33AE318AF6090B76E4ADC5FE1686165786F8B7E559156E8AF690D6EF050133"
      "AB5620FAF91B17CF52FED0B57FAC0924F2CC4",
      ""},
-};
+});
 
 TEST_F(WebCryptoRsaOaepTest, EncryptDecryptKnownAnswerTest) {
   for (const auto& test : kRsaOaepKnownAnswers) {
@@ -650,7 +651,7 @@
     const blink::WebCryptoKeyUsageMask usage;
     const char* const jwk_alg;
   };
-  const TestCase kTests[] = {
+  const auto kTests = std::to_array<TestCase>({
       {blink::kWebCryptoAlgorithmIdSha1, blink::kWebCryptoKeyUsageEncrypt,
        "RSA-OAEP"},
       {blink::kWebCryptoAlgorithmIdSha256, blink::kWebCryptoKeyUsageEncrypt,
@@ -658,7 +659,8 @@
       {blink::kWebCryptoAlgorithmIdSha384, blink::kWebCryptoKeyUsageEncrypt,
        "RSA-OAEP-384"},
       {blink::kWebCryptoAlgorithmIdSha512, blink::kWebCryptoKeyUsageEncrypt,
-       "RSA-OAEP-512"}};
+       "RSA-OAEP-512"},
+  });
 
   for (const auto& test : kTests) {
     SCOPED_TRACE(&test - &kTests[0]);
diff --git a/components/webcrypto/algorithms/rsa_pss_unittest.cc b/components/webcrypto/algorithms/rsa_pss_unittest.cc
index a9f283f..1902643 100644
--- a/components/webcrypto/algorithms/rsa_pss_unittest.cc
+++ b/components/webcrypto/algorithms/rsa_pss_unittest.cc
@@ -5,6 +5,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <array>
+
 #include "base/strings/string_number_conversions.h"
 #include "components/webcrypto/algorithm_dispatch.h"
 #include "components/webcrypto/algorithms/test_helpers.h"
@@ -179,7 +181,7 @@
   const char* signature;
 };
 
-const RsaPssKnownAnswer kRsaPssKnownAnswers[] = {
+const auto kRsaPssKnownAnswers = std::to_array<RsaPssKnownAnswer>({
     // Example 1.1 from pss-vect.txt in
     // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
     {blink::kWebCryptoAlgorithmIdSha1, kKey1,
@@ -219,7 +221,7 @@
      "070ebf79c33fd86c2d608be9438b3d420d09535b97cd3d846ecaf8f6551cdf93197e9f8fb"
      "048044473ab41a801e9f7fc983c62b324361dade9f71a65952bd35c59faaa4d6ff462f68a"
      "6c4ec0b428aa47336f2178aeb276136563b7d"},
-};
+});
 
 blink::WebCryptoKey RsaPssKeyFromBytes(blink::WebCryptoAlgorithmId hash,
                                        const char* key) {
diff --git a/components/webcrypto/algorithms/rsa_ssa_unittest.cc b/components/webcrypto/algorithms/rsa_ssa_unittest.cc
index 575fa0d..715d0d4c 100644
--- a/components/webcrypto/algorithms/rsa_ssa_unittest.cc
+++ b/components/webcrypto/algorithms/rsa_ssa_unittest.cc
@@ -5,6 +5,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <array>
 #include <string_view>
 
 #include "base/check_op.h"
@@ -575,13 +576,11 @@
 TEST_F(WebCryptoRsaSsaTest, GenerateKeyPairRsaBadExponent) {
   const unsigned int modulus_length = 1024;
 
-  const char* const kPublicExponents[] = {
+  const auto kPublicExponents = std::to_array<const char*>({
       "11",  // 17 - This is a valid public exponent, but currently disallowed.
-      "00",
-      "01",
-      "02",
+      "00", "01", "02",
       "010000",  // 65536
-  };
+  });
 
   for (auto* const exponent : kPublicExponents) {
     SCOPED_TRACE(&exponent - &kPublicExponents[0]);
@@ -881,14 +880,16 @@
     const blink::WebCryptoKeyUsageMask usage;
     const char* const jwk_alg;
   };
-  const TestCase kTests[] = {{blink::kWebCryptoAlgorithmIdSha1,
-                              blink::kWebCryptoKeyUsageVerify, "RS1"},
-                             {blink::kWebCryptoAlgorithmIdSha256,
-                              blink::kWebCryptoKeyUsageVerify, "RS256"},
-                             {blink::kWebCryptoAlgorithmIdSha384,
-                              blink::kWebCryptoKeyUsageVerify, "RS384"},
-                             {blink::kWebCryptoAlgorithmIdSha512,
-                              blink::kWebCryptoKeyUsageVerify, "RS512"}};
+  const auto kTests = std::to_array<TestCase>({
+      {blink::kWebCryptoAlgorithmIdSha1, blink::kWebCryptoKeyUsageVerify,
+       "RS1"},
+      {blink::kWebCryptoAlgorithmIdSha256, blink::kWebCryptoKeyUsageVerify,
+       "RS256"},
+      {blink::kWebCryptoAlgorithmIdSha384, blink::kWebCryptoKeyUsageVerify,
+       "RS384"},
+      {blink::kWebCryptoAlgorithmIdSha512, blink::kWebCryptoKeyUsageVerify,
+       "RS512"},
+  });
 
   for (const auto& test : kTests) {
     SCOPED_TRACE(&test - &kTests[0]);
diff --git a/content/browser/accessibility/browser_accessibility_state_impl.cc b/content/browser/accessibility/browser_accessibility_state_impl.cc
index da2a4ae..90ebe65 100644
--- a/content/browser/accessibility/browser_accessibility_state_impl.cc
+++ b/content/browser/accessibility/browser_accessibility_state_impl.cc
@@ -33,6 +33,7 @@
 #include "ui/accessibility/platform/ax_platform_node.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/gfx/color_utils.h"
+#include "ui/native_theme/native_theme.h"
 
 namespace content {
 
@@ -400,6 +401,14 @@
       "Accessibility.ManuallyEnabled",
       !GetAccessibilityMode().is_mode_off() && !allow_ax_mode_changes_);
 
+#if BUILDFLAG(IS_WIN)
+  base::UmaHistogramEnumeration(
+      "Accessibility.WinHighContrastTheme",
+      ui::NativeTheme::GetInstanceForNativeUi()
+          ->GetPlatformHighContrastColorScheme(),
+      ui::NativeTheme::PlatformHighContrastColorScheme::kMaxValue);
+#endif
+
   ui_thread_done_ = true;
   if (other_thread_done_ && background_thread_done_callback_) {
     std::move(background_thread_done_callback_).Run();
diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding.cc b/content/browser/indexed_db/indexed_db_leveldb_coding.cc
index ae776093..35e7065 100644
--- a/content/browser/indexed_db/indexed_db_leveldb_coding.cc
+++ b/content/browser/indexed_db/indexed_db_leveldb_coding.cc
@@ -336,13 +336,13 @@
 
 void EncodeBinary(const std::string& value, std::string* into) {
   EncodeVarInt(value.length(), into);
-  into->append(value.begin(), value.end());
+  into->append(value);
   DCHECK_GE(into->size(), value.size());
 }
 
 void EncodeBinary(base::span<const uint8_t> value, std::string* into) {
   EncodeVarInt(value.size(), into);
-  into->append(value.begin(), value.end());
+  into->append(base::as_string_view(value));
   DCHECK_GE(into->size(), value.size());
 }
 
@@ -353,8 +353,7 @@
 
 void EncodeDouble(double value, std::string* into) {
   // This always has host endianness.
-  const char* p = reinterpret_cast<char*>(&value);
-  into->insert(into->end(), p, p + sizeof(value));
+  into->append(base::as_string_view(base::byte_span_from_ref(value)));
 }
 
 // Return value is true iff successful.
diff --git a/content/browser/interest_group/auction_runner_unittest.cc b/content/browser/interest_group/auction_runner_unittest.cc
index 1bd98a3..6da009ed 100644
--- a/content/browser/interest_group/auction_runner_unittest.cc
+++ b/content/browser/interest_group/auction_runner_unittest.cc
@@ -20611,43 +20611,9 @@
 
 class RoundingTest : public AuctionRunnerTest,
                      public ::testing::WithParamInterface<size_t> {
- public:
-  RoundingTest(size_t bid_bits, size_t score_bits, size_t cost_bits)
-      : bid_bits_(bid_bits), score_bits_(score_bits), cost_bits_(cost_bits) {
-    scoped_feature_list_.InitWithFeaturesAndParameters(
-        {{kFledgeRounding,
-          {{kFledgeBidReportingBits.name, base::NumberToString(bid_bits_)},
-           {kFledgeScoreReportingBits.name, base::NumberToString(score_bits_)},
-           {kFledgeAdCostReportingBits.name,
-            base::NumberToString(cost_bits_)}}}},
-        {});
-  }
-
-  size_t bid_bits() { return bid_bits_; }
-  size_t score_bits() { return score_bits_; }
-  size_t cost_bits() { return cost_bits_; }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-  size_t bid_bits_, score_bits_, cost_bits_;
 };
 
-class BidRoundingTest : public RoundingTest {
- public:
-  BidRoundingTest() : RoundingTest(GetParam(), 8, 8) {}
-};
-
-class ScoreRoundingTest : public RoundingTest {
- public:
-  ScoreRoundingTest() : RoundingTest(8, GetParam(), 8) {}
-};
-
-class CostRoundingTest : public RoundingTest {
- public:
-  CostRoundingTest() : RoundingTest(8, 8, GetParam()) {}
-};
-
-TEST_P(CostRoundingTest, AdCostPassed) {
+TEST_F(RoundingTest, AdCostPassed) {
   const char kBidScript[] = R"(
     const bid = %d;
     function generateBid(
@@ -20692,7 +20658,7 @@
                   GURL("https://buyer-reporting.example.com/?adCost=2")));
 }
 
-TEST_P(CostRoundingTest, AdCostRounded) {
+TEST_F(RoundingTest, AdCostRounded) {
   const char kBidScript[] = R"(
     const bid = %f;
     function generateBid(
@@ -20732,34 +20698,14 @@
   EXPECT_EQ(kBidder1Key, result_.winning_group_id);
   EXPECT_EQ(GURL("https://ad1.com/"), result_.ad_descriptor->url);
 
-  switch (GetParam()) {
-    case 8:
-      EXPECT_THAT(
-          result_.report_urls,
-          testing::ElementsAre(testing::AnyOf(
-              GURL("https://buyer-reporting.example.com/?adCost=1.9921875"),
-              GURL("https://buyer-reporting.example.com/?adCost=1.984375"))));
-      break;
-    case 16:
-      EXPECT_THAT(result_.report_urls,
-                  testing::ElementsAre(
-                      testing::AnyOf(GURL("https://buyer-reporting.example.com/"
-                                          "?adCost=1.990020751953125"),
-                                     GURL("https://buyer-reporting.example.com/"
-                                          "?adCost=1.989990234375"))));
-      break;
-    case 53:
-      EXPECT_THAT(result_.report_urls,
-                  testing::ElementsAre(GURL(
-                      "https://buyer-reporting.example.com/?adCost=1.99")));
-      break;
-    default:
-      // Not a supported test case.
-      ASSERT_TRUE(false);
-  }
+  EXPECT_THAT(
+      result_.report_urls,
+      testing::ElementsAre(testing::AnyOf(
+          GURL("https://buyer-reporting.example.com/?adCost=1.9921875"),
+          GURL("https://buyer-reporting.example.com/?adCost=1.984375"))));
 }
 
-TEST_P(CostRoundingTest, AdCostExponentTruncated) {
+TEST_F(RoundingTest, AdCostExponentTruncated) {
   const char kBidScript[] = R"(
     const bid = %d;
     function generateBid(
@@ -20803,11 +20749,6 @@
                   "https://buyer-reporting.example.com/?adCost=Infinity")));
 }
 
-INSTANTIATE_TEST_SUITE_P(
-    /* no label */,
-    CostRoundingTest,
-    testing::Values(8, 16, 53));
-
 TEST_F(AuctionRunnerTest, ModelingSignalsPassed) {
   // Due to noising, modelingSignals is only correctly passed 99% of the time.
   //
@@ -21177,7 +21118,7 @@
   EXPECT_EQ(GURL("https://ad1.com/"), result_.ad_descriptor->url);
 }
 
-TEST_P(BidRoundingTest, BidRounded) {
+TEST_F(RoundingTest, BidRounded) {
   const char kBidScript[] = R"(
     function generateBid(
         interestGroup, auctionSignals, perBuyerSignals, trustedBiddingSignals,
@@ -21217,44 +21158,18 @@
   EXPECT_EQ(kBidder1Key, result_.winning_group_id);
   EXPECT_EQ(GURL("https://ad1.com/"), result_.ad_descriptor->url);
 
-  switch (GetParam()) {
-    case 8:
-      EXPECT_THAT(
-          result_.report_urls,
-          testing::AnyOf(
-              testing::ElementsAre(
-                  GURL("https://seller-reporting.example.com/?bid=1.9921875"),
-                  GURL("https://buyer-reporting.example.com/?bid=1.9921875")),
-              testing::ElementsAre(
-                  GURL("https://seller-reporting.example.com/?bid=1.984375"),
-                  GURL("https://buyer-reporting.example.com/?bid=1.984375"))));
-      break;
-    case 16:
-      EXPECT_THAT(
-          result_.report_urls,
-          testing::AnyOf(
-              testing::ElementsAre(GURL("https://seller-reporting.example.com/"
-                                        "?bid=1.990020751953125"),
-                                   GURL("https://buyer-reporting.example.com/"
-                                        "?bid=1.990020751953125")),
-              testing::ElementsAre(GURL("https://seller-reporting.example.com/"
-                                        "?bid=1.989990234375"),
-                                   GURL("https://buyer-reporting.example.com/"
-                                        "?bid=1.989990234375"))));
-      break;
-    case 53:
-      EXPECT_THAT(result_.report_urls,
-                  testing::ElementsAre(
-                      GURL("https://seller-reporting.example.com/?bid=1.99"),
-                      GURL("https://buyer-reporting.example.com/?bid=1.99")));
-      break;
-    default:
-      // Not a supported test case.
-      ASSERT_TRUE(false);
-  }
+  EXPECT_THAT(
+      result_.report_urls,
+      testing::AnyOf(
+          testing::ElementsAre(
+              GURL("https://seller-reporting.example.com/?bid=1.9921875"),
+              GURL("https://buyer-reporting.example.com/?bid=1.9921875")),
+          testing::ElementsAre(
+              GURL("https://seller-reporting.example.com/?bid=1.984375"),
+              GURL("https://buyer-reporting.example.com/?bid=1.984375"))));
 }
 
-TEST_P(BidRoundingTest, HighestScoringOtherBidRounded) {
+TEST_F(RoundingTest, HighestScoringOtherBidRounded) {
   const char kBidScript[] = R"(
     function generateBid(
         interestGroup, auctionSignals, perBuyerSignals, trustedBiddingSignals,
@@ -21295,53 +21210,19 @@
   EXPECT_EQ(kBidder2Key, result_.winning_group_id);
   EXPECT_EQ(GURL("https://ad2.com/"), result_.ad_descriptor->url);
 
-  switch (GetParam()) {
-    case 8:
-      EXPECT_THAT(
-          result_.report_urls,
-          testing::ElementsAre(
-              testing::AnyOf(GURL("https://seller-reporting.example.com/"
-                                  "?highestScoringOtherBid=1.9921875"),
-                             GURL("https://seller-reporting.example.com/"
-                                  "?highestScoringOtherBid=1.984375")),
-              testing::AnyOf(GURL("https://buyer-reporting.example.com/"
-                                  "?highestScoringOtherBid=1.9921875"),
-                             GURL("https://buyer-reporting.example.com/"
-                                  "?highestScoringOtherBid=1.984375"))));
-      break;
-    case 16:
-      EXPECT_THAT(
-          result_.report_urls,
-          testing::ElementsAre(
-              testing::AnyOf(GURL("https://seller-reporting.example.com/"
-                                  "?highestScoringOtherBid=1.990020751953125"),
-                             GURL("https://seller-reporting.example.com/"
-                                  "?highestScoringOtherBid=1.989990234375")),
-              testing::AnyOf(GURL("https://buyer-reporting.example.com/"
-                                  "?highestScoringOtherBid=1.990020751953125"),
-                             GURL("https://buyer-reporting.example.com/"
-                                  "?highestScoringOtherBid=1.989990234375"))));
-      break;
-    case 53:
-      EXPECT_THAT(
-          result_.report_urls,
-          testing::ElementsAre(GURL("https://seller-reporting.example.com/"
-                                    "?highestScoringOtherBid=1.99"),
-                               GURL("https://buyer-reporting.example.com/"
-                                    "?highestScoringOtherBid=1.99")));
-      break;
-    default:
-      // Not a supported test case.
-      ASSERT_TRUE(false);
-  }
+  EXPECT_THAT(result_.report_urls,
+              testing::ElementsAre(
+                  testing::AnyOf(GURL("https://seller-reporting.example.com/"
+                                      "?highestScoringOtherBid=1.9921875"),
+                                 GURL("https://seller-reporting.example.com/"
+                                      "?highestScoringOtherBid=1.984375")),
+                  testing::AnyOf(GURL("https://buyer-reporting.example.com/"
+                                      "?highestScoringOtherBid=1.9921875"),
+                                 GURL("https://buyer-reporting.example.com/"
+                                      "?highestScoringOtherBid=1.984375"))));
 }
 
-INSTANTIATE_TEST_SUITE_P(
-    /* no label */,
-    BidRoundingTest,
-    ::testing::Values(8, 16, 53));
-
-TEST_P(ScoreRoundingTest, ScoreRounded) {
+TEST_F(RoundingTest, ScoreRounded) {
   const char kBidScript[] = R"(
     function generateBid(
         interestGroup, auctionSignals, perBuyerSignals, trustedBiddingSignals,
@@ -21378,38 +21259,13 @@
   EXPECT_EQ(kBidder1Key, result_.winning_group_id);
   EXPECT_EQ(GURL("https://ad1.com/"), result_.ad_descriptor->url);
 
-  switch (GetParam()) {
-    case 8:
       EXPECT_THAT(
           result_.report_urls,
           testing::ElementsAre(testing::AnyOf(
               GURL("https://seller-reporting.example.com/?score=1.9921875"),
               GURL("https://seller-reporting.example.com/?score=1.984375"))));
-      break;
-    case 16:
-      EXPECT_THAT(result_.report_urls,
-                  testing::ElementsAre(testing::AnyOf(
-                      GURL("https://seller-reporting.example.com/"
-                           "?score=1.990020751953125"),
-                      GURL("https://seller-reporting.example.com/"
-                           "?score=1.989990234375"))));
-      break;
-    case 53:
-      EXPECT_THAT(result_.report_urls,
-                  testing::ElementsAre(GURL(
-                      "https://seller-reporting.example.com/?score=1.99")));
-      break;
-    default:
-      // Not a supported test case.
-      ASSERT_TRUE(false);
-  }
 }
 
-INSTANTIATE_TEST_SUITE_P(
-    /* no label */,
-    ScoreRoundingTest,
-    ::testing::Values(8, 16, 53));
-
 // Enable and test forDebuggingOnly.reportAdAuctionLoss() and
 // forDebuggingOnly.reportAdAuctionWin() APIs.
 // IMPORTANT: These tests do a better job of covering second-highest-scoring
diff --git a/content/browser/interest_group/interest_group_auction_reporter.cc b/content/browser/interest_group/interest_group_auction_reporter.cc
index 8a346d0..1a1397f 100644
--- a/content/browser/interest_group/interest_group_auction_reporter.cc
+++ b/content/browser/interest_group/interest_group_auction_reporter.cc
@@ -180,17 +180,6 @@
 
 }  // namespace
 
-BASE_FEATURE(kFledgeRounding,
-             "FledgeRounding",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-// For now default bid and score to full resolution.
-const base::FeatureParam<int> kFledgeBidReportingBits{
-    &kFledgeRounding, "fledge_bid_reporting_bits", 8};
-const base::FeatureParam<int> kFledgeScoreReportingBits{
-    &kFledgeRounding, "fledge_score_reporting_bits", 8};
-const base::FeatureParam<int> kFledgeAdCostReportingBits{
-    &kFledgeRounding, "fledge_ad_cost_reporting_bits", 8};
-
 InterestGroupAuctionReporter::SellerWinningBidInfo::SellerWinningBidInfo() =
     default;
 InterestGroupAuctionReporter::SellerWinningBidInfo::SellerWinningBidInfo(
@@ -408,7 +397,7 @@
 
 /* static */
 double InterestGroupAuctionReporter::RoundBidStochastically(double bid) {
-  return RoundStochasticallyToKBits(bid, kFledgeBidReportingBits.Get());
+  return RoundStochasticallyToKBits(bid, kFledgeBidReportingBits);
 }
 
 /* static */
@@ -627,10 +616,9 @@
       /*browser_signal_selected_buyer_and_seller_reporting_id=*/
       browser_signal_selected_buyer_and_seller_reporting_id,
       winning_bid_info_.render_url, seller_info->rounded_bid, bid_currency,
-      RoundStochasticallyToKBits(seller_info->score,
-                                 kFledgeScoreReportingBits.Get()),
+      RoundStochasticallyToKBits(seller_info->score, kFledgeScoreReportingBits),
       RoundStochasticallyToKBits(highest_scoring_other_bid,
-                                 kFledgeBidReportingBits.Get()),
+                                 kFledgeBidReportingBits),
       highest_scoring_other_bid_currency,
       std::move(browser_signals_component_auction_report_result_params),
       seller_info->scoring_signals_data_version, seller_info->trace_id,
@@ -869,7 +857,7 @@
   std::optional<double> rounded_ad_cost;
   if (winning_bid_info_.ad_cost.has_value()) {
     rounded_ad_cost = RoundStochasticallyToKBits(
-        winning_bid_info_.ad_cost.value(), kFledgeAdCostReportingBits.Get());
+        winning_bid_info_.ad_cost.value(), kFledgeAdCostReportingBits);
   }
   std::optional<uint16_t> noised_and_masked_modeling_signals;
   if (winning_bid_info_.modeling_signals) {
@@ -919,7 +907,7 @@
       winning_bid_info_.bid_currency,
       /*browser_signal_highest_scoring_other_bid=*/
       RoundStochasticallyToKBits(highest_scoring_other_bid,
-                                 kFledgeBidReportingBits.Get()),
+                                 kFledgeBidReportingBits),
       highest_scoring_other_bid_currency, made_highest_scoring_other_bid,
       rounded_ad_cost, noised_and_masked_modeling_signals,
       NoiseAndBucketJoinCount(
diff --git a/content/browser/interest_group/interest_group_auction_reporter.h b/content/browser/interest_group/interest_group_auction_reporter.h
index 6a9d48bb..0d57151 100644
--- a/content/browser/interest_group/interest_group_auction_reporter.h
+++ b/content/browser/interest_group/interest_group_auction_reporter.h
@@ -54,14 +54,6 @@
 class InterestGroupManagerImpl;
 class PrivateAggregationManager;
 
-// Configures rounding on reported results from FLEDGE. This feature is intended
-// to be always enabled, but available to attach FeatureParams to so that we can
-// adjust the rounding setting via Finch.
-CONTENT_EXPORT BASE_DECLARE_FEATURE(kFledgeRounding);
-CONTENT_EXPORT extern const base::FeatureParam<int> kFledgeBidReportingBits;
-CONTENT_EXPORT extern const base::FeatureParam<int> kFledgeScoreReportingBits;
-CONTENT_EXPORT extern const base::FeatureParam<int> kFledgeAdCostReportingBits;
-
 // Handles the reporting phase of FLEDGE auctions with a winner. Loads the
 // bidder, seller, and (if present) component seller worklets and invokes
 // reporting-related methods, and invokes reportResult() and reportWin() on
@@ -348,6 +340,11 @@
       unsigned k);
 
  private:
+  // Configures rounding on reported results from FLEDGE.
+  static constexpr int kFledgeBidReportingBits = 8;
+  static constexpr int kFledgeScoreReportingBits = 8;
+  static constexpr int kFledgeAdCostReportingBits = 8;
+
   // Starts request for a seller worklet. Invokes OnSellerWorkletReceived() on
   // success, OnSellerWorkletFatalError() on error.
   void RequestSellerWorklet(
diff --git a/content/browser/tracing/trace_report/trace_report_database.cc b/content/browser/tracing/trace_report/trace_report_database.cc
index 0c944d90..07d0a579 100644
--- a/content/browser/tracing/trace_report/trace_report_database.cc
+++ b/content/browser/tracing/trace_report/trace_report_database.cc
@@ -385,7 +385,8 @@
 
   sql::Statement delete_reports_older_than(
       database_.GetCachedStatement(SQL_FROM_HERE, R"sql(
-        DELETE FROM local_traces
+        UPDATE local_traces
+        SET trace_content = null
         WHERE state=? AND upload_time < ?)sql"));
 
   delete_reports_older_than.BindInt(
diff --git a/content/browser/tracing/trace_report/trace_report_database_unittest.cc b/content/browser/tracing/trace_report/trace_report_database_unittest.cc
index 4a6e942..bd5bd99 100644
--- a/content/browser/tracing/trace_report/trace_report_database_unittest.cc
+++ b/content/browser/tracing/trace_report/trace_report_database_unittest.cc
@@ -207,6 +207,7 @@
   for (int i = 0; i < 3; i++) {
     NewTraceReport new_report = MakeNewTraceReport(today - base::Days(20));
     ASSERT_TRUE(trace_report_.AddTrace(new_report));
+    trace_report_.UploadComplete(new_report.uuid, today);
   }
   for (int i = 0; i < 3; i++) {
     NewTraceReport new_report = MakeNewTraceReport(today - base::Days(20));
@@ -217,7 +218,12 @@
   EXPECT_EQ(trace_report_.GetAllReports().size(), 6u);
 
   ASSERT_TRUE(trace_report_.DeleteUploadedTraceContentOlderThan(base::Days(5)));
-  EXPECT_EQ(trace_report_.GetAllReports().size(), 3u);
+  auto received_reports = trace_report_.GetAllReports();
+  EXPECT_EQ(received_reports.size(), 6u);
+  for (const auto& report : received_reports) {
+    EXPECT_EQ(report.has_trace_content,
+              report.upload_time >= (today - base::Days(5)));
+  }
 }
 
 TEST_F(TraceReportDatabaseTest, DeleteOldTraceContent) {
diff --git a/content/browser/webauth/authenticator_common_impl.cc b/content/browser/webauth/authenticator_common_impl.cc
index 9e04b8d..9475f8b 100644
--- a/content/browser/webauth/authenticator_common_impl.cc
+++ b/content/browser/webauth/authenticator_common_impl.cc
@@ -2484,7 +2484,7 @@
   common_info->client_data_json.assign(req_state_->client_data_json.begin(),
                                        req_state_->client_data_json.end());
   common_info->raw_id = response_data.attestation_object.GetCredentialId();
-  common_info->id = Base64UrlEncodeChallenge(common_info->raw_id);
+  common_info->id = Base64UrlEncodeOmitPadding(common_info->raw_id);
 
   response->authenticator_attachment =
       response_data.transport_used
@@ -2685,7 +2685,7 @@
   common_info->client_data_json.assign(req_state_->client_data_json.begin(),
                                        req_state_->client_data_json.end());
   common_info->raw_id = response_data.credential->id;
-  common_info->id = Base64UrlEncodeChallenge(common_info->raw_id);
+  common_info->id = Base64UrlEncodeOmitPadding(common_info->raw_id);
   response->info = std::move(common_info);
   response->info->authenticator_data =
       response_data.authenticator_data.SerializeToByteArray();
diff --git a/content/browser/webauth/client_data_json.cc b/content/browser/webauth/client_data_json.cc
index 1be92f9..c1b7aff 100644
--- a/content/browser/webauth/client_data_json.cc
+++ b/content/browser/webauth/client_data_json.cc
@@ -91,7 +91,7 @@
   }
 
   ret.append(R"(,"challenge":)");
-  ret.append(ToJSONString(Base64UrlEncodeChallenge(params.challenge)));
+  ret.append(ToJSONString(Base64UrlEncodeOmitPadding(params.challenge)));
 
   ret.append(R"(,"origin":)");
   ret.append(ToJSONString(params.origin.Serialize()));
@@ -141,7 +141,13 @@
     ret.append(R"(,"displayName":)");
     ret.append(ToJSONString(params.payment_options->instrument->display_name));
 
-    ret.append("}}");
+    ret.append("}");
+    if (params.payment_options->browser_bound_public_key.has_value()) {
+      ret.append(R"(,"browserBoundPublicKey":)");
+      ret.append(ToJSONString(Base64UrlEncodeOmitPadding(
+          *params.payment_options->browser_bound_public_key)));
+    }
+    ret.append("}");
   }
 
   if (base::RandDouble() < 0.2) {
diff --git a/content/browser/webauth/common_utils.cc b/content/browser/webauth/common_utils.cc
index a8de7211..88de216 100644
--- a/content/browser/webauth/common_utils.cc
+++ b/content/browser/webauth/common_utils.cc
@@ -11,7 +11,7 @@
 
 namespace content {
 
-std::string Base64UrlEncodeChallenge(
+std::string Base64UrlEncodeOmitPadding(
     const base::span<const uint8_t> challenge) {
   std::string ret;
   base::Base64UrlEncode(challenge, base::Base64UrlEncodePolicy::OMIT_PADDING,
diff --git a/content/browser/webauth/common_utils.h b/content/browser/webauth/common_utils.h
index 3ecc3e2..bff5e7e 100644
--- a/content/browser/webauth/common_utils.h
+++ b/content/browser/webauth/common_utils.h
@@ -11,7 +11,8 @@
 
 namespace content {
 
-std::string Base64UrlEncodeChallenge(const base::span<const uint8_t> challenge);
+std::string Base64UrlEncodeOmitPadding(
+    const base::span<const uint8_t> challenge);
 
 }  // namespace content
 
diff --git a/content/public/android/javatests/src/org/chromium/content_public/browser/ClientDataJsonTest.java b/content/public/android/javatests/src/org/chromium/content_public/browser/ClientDataJsonTest.java
index 6cf1323..caef7793 100644
--- a/content/public/android/javatests/src/org/chromium/content_public/browser/ClientDataJsonTest.java
+++ b/content/public/android/javatests/src/org/chromium/content_public/browser/ClientDataJsonTest.java
@@ -48,6 +48,7 @@
         payment.payeeOrigin.scheme = "https";
         payment.payeeOrigin.host = "test.example";
         payment.payeeOrigin.port = 443;
+        payment.browserBoundPublicKey = new byte[] {0x01, 0x02, 0x03, 0x04};
 
         byte[] challenge = new byte[3];
         String relyingPartyId = "subdomain.example.test";
@@ -83,5 +84,6 @@
                 output,
                 containsString(
                         String.format("\"displayName\":\"%s\"", payment.instrument.displayName)));
+        assertThat(output, containsString(String.format("\"browserBoundPublicKey\":\"AQIDBA\"")));
     }
 }
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index ff59226..236d6c4 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -1827,10 +1827,16 @@
 
   static base::NoDestructor<language_detection::LanguageDetectionModelProvider>
       provider(background_task_runner);
-  provider->ReplaceModelFile(
-      base::FilePath(base::FilePath::kCurrentDirectory)
-          .AppendASCII(kLanguageDetectionLocalFileModelPath.Get())
-          .NormalizePathSeparators());
+  const std::string model_file_path =
+      kLanguageDetectionLocalFileModelPath.Get();
+  if (model_file_path.length()) {
+    provider->ReplaceModelFile(base::FilePath::FromASCII(model_file_path));
+  } else {
+    // There is no model and there's not going to be one. If we don't call this
+    // the provider will queue requests, expecting that some time in the future
+    // a model will become available.
+    provider->UnloadModelFile();
+  }
 
   static base::NoDestructor<language_detection::ContentLanguageDetectionDriver>
       driver(provider.get());
diff --git a/extensions/browser/api/feedback_private/feedback_service.cc b/extensions/browser/api/feedback_private/feedback_service.cc
index 484b52c9..d7a51a7 100644
--- a/extensions/browser/api/feedback_private/feedback_service.cc
+++ b/extensions/browser/api/feedback_private/feedback_service.cc
@@ -27,6 +27,7 @@
 #include "components/feedback/redaction_tool/redaction_tool.h"
 #include "components/feedback/system_logs/system_logs_fetcher.h"
 #include "components/feedback/system_logs/system_logs_source.h"
+#include "components/variations/net/variations_command_line.h"
 #include "content/public/browser/browser_context.h"
 #include "extensions/browser/api/extensions_api_client.h"
 #include "extensions/browser/api/feedback_private/feedback_private_delegate.h"
@@ -40,7 +41,6 @@
 #include "chromeos/ash/services/assistant/public/cpp/assistant_service.h"
 #include "components/account_id/account_id.h"
 #include "components/user_manager/user_manager.h"
-#include "components/variations/net/variations_command_line.h"
 #include "content/public/browser/storage_partition.h"
 #include "extensions/browser/api/feedback_private/proto/hpke.pb.h"
 #include "net/http/http_status_code.h"
@@ -53,6 +53,11 @@
 #include "third_party/cros_system_api/dbus/debugd/dbus-constants.h"
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
+#if !BUILDFLAG(IS_CHROMEOS)
+#include "base/base64.h"
+#include "base/feature_list.h"
+#endif
+
 namespace extensions {
 
 using system_logs::SysLogsFetcherCallback;
@@ -61,6 +66,10 @@
 
 namespace {
 
+#if !BUILDFLAG(IS_CHROMEOS)
+constexpr char kVariationsStateAttachmentName[] = "variations_state.bin";
+#endif
+
 #if BUILDFLAG(IS_CHROMEOS)
 // The paths are relative to "/var/log/" by default, which can be overwritten
 // for testing purpose.
@@ -118,6 +127,22 @@
 }
 #endif
 
+#if !BUILDFLAG(IS_CHROMEOS)
+void IncludeVariations(scoped_refptr<feedback::FeedbackData> feedback_data) {
+  std::vector<uint8_t> ciphertext;
+  auto status =
+      variations::VariationsCommandLine::GetForCurrentProcess().EncryptToString(
+          &ciphertext);
+  base::UmaHistogramEnumeration("Variations.VariationsStateEncryptionStatus",
+                                status);
+  // Variations is at best effort.
+  if (status == variations::VariationsStateEncryptionStatus::kSuccess) {
+    feedback_data->AddFile(kVariationsStateAttachmentName,
+                           std::string(ciphertext.begin(), ciphertext.end()));
+  }
+}
+#endif
+
 void RedactFeedbackData(scoped_refptr<feedback::FeedbackData> feedback_data) {
   redaction::RedactionTool redactor(nullptr);
   redactor.EnableCreditCardRedaction(true);
@@ -272,6 +297,12 @@
         feedback_data->AddLog(std::move(itr.first), std::move(itr.second));
     }
   }
+#if !BUILDFLAG(IS_CHROMEOS)
+  if (base::FeatureList::IsEnabled(variations::kFeedbackIncludeVariations)) {
+    IncludeVariations(feedback_data);
+  }
+#endif
+
 #if BUILDFLAG(IS_CHROMEOS)
   FetchExtraLogs(params, feedback_data);
 #else
diff --git a/gpu/command_buffer/common/discardable_handle.h b/gpu/command_buffer/common/discardable_handle.h
index 41ed094..f3ad4ea4 100644
--- a/gpu/command_buffer/common/discardable_handle.h
+++ b/gpu/command_buffer/common/discardable_handle.h
@@ -5,6 +5,7 @@
 #ifndef GPU_COMMAND_BUFFER_COMMON_DISCARDABLE_HANDLE_H_
 #define GPU_COMMAND_BUFFER_COMMON_DISCARDABLE_HANDLE_H_
 
+#include "base/atomicops.h"
 #include "base/memory/ref_counted.h"
 #include "base/types/id_type.h"
 #include "gpu/gpu_export.h"
diff --git a/gpu/command_buffer/service/dawn_context_provider.cc b/gpu/command_buffer/service/dawn_context_provider.cc
index 7ae8969..a6afb17b 100644
--- a/gpu/command_buffer/service/dawn_context_provider.cc
+++ b/gpu/command_buffer/service/dawn_context_provider.cc
@@ -109,11 +109,10 @@
   enabled_toggles.push_back("use_user_defined_labels_in_backend");
 #endif
 
-#if !DCHECK_IS_ON()
   if (features::kSkiaGraphiteDawnSkipValidation.Get()) {
     enabled_toggles.push_back("skip_validation");
   }
-#endif
+
   enabled_toggles.push_back("disable_robustness");
   enabled_toggles.push_back("disable_lazy_clear_for_mapped_at_creation_buffer");
 
diff --git a/gpu/config/gpu_finch_features.cc b/gpu/config/gpu_finch_features.cc
index f238a28..688407d5 100644
--- a/gpu/config/gpu_finch_features.cc
+++ b/gpu/config/gpu_finch_features.cc
@@ -377,7 +377,7 @@
 
 // Whether the Dawn "skip_validation" toggle is enabled for Skia Graphite.
 const base::FeatureParam<bool> kSkiaGraphiteDawnSkipValidation{
-    &kSkiaGraphite, "dawn_skip_validation", true};
+    &kSkiaGraphite, "dawn_skip_validation", !DCHECK_IS_ON()};
 
 // Whether Dawn backend validation is enabled for Skia Graphite.
 const base::FeatureParam<bool> kSkiaGraphiteDawnBackendValidation{
diff --git a/gpu/ipc/client/DEPS b/gpu/ipc/client/DEPS
index 4bb85ef..549adf03 100644
--- a/gpu/ipc/client/DEPS
+++ b/gpu/ipc/client/DEPS
@@ -9,6 +9,7 @@
 specific_include_rules = {
   "gpu_in_process_context_tests.cc": [
     "+components/viz/test/test_gpu_memory_buffer_manager.h",
+    "+components/viz/test/test_gpu_service_holder.h",
   ],
   "image_decode_accelerator_proxy(_unittest)?\.cc": [
     "+cc/paint/paint_image.h",
diff --git a/gpu/ipc/client/gpu_in_process_context_tests.cc b/gpu/ipc/client/gpu_in_process_context_tests.cc
index c57bd22..7b2a8cc 100644
--- a/gpu/ipc/client/gpu_in_process_context_tests.cc
+++ b/gpu/ipc/client/gpu_in_process_context_tests.cc
@@ -16,9 +16,15 @@
 #include "gpu/command_buffer/client/test_gpu_memory_buffer_manager.h"
 #include "gpu/ipc/common/surface_handle.h"
 #include "gpu/ipc/gl_in_process_context.h"
-#include "gpu/ipc/in_process_gpu_thread_holder.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+// TODO(crbug.com/351775836): Move ChromeOS to use TestGpuServiceHolder.
+#if BUILDFLAG(IS_CHROMEOS)
+#include "gpu/ipc/in_process_gpu_thread_holder.h"
+#else
+#include "components/viz/test/test_gpu_service_holder.h"
+#endif
+
 namespace {
 
 class ContextTestBase : public testing::Test {
@@ -28,7 +34,12 @@
     attributes.bind_generates_resource = false;
 
     auto context = std::make_unique<gpu::GLInProcessContext>();
+    // TODO(crbug.com/351775836): Move ChromeOS to use TestGpuServiceHolder.
+#if BUILDFLAG(IS_CHROMEOS)
     auto result = context->Initialize(gpu_thread_holder_.GetTaskExecutor(),
+#else
+    auto result = context->Initialize(gpu_thread_holder_.task_executor(),
+#endif
                                       attributes, gpu::SharedMemoryLimits());
     DCHECK_EQ(result, gpu::ContextResult::kSuccess);
     return context;
@@ -51,7 +62,12 @@
   raw_ptr<gpu::ContextSupport> context_support_;
 
  private:
+  // TODO(crbug.com/351775836): Move ChromeOS to use TestGpuServiceHolder.
+#if BUILDFLAG(IS_CHROMEOS)
   gpu::InProcessGpuThreadHolder gpu_thread_holder_;
+#else
+  viz::TestGpuServiceHolder gpu_thread_holder_;
+#endif
   std::unique_ptr<gpu::GLInProcessContext> context_;
 };
 
diff --git a/infra/config/generated/builders/ci/Linux ASan LSan Builder/targets/chromium.memory.json b/infra/config/generated/builders/ci/Linux ASan LSan Builder/targets/chromium.memory.json
index 5e8213e..6438104 100644
--- a/infra/config/generated/builders/ci/Linux ASan LSan Builder/targets/chromium.memory.json
+++ b/infra/config/generated/builders/ci/Linux ASan LSan Builder/targets/chromium.memory.json
@@ -1264,7 +1264,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 6
+          "shards": 7
         },
         "test": "sync_integration_tests",
         "test_id_prefix": "ninja://chrome/test:sync_integration_tests/"
diff --git "a/infra/config/generated/builders/ci/Linux ASan LSan Tests \0501\051/targets/chromium.memory.json" "b/infra/config/generated/builders/ci/Linux ASan LSan Tests \0501\051/targets/chromium.memory.json"
index 5e8213e..6438104 100644
--- "a/infra/config/generated/builders/ci/Linux ASan LSan Tests \0501\051/targets/chromium.memory.json"
+++ "b/infra/config/generated/builders/ci/Linux ASan LSan Tests \0501\051/targets/chromium.memory.json"
@@ -1264,7 +1264,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 6
+          "shards": 7
         },
         "test": "sync_integration_tests",
         "test_id_prefix": "ninja://chrome/test:sync_integration_tests/"
diff --git a/infra/config/generated/builders/ci/Linux Builder/targets/chromium.linux.json b/infra/config/generated/builders/ci/Linux Builder/targets/chromium.linux.json
index 7eb7a7c..8c7dc58 100644
--- a/infra/config/generated/builders/ci/Linux Builder/targets/chromium.linux.json
+++ b/infra/config/generated/builders/ci/Linux Builder/targets/chromium.linux.json
@@ -721,7 +721,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 7
+          "shards": 8
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
@@ -1422,7 +1422,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 13
+          "shards": 4
         },
         "test": "blink_wpt_tests",
         "test_id_prefix": "ninja://:blink_wpt_tests/"
@@ -1943,7 +1943,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 11
+          "shards": 14
         },
         "test": "headless_shell_wpt",
         "test_id_prefix": "ninja://:headless_shell_wpt/"
diff --git a/infra/config/generated/builders/ci/Linux Tests/targets/chromium.linux.json b/infra/config/generated/builders/ci/Linux Tests/targets/chromium.linux.json
index 67da5a0..c2ed78bd 100644
--- a/infra/config/generated/builders/ci/Linux Tests/targets/chromium.linux.json
+++ b/infra/config/generated/builders/ci/Linux Tests/targets/chromium.linux.json
@@ -690,7 +690,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 7
+          "shards": 8
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
@@ -1391,7 +1391,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 13
+          "shards": 4
         },
         "test": "blink_wpt_tests",
         "test_id_prefix": "ninja://:blink_wpt_tests/"
@@ -1912,7 +1912,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 11
+          "shards": 14
         },
         "test": "headless_shell_wpt",
         "test_id_prefix": "ninja://:headless_shell_wpt/"
diff --git a/infra/config/generated/builders/ci/android-oreo-x86-rel/targets/chromium.android.json b/infra/config/generated/builders/ci/android-oreo-x86-rel/targets/chromium.android.json
index 58837a0..1feaa63 100644
--- a/infra/config/generated/builders/ci/android-oreo-x86-rel/targets/chromium.android.json
+++ b/infra/config/generated/builders/ci/android-oreo-x86-rel/targets/chromium.android.json
@@ -1019,7 +1019,7 @@
             }
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 90
+          "shards": 70
         },
         "test": "content_browsertests",
         "test_id_prefix": "ninja://content/test:content_browsertests/"
diff --git a/infra/config/generated/builders/ci/linux-chromeos-rel/targets/chromium.chromiumos.json b/infra/config/generated/builders/ci/linux-chromeos-rel/targets/chromium.chromiumos.json
index ec5ecdd..db404f8 100644
--- a/infra/config/generated/builders/ci/linux-chromeos-rel/targets/chromium.chromiumos.json
+++ b/infra/config/generated/builders/ci/linux-chromeos-rel/targets/chromium.chromiumos.json
@@ -295,7 +295,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 96
+          "shards": 104
         },
         "test": "browser_tests",
         "test_id_prefix": "ninja://chrome/test:browser_tests/"
diff --git a/infra/config/generated/builders/try/android-oreo-x86-rel/targets/chromium.android.json b/infra/config/generated/builders/try/android-oreo-x86-rel/targets/chromium.android.json
index 58837a0..1feaa63 100644
--- a/infra/config/generated/builders/try/android-oreo-x86-rel/targets/chromium.android.json
+++ b/infra/config/generated/builders/try/android-oreo-x86-rel/targets/chromium.android.json
@@ -1019,7 +1019,7 @@
             }
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 90
+          "shards": 70
         },
         "test": "content_browsertests",
         "test_id_prefix": "ninja://content/test:content_browsertests/"
diff --git a/infra/config/generated/builders/try/android-x86-rel/targets/chromium.android.json b/infra/config/generated/builders/try/android-x86-rel/targets/chromium.android.json
index 58837a0..1feaa63 100644
--- a/infra/config/generated/builders/try/android-x86-rel/targets/chromium.android.json
+++ b/infra/config/generated/builders/try/android-x86-rel/targets/chromium.android.json
@@ -1019,7 +1019,7 @@
             }
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 90
+          "shards": 70
         },
         "test": "content_browsertests",
         "test_id_prefix": "ninja://content/test:content_browsertests/"
diff --git a/infra/config/generated/builders/try/linux-chromeos-rel/targets/chromium.chromiumos.json b/infra/config/generated/builders/try/linux-chromeos-rel/targets/chromium.chromiumos.json
index ec5ecdd..db404f8 100644
--- a/infra/config/generated/builders/try/linux-chromeos-rel/targets/chromium.chromiumos.json
+++ b/infra/config/generated/builders/try/linux-chromeos-rel/targets/chromium.chromiumos.json
@@ -295,7 +295,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 96
+          "shards": 104
         },
         "test": "browser_tests",
         "test_id_prefix": "ninja://chrome/test:browser_tests/"
diff --git a/infra/config/generated/builders/try/linux-dcheck-off-rel/targets/chromium.linux.json b/infra/config/generated/builders/try/linux-dcheck-off-rel/targets/chromium.linux.json
index 7eb7a7c..8c7dc58 100644
--- a/infra/config/generated/builders/try/linux-dcheck-off-rel/targets/chromium.linux.json
+++ b/infra/config/generated/builders/try/linux-dcheck-off-rel/targets/chromium.linux.json
@@ -721,7 +721,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 7
+          "shards": 8
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
@@ -1422,7 +1422,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 13
+          "shards": 4
         },
         "test": "blink_wpt_tests",
         "test_id_prefix": "ninja://:blink_wpt_tests/"
@@ -1943,7 +1943,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 11
+          "shards": 14
         },
         "test": "headless_shell_wpt",
         "test_id_prefix": "ninja://:headless_shell_wpt/"
diff --git a/infra/config/generated/builders/try/linux-full-remote-rel/targets/chromium.linux.json b/infra/config/generated/builders/try/linux-full-remote-rel/targets/chromium.linux.json
index 7eb7a7c..8c7dc58 100644
--- a/infra/config/generated/builders/try/linux-full-remote-rel/targets/chromium.linux.json
+++ b/infra/config/generated/builders/try/linux-full-remote-rel/targets/chromium.linux.json
@@ -721,7 +721,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 7
+          "shards": 8
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
@@ -1422,7 +1422,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 13
+          "shards": 4
         },
         "test": "blink_wpt_tests",
         "test_id_prefix": "ninja://:blink_wpt_tests/"
@@ -1943,7 +1943,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 11
+          "shards": 14
         },
         "test": "headless_shell_wpt",
         "test_id_prefix": "ninja://:headless_shell_wpt/"
diff --git a/infra/config/generated/builders/try/linux-rel/targets/chromium.linux.json b/infra/config/generated/builders/try/linux-rel/targets/chromium.linux.json
index 7eb7a7c..8c7dc58 100644
--- a/infra/config/generated/builders/try/linux-rel/targets/chromium.linux.json
+++ b/infra/config/generated/builders/try/linux-rel/targets/chromium.linux.json
@@ -721,7 +721,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 7
+          "shards": 8
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
@@ -1422,7 +1422,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 13
+          "shards": 4
         },
         "test": "blink_wpt_tests",
         "test_id_prefix": "ninja://:blink_wpt_tests/"
@@ -1943,7 +1943,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 11
+          "shards": 14
         },
         "test": "headless_shell_wpt",
         "test_id_prefix": "ninja://:headless_shell_wpt/"
diff --git a/infra/config/generated/builders/try/linux_chromium_asan_rel_ng/targets/chromium.memory.json b/infra/config/generated/builders/try/linux_chromium_asan_rel_ng/targets/chromium.memory.json
index 5e8213e..6438104 100644
--- a/infra/config/generated/builders/try/linux_chromium_asan_rel_ng/targets/chromium.memory.json
+++ b/infra/config/generated/builders/try/linux_chromium_asan_rel_ng/targets/chromium.memory.json
@@ -1264,7 +1264,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 6
+          "shards": 7
         },
         "test": "sync_integration_tests",
         "test_id_prefix": "ninja://chrome/test:sync_integration_tests/"
diff --git a/infra/config/generated/builders/try/linux_chromium_compile_rel_ng/targets/chromium.linux.json b/infra/config/generated/builders/try/linux_chromium_compile_rel_ng/targets/chromium.linux.json
index 7eb7a7c..8c7dc58 100644
--- a/infra/config/generated/builders/try/linux_chromium_compile_rel_ng/targets/chromium.linux.json
+++ b/infra/config/generated/builders/try/linux_chromium_compile_rel_ng/targets/chromium.linux.json
@@ -721,7 +721,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 7
+          "shards": 8
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
@@ -1422,7 +1422,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 13
+          "shards": 4
         },
         "test": "blink_wpt_tests",
         "test_id_prefix": "ninja://:blink_wpt_tests/"
@@ -1943,7 +1943,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 11
+          "shards": 14
         },
         "test": "headless_shell_wpt",
         "test_id_prefix": "ninja://:headless_shell_wpt/"
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index d8ffa0c..1f168cb 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -86985,7 +86985,7 @@
       dimensions: "builderless:1"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.android.pixel6.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -87088,6 +87088,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "android-dawn-arm64-rel"
@@ -87204,7 +87205,7 @@
       dimensions: "builderless:1"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.android.s23.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -87307,6 +87308,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "android-desktop-14-x64-rel"
@@ -94447,7 +94449,7 @@
       dimensions: "builderless:1"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.chromeos.volteer.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -94550,6 +94552,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "dawn-try-linux-tsan-rel"
@@ -94557,7 +94560,7 @@
       dimensions: "builderless:1"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.linux.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -94660,6 +94663,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "dawn-try-linux-x64-intel-uhd770-rel"
@@ -94667,7 +94671,7 @@
       dimensions: "builderless:1"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.linux.intel.uhd770.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -94770,6 +94774,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "dawn-try-mac-amd-exp"
@@ -95319,7 +95324,7 @@
       dimensions: "builderless:1"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.intel.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -95422,6 +95427,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "dawn-try-win-x64-intel-uhd770-rel"
@@ -95429,7 +95435,7 @@
       dimensions: "builderless:1"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.intel.uhd770.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -95532,6 +95538,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "dawn-try-win-x64-nvidia-exp"
@@ -95539,7 +95546,7 @@
       dimensions: "builderless:1"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -95642,6 +95649,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "dawn-try-win-x86-intel-exp"
@@ -95649,7 +95657,7 @@
       dimensions: "builderless:1"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.intel.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -95752,6 +95760,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "dawn-try-win-x86-nvidia-exp"
@@ -95759,7 +95768,7 @@
       dimensions: "builderless:1"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -95862,6 +95871,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "dawn-try-win10-x64-intel-asan"
@@ -95869,7 +95879,7 @@
       dimensions: "builderless:1"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.intel.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -95972,6 +95982,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "dawn-try-win10-x64-nvidia-asan"
@@ -95979,7 +95990,7 @@
       dimensions: "builderless:1"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -96082,6 +96093,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "dawn-try-win10-x86-rel"
@@ -98360,7 +98372,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.android.nexus5x.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -98459,6 +98471,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-android-nvidia-shield-tv"
@@ -98467,7 +98480,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.android.nvidia.shield.tv.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -98566,6 +98579,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-android-p-pixel-2-32"
@@ -98574,7 +98588,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.android.pixel2.chromium.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -98673,6 +98687,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-android-pixel-6-64"
@@ -98681,7 +98696,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.android.pixel6.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -98780,6 +98795,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-android-pixel-6-64-exp"
@@ -98788,7 +98804,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.android.pixel6.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -98887,6 +98903,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-android-r-pixel-4-32"
@@ -98895,7 +98912,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.android.pixel4.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -98994,6 +99011,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-android-s23-64"
@@ -99002,7 +99020,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.android.s23.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -99101,6 +99119,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-chromeos-amd64-generic"
@@ -99109,7 +99128,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.chromeos.amd64.generic.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -99208,6 +99227,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-chromeos-skylab-volteer"
@@ -99216,7 +99236,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.chromeos.volteer.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -99315,6 +99335,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-linux-amd-rel"
@@ -99323,7 +99344,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.linux.amd.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -99422,6 +99443,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-linux-intel-exp"
@@ -99430,7 +99452,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.linux.intel.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -99529,6 +99551,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-linux-intel-rel"
@@ -99537,7 +99560,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.linux.intel.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -99636,6 +99659,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-linux-intel-uhd770-rel"
@@ -99644,7 +99668,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.linux.intel.uhd770.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -99743,6 +99767,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-linux-nvidia-dbg"
@@ -99751,7 +99776,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.linux.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -99850,6 +99875,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-linux-nvidia-exp"
@@ -99858,7 +99884,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.linux.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -99957,6 +99983,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-linux-nvidia-rel"
@@ -99965,7 +99992,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.linux.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -100064,6 +100091,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-linux-nvidia-tsn"
@@ -100072,7 +100100,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.linux.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -100171,6 +100199,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-linux-wayland-amd-rel"
@@ -100179,7 +100208,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.linux.amd.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -100278,6 +100307,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-linux-wayland-intel-rel"
@@ -100286,7 +100316,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.linux.intel.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -100385,6 +100415,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-mac-amd-pro-rel"
@@ -101972,7 +102003,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.amd.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -102071,6 +102102,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-win10-intel-exp-64"
@@ -102079,7 +102111,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.intel.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -102178,6 +102210,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-win10-intel-rel-64"
@@ -102186,7 +102219,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.intel.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -102285,6 +102318,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-win10-intel-uhd770-rel"
@@ -102293,7 +102327,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.intel.uhd770.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -102392,6 +102426,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-win10-nvidia-4070-rel-64"
@@ -102400,7 +102435,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -102499,6 +102534,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-win10-nvidia-dbg-64"
@@ -102507,7 +102543,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -102606,6 +102642,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-win10-nvidia-dx12vk-dbg-64"
@@ -102614,7 +102651,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -102713,6 +102750,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-win10-nvidia-dx12vk-rel-64"
@@ -102721,7 +102759,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -102820,6 +102858,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-win10-nvidia-exp-64"
@@ -102828,7 +102867,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -102927,6 +102966,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-win10-nvidia-rel-32"
@@ -102935,7 +102975,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -103034,6 +103074,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-win10-nvidia-rel-64"
@@ -103042,7 +103083,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -103141,6 +103182,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-fyi-try-win11-qualcomm-rel-64"
@@ -103149,7 +103191,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win11.qualcomm.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -103248,6 +103290,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-try-android-m-nexus-5x-64"
@@ -103256,7 +103299,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.android.nexus5x.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -103355,6 +103398,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-try-android-pixel-2-64"
@@ -103363,7 +103407,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.android.pixel2.chromium.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -103462,6 +103506,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-try-linux-nvidia-dbg"
@@ -103470,7 +103515,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.linux.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -103569,6 +103614,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-try-linux-nvidia-rel"
@@ -103577,7 +103623,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.linux.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -103676,6 +103722,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "gpu-try-mac-amd-retina-dbg"
@@ -103894,7 +103941,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.gpu.win10.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -103993,6 +104040,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "ios-angle-try-intel"
@@ -109996,7 +110044,7 @@
       dimensions: "builderless:1"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.linux.intel.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -110099,6 +110147,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "linux-dawn-nvidia-1660-exp-rel"
@@ -110106,7 +110155,7 @@
       dimensions: "builderless:1"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-22.04"
-      dimensions: "pool:luci.chromium.gpu.linux.nvidia.try"
+      dimensions: "pool:luci.chromium.gpu.try"
       dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -110209,6 +110258,7 @@
         predicates: "has(build.output.properties.is_cached)"
         predicates: "string(build.output.properties.is_cached) == \"false\""
       }
+      max_concurrent_builds: 1
     }
     builders {
       name: "linux-dawn-rel"
diff --git a/infra/config/subprojects/chromium/gpu.try.star b/infra/config/subprojects/chromium/gpu.try.star
index 62744e6..5b20687 100644
--- a/infra/config/subprojects/chromium/gpu.try.star
+++ b/infra/config/subprojects/chromium/gpu.try.star
@@ -42,8 +42,11 @@
 def gpu_android_builder(*, name, **kwargs):
     return try_.builder(
         name = name,
+        pool = "luci.chromium.gpu.try",
         builder_group = "tryserver.chromium.android",
         builderless = True,
+        max_concurrent_builds = 1,
+        os = os.LINUX_DEFAULT,
         siso_remote_jobs = siso.remote_jobs.LOW_JOBS_FOR_CQ,
         ssd = None,
         **kwargs
@@ -56,7 +59,6 @@
         "ci/Android FYI Release (Nexus 5X)",
     ],
     gn_args = "ci/GPU FYI Android arm64 Builder",
-    pool = "luci.chromium.gpu.android.nexus5x.try",
 )
 
 gpu_android_builder(
@@ -66,7 +68,6 @@
         "ci/Android FYI Release (NVIDIA Shield TV)",
     ],
     gn_args = "ci/GPU FYI Android arm Builder",
-    pool = "luci.chromium.gpu.android.nvidia.shield.tv.try",
 )
 
 gpu_android_builder(
@@ -76,7 +77,6 @@
         "ci/Android FYI Release (Pixel 2)",
     ],
     gn_args = "ci/GPU FYI Android arm Builder",
-    pool = "luci.chromium.gpu.android.pixel2.chromium.try",
 )
 
 gpu_android_builder(
@@ -86,7 +86,6 @@
         "ci/Android FYI Release (Pixel 4)",
     ],
     gn_args = "ci/GPU FYI Android arm Builder",
-    pool = "luci.chromium.gpu.android.pixel4.try",
 )
 
 gpu_android_builder(
@@ -96,7 +95,6 @@
         "ci/Android FYI Release (Pixel 6)",
     ],
     gn_args = "ci/GPU FYI Android arm64 Builder",
-    pool = "luci.chromium.gpu.android.pixel6.try",
 )
 
 gpu_android_builder(
@@ -107,7 +105,6 @@
         "ci/Android FYI Experimental Release (Pixel 6)",
     ],
     gn_args = "ci/GPU FYI Android arm64 Builder",
-    pool = "luci.chromium.gpu.android.pixel6.try",
 )
 
 gpu_android_builder(
@@ -118,7 +115,6 @@
         "ci/Android FYI Release (Samsung S23)",
     ],
     gn_args = "ci/GPU FYI Android arm64 Builder",
-    pool = "luci.chromium.gpu.android.s23.try",
 )
 
 gpu_android_builder(
@@ -137,7 +133,6 @@
             "static_angle",
         ],
     ),
-    pool = "luci.chromium.gpu.android.nexus5x.try",
 )
 
 gpu_android_builder(
@@ -146,14 +141,16 @@
         "ci/Android Release (Pixel 2)",
     ],
     gn_args = "ci/Android Release (Pixel 2)",
-    pool = "luci.chromium.gpu.android.pixel2.chromium.try",
 )
 
 def gpu_chromeos_builder(*, name, **kwargs):
     return try_.builder(
         name = name,
+        pool = "luci.chromium.gpu.try",
         builder_group = "tryserver.chromium.chromiumos",
         builderless = True,
+        max_concurrent_builds = 1,
+        os = os.LINUX_DEFAULT,
         siso_remote_jobs = siso.remote_jobs.LOW_JOBS_FOR_CQ,
         ssd = None,
         **kwargs
@@ -165,7 +162,6 @@
         "ci/ChromeOS FYI Release (amd64-generic)",
     ],
     gn_args = "ci/ChromeOS FYI Release (amd64-generic)",
-    pool = "luci.chromium.gpu.chromeos.amd64.generic.try",
 )
 
 gpu_chromeos_builder(
@@ -175,14 +171,16 @@
         "ci/ChromeOS FYI Release Skylab (volteer)",
     ],
     gn_args = "ci/ChromeOS FYI Release Skylab (volteer)",
-    pool = "luci.chromium.gpu.chromeos.volteer.try",
 )
 
 def gpu_linux_builder(*, name, **kwargs):
     return try_.builder(
         name = name,
+        pool = "luci.chromium.gpu.try",
         builder_group = "tryserver.chromium.linux",
         builderless = True,
+        max_concurrent_builds = 1,
+        os = os.LINUX_DEFAULT,
         siso_remote_jobs = siso.remote_jobs.LOW_JOBS_FOR_CQ,
         ssd = None,
         **kwargs
@@ -196,7 +194,6 @@
         "ci/Linux Wayland FYI Release (AMD)",
     ],
     gn_args = "ci/GPU FYI Linux Wayland Builder",
-    pool = "luci.chromium.gpu.linux.amd.try",
 )
 
 gpu_linux_builder(
@@ -207,7 +204,6 @@
         "ci/Linux Wayland FYI Release (Intel)",
     ],
     gn_args = "ci/GPU FYI Linux Wayland Builder",
-    pool = "luci.chromium.gpu.linux.intel.try",
 )
 
 gpu_linux_builder(
@@ -217,7 +213,6 @@
         "ci/Linux FYI Release (AMD RX 5500 XT)",
     ],
     gn_args = "ci/GPU FYI Linux Builder",
-    pool = "luci.chromium.gpu.linux.amd.try",
 )
 
 gpu_linux_builder(
@@ -227,7 +222,6 @@
         "ci/Linux FYI Experimental Release (Intel UHD 630)",
     ],
     gn_args = "ci/GPU FYI Linux Builder",
-    pool = "luci.chromium.gpu.linux.intel.try",
 )
 
 gpu_linux_builder(
@@ -237,7 +231,6 @@
         "ci/Linux FYI Release (Intel UHD 630)",
     ],
     gn_args = "ci/GPU FYI Linux Builder",
-    pool = "luci.chromium.gpu.linux.intel.try",
 )
 
 gpu_linux_builder(
@@ -248,7 +241,6 @@
         "ci/Linux FYI Release (Intel UHD 770)",
     ],
     gn_args = "ci/GPU FYI Linux Builder",
-    pool = "luci.chromium.gpu.linux.intel.uhd770.try",
 )
 
 gpu_linux_builder(
@@ -258,7 +250,6 @@
         "ci/Linux FYI Debug (NVIDIA)",
     ],
     gn_args = "ci/GPU FYI Linux Builder (dbg)",
-    pool = "luci.chromium.gpu.linux.nvidia.try",
 )
 
 gpu_linux_builder(
@@ -268,7 +259,6 @@
         "ci/Linux FYI Experimental Release (NVIDIA)",
     ],
     gn_args = "ci/GPU FYI Linux Builder",
-    pool = "luci.chromium.gpu.linux.nvidia.try",
 )
 
 gpu_linux_builder(
@@ -278,7 +268,6 @@
         "ci/Linux FYI Release (NVIDIA)",
     ],
     gn_args = "ci/GPU FYI Linux Builder",
-    pool = "luci.chromium.gpu.linux.nvidia.try",
 )
 
 gpu_linux_builder(
@@ -287,7 +276,6 @@
         "ci/Linux FYI GPU TSAN Release",
     ],
     gn_args = "ci/Linux FYI GPU TSAN Release",
-    pool = "luci.chromium.gpu.linux.nvidia.try",
 )
 
 gpu_linux_builder(
@@ -297,7 +285,6 @@
         "ci/Linux Debug (NVIDIA)",
     ],
     gn_args = "ci/GPU Linux Builder (dbg)",
-    pool = "luci.chromium.gpu.linux.nvidia.try",
 )
 
 gpu_linux_builder(
@@ -312,7 +299,6 @@
             "no_symbols",
         ],
     ),
-    pool = "luci.chromium.gpu.linux.nvidia.try",
 )
 
 def gpu_mac_builder(*, name, **kwargs):
@@ -510,8 +496,10 @@
 def gpu_win_builder(*, name, **kwargs):
     return try_.builder(
         name = name,
+        pool = "luci.chromium.gpu.try",
         builder_group = "tryserver.chromium.win",
         builderless = True,
+        max_concurrent_builds = 1,
         os = os.WINDOWS_ANY,
         siso_remote_jobs = siso.remote_jobs.LOW_JOBS_FOR_CQ,
         ssd = None,
@@ -525,7 +513,6 @@
         "ci/Win10 FYI x64 Release (AMD RX 5500 XT)",
     ],
     gn_args = "ci/GPU FYI Win x64 Builder",
-    pool = "luci.chromium.gpu.win10.amd.try",
 )
 
 gpu_win_builder(
@@ -535,7 +522,6 @@
         "ci/Win10 FYI x64 Experimental Release (Intel)",
     ],
     gn_args = "ci/GPU FYI Win x64 Builder",
-    pool = "luci.chromium.gpu.win10.intel.try",
 )
 
 gpu_win_builder(
@@ -545,7 +531,6 @@
         "ci/Win10 FYI x64 Release (Intel)",
     ],
     gn_args = "ci/GPU FYI Win x64 Builder",
-    pool = "luci.chromium.gpu.win10.intel.try",
 )
 
 gpu_win_builder(
@@ -556,7 +541,6 @@
         "ci/Win10 FYI x64 Release (Intel UHD 770)",
     ],
     gn_args = "ci/GPU FYI Win x64 Builder",
-    pool = "luci.chromium.gpu.win10.intel.uhd770.try",
 )
 
 gpu_win_builder(
@@ -566,7 +550,6 @@
         "ci/Win10 FYI x64 Debug (NVIDIA)",
     ],
     gn_args = "ci/GPU FYI Win x64 Builder (dbg)",
-    pool = "luci.chromium.gpu.win10.nvidia.try",
 )
 
 gpu_win_builder(
@@ -576,7 +559,6 @@
         "ci/Win10 FYI x64 DX12 Vulkan Debug (NVIDIA)",
     ],
     gn_args = "ci/GPU FYI Win x64 DX12 Vulkan Builder (dbg)",
-    pool = "luci.chromium.gpu.win10.nvidia.try",
 )
 
 gpu_win_builder(
@@ -586,7 +568,6 @@
         "ci/Win10 FYI x64 DX12 Vulkan Release (NVIDIA)",
     ],
     gn_args = "ci/GPU FYI Win x64 DX12 Vulkan Builder",
-    pool = "luci.chromium.gpu.win10.nvidia.try",
 )
 
 gpu_win_builder(
@@ -596,7 +577,6 @@
         "ci/Win10 FYI x64 Exp Release (NVIDIA)",
     ],
     gn_args = "ci/GPU FYI Win x64 Builder",
-    pool = "luci.chromium.gpu.win10.nvidia.try",
 )
 
 gpu_win_builder(
@@ -606,7 +586,6 @@
         "ci/Win10 FYI x86 Release (NVIDIA)",
     ],
     gn_args = "ci/GPU FYI Win Builder",
-    pool = "luci.chromium.gpu.win10.nvidia.try",
 )
 
 gpu_win_builder(
@@ -616,7 +595,6 @@
         "ci/Win10 FYI x64 Release (NVIDIA)",
     ],
     gn_args = "ci/GPU FYI Win x64 Builder",
-    pool = "luci.chromium.gpu.win10.nvidia.try",
 )
 
 gpu_win_builder(
@@ -627,7 +605,6 @@
         "ci/Win10 FYI x64 Release (NVIDIA RTX 4070 Super)",
     ],
     gn_args = "ci/GPU FYI Win x64 Builder",
-    pool = "luci.chromium.gpu.win10.nvidia.try",
 )
 
 gpu_win_builder(
@@ -638,7 +615,6 @@
         "ci/Win11 FYI arm64 Release (Qualcomm Adreno 690)",
     ],
     gn_args = "ci/GPU FYI Win arm64 Builder",
-    pool = "luci.chromium.gpu.win11.qualcomm.try",
 )
 
 gpu_win_builder(
@@ -648,5 +624,4 @@
         "ci/Win10 x64 Debug (NVIDIA)",
     ],
     gn_args = "ci/GPU Win x64 Builder (dbg)",
-    pool = "luci.chromium.gpu.win10.nvidia.try",
 )
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.dawn.star b/infra/config/subprojects/chromium/try/tryserver.chromium.dawn.star
index 230271e..5ab124e 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.dawn.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.dawn.star
@@ -333,9 +333,10 @@
         "ci/Dawn Android arm64 Experimental Release (Pixel 6)",
     ],
     gn_args = "ci/Dawn Android arm64 Builder",
-    pool = "luci.chromium.gpu.android.pixel6.try",
+    pool = "luci.chromium.gpu.try",
     builderless = True,
     os = os.LINUX_DEFAULT,
+    max_concurrent_builds = 1,
     test_presentation = resultdb.test_presentation(
         grouping_keys = ["status", "v.test_suite", "v.gpu"],
     ),
@@ -351,11 +352,10 @@
         "ci/Dawn Android arm64 Release (Samsung S24)",
     ],
     gn_args = "ci/Dawn Android arm64 Builder",
-    # TODO(crbug.com/333424893): Change this to a dedicated S24 pool once
-    # additional GCE quota is available.
-    pool = "luci.chromium.gpu.android.s23.try",
+    pool = "luci.chromium.gpu.try",
     builderless = True,
     os = os.LINUX_DEFAULT,
+    max_concurrent_builds = 1,
     test_presentation = resultdb.test_presentation(
         grouping_keys = ["status", "v.test_suite", "v.gpu"],
     ),
@@ -369,9 +369,10 @@
         "ci/Dawn Linux x64 Experimental Release (Intel UHD 630)",
     ],
     gn_args = "ci/Dawn Linux x64 Builder",
-    pool = "luci.chromium.gpu.linux.intel.try",
+    pool = "luci.chromium.gpu.try",
     builderless = True,
     os = os.LINUX_DEFAULT,
+    max_concurrent_builds = 1,
     test_presentation = resultdb.test_presentation(
         grouping_keys = ["status", "v.test_suite", "v.gpu"],
     ),
@@ -385,9 +386,10 @@
         "ci/Dawn Linux x64 Experimental Release (NVIDIA GTX 1660)",
     ],
     gn_args = "ci/Dawn Linux x64 Builder",
-    pool = "luci.chromium.gpu.linux.nvidia.try",
+    pool = "luci.chromium.gpu.try",
     builderless = True,
     os = os.LINUX_DEFAULT,
+    max_concurrent_builds = 1,
     test_presentation = resultdb.test_presentation(
         grouping_keys = ["status", "v.test_suite", "v.gpu"],
     ),
@@ -442,8 +444,9 @@
         "ci/Dawn ChromeOS Skylab Release (volteer)",
     ],
     gn_args = "ci/Dawn ChromeOS Skylab Release (volteer)",
-    pool = "luci.chromium.gpu.chromeos.volteer.try",
+    pool = "luci.chromium.gpu.try",
     builderless = True,
+    max_concurrent_builds = 1,
     test_presentation = resultdb.test_presentation(
         grouping_keys = ["status", "v.test_suite", "v.gpu"],
     ),
@@ -457,8 +460,9 @@
         "ci/Dawn Linux x64 Release (Intel UHD 770)",
     ],
     gn_args = "ci/Dawn Linux x64 Builder",
-    pool = "luci.chromium.gpu.linux.intel.uhd770.try",
+    pool = "luci.chromium.gpu.try",
     builderless = True,
+    max_concurrent_builds = 1,
     test_presentation = resultdb.test_presentation(
         grouping_keys = ["status", "v.test_suite", "v.gpu"],
     ),
@@ -470,8 +474,9 @@
         "ci/Dawn Linux TSAN Release",
     ],
     gn_args = "ci/Dawn Linux TSAN Release",
-    pool = "luci.chromium.gpu.linux.nvidia.try",
+    pool = "luci.chromium.gpu.try",
     builderless = True,
+    max_concurrent_builds = 1,
     test_presentation = resultdb.test_presentation(
         grouping_keys = ["status", "v.test_suite", "v.gpu"],
     ),
@@ -563,9 +568,10 @@
         "ci/Dawn Win10 x64 Experimental Release (Intel)",
     ],
     gn_args = "ci/Dawn Win10 x64 Builder",
-    pool = "luci.chromium.gpu.win10.intel.try",
+    pool = "luci.chromium.gpu.try",
     builderless = True,
     os = os.WINDOWS_ANY,
+    max_concurrent_builds = 1,
     test_presentation = resultdb.test_presentation(
         grouping_keys = ["status", "v.test_suite", "v.gpu"],
     ),
@@ -579,9 +585,10 @@
         "ci/Dawn Win10 x64 Release (Intel UHD 770)",
     ],
     gn_args = "ci/Dawn Win10 x64 Builder",
-    pool = "luci.chromium.gpu.win10.intel.uhd770.try",
+    pool = "luci.chromium.gpu.try",
     builderless = True,
     os = os.WINDOWS_ANY,
+    max_concurrent_builds = 1,
     test_presentation = resultdb.test_presentation(
         grouping_keys = ["status", "v.test_suite", "v.gpu"],
     ),
@@ -595,9 +602,10 @@
         "ci/Dawn Win10 x64 Experimental Release (NVIDIA)",
     ],
     gn_args = "ci/Dawn Win10 x64 Builder",
-    pool = "luci.chromium.gpu.win10.nvidia.try",
+    pool = "luci.chromium.gpu.try",
     builderless = True,
     os = os.WINDOWS_ANY,
+    max_concurrent_builds = 1,
     test_presentation = resultdb.test_presentation(
         grouping_keys = ["status", "v.test_suite", "v.gpu"],
     ),
@@ -610,9 +618,10 @@
         "ci/Dawn Win10 x86 Experimental Release (Intel)",
     ],
     gn_args = "ci/Dawn Win10 x86 Builder",
-    pool = "luci.chromium.gpu.win10.intel.try",
+    pool = "luci.chromium.gpu.try",
     builderless = True,
     os = os.WINDOWS_ANY,
+    max_concurrent_builds = 1,
     test_presentation = resultdb.test_presentation(
         grouping_keys = ["status", "v.test_suite", "v.gpu"],
     ),
@@ -626,9 +635,10 @@
         "ci/Dawn Win10 x86 Experimental Release (NVIDIA)",
     ],
     gn_args = "ci/Dawn Win10 x86 Builder",
-    pool = "luci.chromium.gpu.win10.nvidia.try",
+    pool = "luci.chromium.gpu.try",
     builderless = True,
     os = os.WINDOWS_ANY,
+    max_concurrent_builds = 1,
     test_presentation = resultdb.test_presentation(
         grouping_keys = ["status", "v.test_suite", "v.gpu"],
     ),
@@ -681,9 +691,10 @@
         "ci/Dawn Win10 x64 ASAN Release (Intel)",
     ],
     gn_args = "ci/Dawn Win10 x64 ASAN Builder",
-    pool = "luci.chromium.gpu.win10.intel.try",
+    pool = "luci.chromium.gpu.try",
     builderless = True,
     os = os.WINDOWS_ANY,
+    max_concurrent_builds = 1,
     test_presentation = resultdb.test_presentation(
         grouping_keys = ["status", "v.test_suite", "v.gpu"],
     ),
@@ -696,9 +707,10 @@
         "ci/Dawn Win10 x64 ASAN Release (NVIDIA)",
     ],
     gn_args = "ci/Dawn Win10 x64 ASAN Builder",
-    pool = "luci.chromium.gpu.win10.nvidia.try",
+    pool = "luci.chromium.gpu.try",
     builderless = True,
     os = os.WINDOWS_ANY,
+    max_concurrent_builds = 1,
     test_presentation = resultdb.test_presentation(
         grouping_keys = ["status", "v.test_suite", "v.gpu"],
     ),
diff --git a/infra/config/targets/autoshard_exceptions.json b/infra/config/targets/autoshard_exceptions.json
index 2c0fa401..ba3818e2 100644
--- a/infra/config/targets/autoshard_exceptions.json
+++ b/infra/config/targets/autoshard_exceptions.json
@@ -95,18 +95,18 @@
         "android-oreo-x86-rel": {
             "content_browsertests": {
                 "debug": {
-                    "avg_num_builds_per_peak_hour": 102,
-                    "estimated_bot_hour_delta": 22.95,
-                    "prev_avg_pending_time_sec": 17.5,
+                    "avg_num_builds_per_peak_hour": 94,
+                    "estimated_bot_hour_delta": -31.33,
+                    "prev_avg_pending_time_sec": 19.3,
                     "prev_p50_pending_time_sec": 3.0,
-                    "prev_p90_pending_time_sec": 53.0,
-                    "prev_percentile_duration_minutes": 17.68,
-                    "prev_shard_count": 75,
-                    "simulated_max_shard_duration": 14.88,
-                    "test_overhead_min": 0.9,
+                    "prev_p90_pending_time_sec": 64.0,
+                    "prev_percentile_duration_minutes": 11.82,
+                    "prev_shard_count": 90,
+                    "simulated_max_shard_duration": 14.91,
+                    "test_overhead_min": 1.0,
                     "try_builder": "android-x86-rel"
                 },
-                "shards": 90
+                "shards": 70
             },
             "unit_tests": {
                 "debug": {
@@ -223,18 +223,18 @@
             },
             "browser_tests": {
                 "debug": {
-                    "avg_num_builds_per_peak_hour": 99,
-                    "estimated_bot_hour_delta": -17.55,
-                    "prev_avg_pending_time_sec": 34.4,
-                    "prev_p50_pending_time_sec": 5.0,
-                    "prev_p90_pending_time_sec": 110.0,
-                    "prev_percentile_duration_minutes": 13.55,
-                    "prev_shard_count": 107,
-                    "simulated_max_shard_duration": 14.99,
-                    "test_overhead_min": 0.9666666666666667,
+                    "avg_num_builds_per_peak_hour": 90,
+                    "estimated_bot_hour_delta": 5.4,
+                    "prev_avg_pending_time_sec": 24.7,
+                    "prev_p50_pending_time_sec": 2.0,
+                    "prev_p90_pending_time_sec": 86.0,
+                    "prev_percentile_duration_minutes": 16.07,
+                    "prev_shard_count": 96,
+                    "simulated_max_shard_duration": 14.87,
+                    "test_overhead_min": 0.45,
                     "try_builder": "linux-chromeos-rel"
                 },
-                "shards": 96
+                "shards": 104
             },
             "components_unittests": {
                 "debug": {
@@ -380,18 +380,18 @@
             },
             "blink_wpt_tests": {
                 "debug": {
-                    "avg_num_builds_per_peak_hour": 98,
-                    "estimated_bot_hour_delta": -3.46,
-                    "prev_avg_pending_time_sec": 18.3,
+                    "avg_num_builds_per_peak_hour": 94,
+                    "estimated_bot_hour_delta": -17.62,
+                    "prev_avg_pending_time_sec": 19.0,
                     "prev_p50_pending_time_sec": 1.0,
-                    "prev_p90_pending_time_sec": 62.0,
-                    "prev_percentile_duration_minutes": 13.39,
-                    "prev_shard_count": 14,
-                    "simulated_max_shard_duration": 14.26,
-                    "test_overhead_min": 2.1166666666666667,
+                    "prev_p90_pending_time_sec": 67.0,
+                    "prev_percentile_duration_minutes": 5.21,
+                    "prev_shard_count": 13,
+                    "simulated_max_shard_duration": 14.12,
+                    "test_overhead_min": 1.25,
                     "try_builder": "linux-rel"
                 },
-                "shards": 13
+                "shards": 4
             },
             "browser_tests": {
                 "debug": {
@@ -425,18 +425,18 @@
             },
             "interactive_ui_tests": {
                 "debug": {
-                    "avg_num_builds_per_peak_hour": 85,
-                    "estimated_bot_hour_delta": 0.64,
-                    "prev_avg_pending_time_sec": 36.6,
+                    "avg_num_builds_per_peak_hour": 94,
+                    "estimated_bot_hour_delta": 0.81,
+                    "prev_avg_pending_time_sec": 18.4,
                     "prev_p50_pending_time_sec": 0.0,
-                    "prev_p90_pending_time_sec": 79.0,
-                    "prev_percentile_duration_minutes": 16.19,
-                    "prev_shard_count": 6,
-                    "simulated_max_shard_duration": 13.94,
-                    "test_overhead_min": 0.45,
+                    "prev_p90_pending_time_sec": 64.0,
+                    "prev_percentile_duration_minutes": 16.06,
+                    "prev_shard_count": 7,
+                    "simulated_max_shard_duration": 14.12,
+                    "test_overhead_min": 0.5166666666666667,
                     "try_builder": "linux-rel"
                 },
-                "shards": 7
+                "shards": 8
             },
             "not_site_per_process_blink_wpt_tests": {
                 "debug": {
@@ -452,6 +452,21 @@
                     "try_builder": "linux-rel"
                 },
                 "shards": 5
+            },
+            "not_site_per_process_headless_shell_wpt_tests": {
+                "debug": {
+                    "avg_num_builds_per_peak_hour": 94,
+                    "estimated_bot_hour_delta": 15.82,
+                    "prev_avg_pending_time_sec": 20.0,
+                    "prev_p50_pending_time_sec": 1.0,
+                    "prev_p90_pending_time_sec": 71.0,
+                    "prev_percentile_duration_minutes": 17.57,
+                    "prev_shard_count": 11,
+                    "simulated_max_shard_duration": 14.53,
+                    "test_overhead_min": 3.3666666666666667,
+                    "try_builder": "linux-rel"
+                },
+                "shards": 14
             }
         },
         "Linux Tests (Wayland)": {
@@ -534,18 +549,18 @@
             },
             "sync_integration_tests": {
                 "debug": {
-                    "avg_num_builds_per_peak_hour": 93,
-                    "estimated_bot_hour_delta": 1.52,
-                    "prev_avg_pending_time_sec": 12.7,
+                    "avg_num_builds_per_peak_hour": 92,
+                    "estimated_bot_hour_delta": 1.53,
+                    "prev_avg_pending_time_sec": 20.7,
                     "prev_p50_pending_time_sec": 0.0,
-                    "prev_p90_pending_time_sec": 44.0,
-                    "prev_percentile_duration_minutes": 16.0,
-                    "prev_shard_count": 5,
-                    "simulated_max_shard_duration": 13.5,
-                    "test_overhead_min": 0.9833333333333333,
+                    "prev_p90_pending_time_sec": 76.0,
+                    "prev_percentile_duration_minutes": 16.14,
+                    "prev_shard_count": 6,
+                    "simulated_max_shard_duration": 13.98,
+                    "test_overhead_min": 1.0,
                     "try_builder": "linux_chromium_asan_rel_ng"
                 },
-                "shards": 6
+                "shards": 7
             },
             "unit_tests": {
                 "debug": {
diff --git a/infra/inclusive_language_presubmit_exempt_dirs.txt b/infra/inclusive_language_presubmit_exempt_dirs.txt
index dcc78090..db6e317 100644
--- a/infra/inclusive_language_presubmit_exempt_dirs.txt
+++ b/infra/inclusive_language_presubmit_exempt_dirs.txt
@@ -415,12 +415,13 @@
 third_party/blink/tools/blinkpy/common/net 3 2
 third_party/blink/tools/blinkpy/common/system 2 1
 third_party/blink/tools/blinkpy/style/checkers 1 1
-third_party/blink/tools/blinkpy/w3c 21 8
+third_party/blink/tools/blinkpy/w3c 20 7
 third_party/blink/tools/blinkpy/web_tests 2 1
 third_party/blink/tools/blinkpy/web_tests/controllers 1 1
 third_party/blink/tools/blinkpy/web_tests/layout_package 7 2
 third_party/blink/tools/blinkpy/web_tests/models 1 1
 third_party/blink/tools/blinkpy/web_tests/port 1 1
+third_party/blink/tools/blinkpy/wpt_tests 1 1
 third_party/blink/web_tests/dom/domparsing 2 2
 third_party/blink/web_tests/external/wpt 2 1
 third_party/blink/web_tests/external/wpt/bluetooth/resources 2 1
@@ -775,7 +776,6 @@
 third_party/tflite_support/src/tensorflow_lite_support/tools/docs 1 1
 third_party/usb_ids 8 1
 third_party/utf/src/share 1 1
-third_party/webpagereplay 1 1
 third_party/webxr_test_pages 1 1
 third_party/webxr_test_pages/webxr-samples 7 5
 third_party/woff2/src 1 1
@@ -808,7 +808,6 @@
 tools/emacs 320 4
 tools/git 2 1
 tools/mac/power/protos/third_party/pprof 1 1
-tools/mb/docs 1 1
 tools/md_browser 7 5
 tools/memory/partition_allocator/palloc_viewer 1 1
 tools/metrics/actions 1 1
diff --git a/internal b/internal
index 1f13466..6f4b9ae 160000
--- a/internal
+++ b/internal
@@ -1 +1 @@
-Subproject commit 1f13466bea73c6280adba142e7bed8f95d04499b
+Subproject commit 6f4b9ae57761436c222a02facc36f260e7b08ed8
diff --git a/ios/chrome/app/application_delegate/app_state.mm b/ios/chrome/app/application_delegate/app_state.mm
index af0a5ba1..582852958 100644
--- a/ios/chrome/app/application_delegate/app_state.mm
+++ b/ios/chrome/app/application_delegate/app_state.mm
@@ -362,8 +362,6 @@
 - (void)sceneState:(SceneState*)sceneState
     transitionedToActivationLevel:(SceneActivationLevel)level {
   if (level >= SceneActivationLevelForegroundActive) {
-    sceneState.presentingModalOverlay =
-        (_uiBlockerTarget != nil) && (_uiBlockerTarget != sceneState);
     [_observers appState:self sceneDidBecomeActive:sceneState];
   }
   crash_keys::SetForegroundScenesCount([self foregroundScenes].count);
diff --git a/ios/chrome/app/profile/profile_state.mm b/ios/chrome/app/profile/profile_state.mm
index 8d3057cb..08c5d1d 100644
--- a/ios/chrome/app/profile/profile_state.mm
+++ b/ios/chrome/app/profile/profile_state.mm
@@ -259,6 +259,7 @@
 
 - (void)sceneState:(SceneState*)sceneState
     transitionedToActivationLevel:(SceneActivationLevel)level {
+  id<UIBlockerTarget> currentUIBlocker = self.currentUIBlocker;
   switch (level) {
     case SceneActivationLevelUnattached:
       // Nothing to do.
@@ -276,6 +277,8 @@
 
     case SceneActivationLevelForegroundActive:
       [_observers profileState:self sceneDidBecomeActive:sceneState];
+      sceneState.presentingModalOverlay =
+          currentUIBlocker && currentUIBlocker != sceneState;
       break;
   }
 }
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ar.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ar.xtb
index eb9fbb1..87885c6 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ar.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ar.xtb
@@ -154,7 +154,7 @@
 <translation id="5389212809648216794">‏يتعذر على Google Chrome استخدام الكاميرا نظرًا لأنها قيد الاستخدام من قِبل تطبيق آخر</translation>
 <translation id="5395376160638294582">‏يُرجى التأكُّد من أنّه يمكنك استخدام بيانات Chrome في حسابك على Google في أي وقت.</translation>
 <translation id="5404252374083197467">‏هل تريد ضبط Chrome كمتصفِّح تلقائي؟</translation>
-<translation id="5439191312780166229">‏ستتلقّى تحذيرات بشأن المواقع الإلكترونية الخطيرة، بما فيها المواقع التي لم يتعرّف عليها محرك البحث Google من قَبل، من خلال تحليل بيانات من المواقع الإلكترونية أكثر من الحماية العادية. يمكنك اختيار تخطّي تحذيرات Chrome.</translation>
+<translation id="5439191312780166229">‏ستتلقّى تحذيرات بشأن المواقع الإلكترونية الخطيرة، بما فيها المواقع الإلكترونية التي لم يتعرّف عليها محرك بحث Google، من خلال تحليل قدر أكبر من البيانات الواردة من المواقع الإلكترونية، مقارنةً بالحماية العادية. يمكنك اختيار تخطّي تحذيرات Chrome.</translation>
 <translation id="5442013002200339429">‏في حال إخفاء "<ph name="MODULE_NAME" />"، لن يتتبّع Chrome الطرود المستقبلية تلقائيًا وسيحذف جميع بيانات تتبُّع الطرود السابقة.</translation>
 <translation id="5460571915754665838">‏4- اختيار Chrome</translation>
 <translation id="546541279759910616">{COUNT,plural, =1{‏سيساعدك متصفِّح Chrome في تتبُّع هذه الحزمة في صفحة علامة تبويب جديدة.}zero{‏سيساعدك متصفِّح Chrome في تتبُّع هذه الحِزم في صفحة علامة تبويب جديدة.}two{‏سيساعدك متصفِّح Chrome في تتبُّع هاتين الحزمتَين في صفحة علامة تبويب جديدة.}few{‏سيساعدك متصفِّح Chrome في تتبُّع هذه الحِزم في صفحة علامة تبويب جديدة.}many{‏سيساعدك متصفِّح Chrome في تتبُّع هذه الحِزم في صفحة علامة تبويب جديدة.}other{‏سيساعدك متصفِّح Chrome في تتبُّع هذه الحِزم في صفحة علامة تبويب جديدة.}}</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_am.xtb b/ios/chrome/app/strings/resources/ios_strings_am.xtb
index fc979bac..a37ba47 100644
--- a/ios/chrome/app/strings/resources/ios_strings_am.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_am.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">ማንነት በማያሳውቅ ሁነታ ላይ አግድ</translation>
 <translation id="6625830436658400045">የእርስዎ የማስመር ቅንብሮች በእርስዎ የመጨረሻ ምትኬ ላይ በመመስረት ወደነበሩበት ይመለሳሉ። በማንኛውም ጊዜ ምን እንደሚያሰምሩ በ<ph name="BEGIN_LINK" />ቅንብሮች<ph name="END_LINK" /> ውስጥ መምረጥ ይችላሉ።</translation>
 <translation id="6627583120233659107">አቃፊ አርትዕ</translation>
+<translation id="6629759408545977279">ከ፦ <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">የእርስዎ ድርጅት ማንነት የማያሳውቅ ሁነታን አጥፍቷል</translation>
 <translation id="6638511529934826365">ጽሑፍን አጉላ…</translation>
 <translation id="6640268266988685324">ትር ክፈት</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ar.xtb b/ios/chrome/app/strings/resources/ios_strings_ar.xtb
index bbc4361a..1089aca 100644
--- a/ios/chrome/app/strings/resources/ios_strings_ar.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_ar.xtb
@@ -464,7 +464,7 @@
 
 
 اطّلِع على تعليمات محرك البحث بشأن حذف سجلّ البحث، إن أمكن.</translation>
-<translation id="3080525922482950719">يمكنك حفظ صفحات لقرائتها لاحقًا أو بلا إنترنت.</translation>
+<translation id="3080525922482950719">يمكنك حفظ صفحات لقراءتها لاحقًا أو بلا إنترنت</translation>
 <translation id="3081338492074632642">يُرجى التأكّد من أنّ كلمة المرور التي تريد حفظها تطابِق كلمة مرور <ph name="WEBSITE" />.</translation>
 <translation id="3087734570205094154">أسفل</translation>
 <translation id="309710370695886264">لديك كلمة مرور واحدة مستخدَمة لحساب آخر. عليك تغييرها الآن للحفاظ على أمانك.</translation>
@@ -1113,7 +1113,7 @@
 <translation id="6100617279104942061">تم تسجيل الدخول بحساب "<ph name="USER_EMAIL" />". يفتح هذا الزر صفحة الإعدادات.</translation>
 <translation id="6103540626693881831">التشفير على الجهاز فقط</translation>
 <translation id="6122191549521593678">متصل</translation>
-<translation id="6122831415929794347">هل تريد إيقاف "التصفُّح الآمن"؟</translation>
+<translation id="6122831415929794347">هل المطلوب إيقاف "التصفُّح الآمن"؟</translation>
 <translation id="6123514585040403489">سيتم إغلاق علامات التبويب</translation>
 <translation id="6127379762771434464">أُزيلَ عنصر</translation>
 <translation id="6136914049981179737">قبل ثانية</translation>
@@ -1526,7 +1526,7 @@
 <translation id="7899199123054742721">وضع علامة "غير مقروءة" على الكل</translation>
 <translation id="7911190106180361398">لا تسمح لك مؤسستك بمزامنة كل البيانات.</translation>
 <translation id="792357691529995513">لم يتم رصد أي مشاكل.</translation>
-<translation id="7925108652071887026">ملء البيانات تلقائيًا</translation>
+<translation id="7925108652071887026">بيانات الملء التلقائي</translation>
 <translation id="7926975587469166629">لقب البطاقة</translation>
 <translation id="7927711904086083099">غير محدد</translation>
 <translation id="7930998711684428189">التحذير في حال الكشف عن كلمات المرور في عملية اختراق بيانات</translation>
@@ -1551,7 +1551,7 @@
 <translation id="7993619969781047893">قد تتوقف الميزات عن العمل في بعض المواقع الإلكترونية.</translation>
 <translation id="7996239959906074962">إعداد…</translation>
 <translation id="800361585186029508">‏فتح عناوين URL التي تم إدخالها في Google Chrome</translation>
-<translation id="8005666035647241369">‏حفظ كلمة المرور في "مدير كلمات المرور" من Google على هذا الجهاز</translation>
+<translation id="8005666035647241369">‏في "مدير كلمات المرور في Google" على هذا الجهاز</translation>
 <translation id="8011489434346330032">‏أداة فحص الويب (Web Inspector) </translation>
 <translation id="802154636333426148">تعذّر التنزيل</translation>
 <translation id="8023878949384262191">توسيع القسم.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_as.xtb b/ios/chrome/app/strings/resources/ios_strings_as.xtb
index 9960c9e..7c1ee72 100644
--- a/ios/chrome/app/strings/resources/ios_strings_as.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_as.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">ইনক’গনিট’ ম’ডত অৱৰোধ কৰক</translation>
 <translation id="6625830436658400045">আপোনাৰ অন্তিম বেকআপৰ ভিত্তিত আপোনাৰ ছিংকৰ ছেটিং পুনঃস্থাপন কৰা হ’ব। আপুনি কি ছিংক কৰিব লাগে সেয়া <ph name="BEGIN_LINK" />ছেটিঙ<ph name="END_LINK" />লৈ গৈ যেতিয়াই মন যায় তেতিয়াই বাছনি কৰিব পাৰে।</translation>
 <translation id="6627583120233659107">ফ’ল্ডাৰ সম্পাদনা কৰক</translation>
+<translation id="6629759408545977279">হ’ষ্ট: <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">আপোনাৰ প্ৰতিষ্ঠানে ইনক’গনিট’ ম’ডটো অফ কৰিছে</translation>
 <translation id="6638511529934826365">পাঠ জুম কৰক…</translation>
 <translation id="6640268266988685324">খোলা টেব</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_az.xtb b/ios/chrome/app/strings/resources/ios_strings_az.xtb
index d64583b2..b01eb54 100644
--- a/ios/chrome/app/strings/resources/ios_strings_az.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_az.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">Anonim rejimdə bloklayın</translation>
 <translation id="6625830436658400045">Sinxronizasiya ayarlarınız son yedəkləmənizə əsasən bərpa olunacaq. Sinxronizasiya seçimlərini <ph name="BEGIN_LINK" />ayarlarda<ph name="END_LINK" /> edə bilərsiniz.</translation>
 <translation id="6627583120233659107">Qovluğa düzəliş edin</translation>
+<translation id="6629759408545977279">Haradan: <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">Təşkilatınız Anonim rejimi deaktiv edib</translation>
 <translation id="6638511529934826365">Mətni Böyüdün…</translation>
 <translation id="6640268266988685324">Açıq Tab</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ca.xtb b/ios/chrome/app/strings/resources/ios_strings_ca.xtb
index 07e20a9..c3c9a11 100644
--- a/ios/chrome/app/strings/resources/ios_strings_ca.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_ca.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">Bloqueja en mode d'incògnit</translation>
 <translation id="6625830436658400045">La configuració de sincronització es restaurarà a partir de la darrera còpia de seguretat. Pots anar a la <ph name="BEGIN_LINK" />configuració<ph name="END_LINK" /> en qualsevol moment per decidir què vols sincronitzar.</translation>
 <translation id="6627583120233659107">Edita la carpeta</translation>
+<translation id="6629759408545977279">De: <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">La teva organització ha desactivat el mode d'incògnit</translation>
 <translation id="6638511529934826365">Amplia el text…</translation>
 <translation id="6640268266988685324">Obre la pestanya</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_da.xtb b/ios/chrome/app/strings/resources/ios_strings_da.xtb
index b3a0cff7..04ded907 100644
--- a/ios/chrome/app/strings/resources/ios_strings_da.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_da.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">Bloker i inkognito</translation>
 <translation id="6625830436658400045">Dine indstillinger for synkronisering gendannes på baggrund af din seneste sikkerhedskopi. Du kan altid vælge, hvad der skal synkroniseres, i <ph name="BEGIN_LINK" />indstillingerne<ph name="END_LINK" />.</translation>
 <translation id="6627583120233659107">Rediger mappen</translation>
+<translation id="6629759408545977279">Fra: <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">Din organisation har deaktiveret inkognitotilstand</translation>
 <translation id="6638511529934826365">Zoom ind/ud på tekst…</translation>
 <translation id="6640268266988685324">Åben fane</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_el.xtb b/ios/chrome/app/strings/resources/ios_strings_el.xtb
index be53bffe..cb7be29 100644
--- a/ios/chrome/app/strings/resources/ios_strings_el.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_el.xtb
@@ -1418,7 +1418,7 @@
 <translation id="7438481509621345350">Θα βλέπετε πλέον ειδήσεις από τον ιστότοπο <ph name="CHANNEL_NAME" /> όταν ανοίγετε μια νέα καρτέλα.</translation>
 <translation id="7451023311965289370">{count,plural, =1{Ο σελιδοδείκτης αποθηκεύτηκε στον φάκελο {title}}other{Οι σελιδοδείκτες αποθηκεύτηκαν στον φάκελο {title}}}</translation>
 <translation id="7451404862887877229">Πατήστε Απόρρητο και ασφάλεια και έπειτα Ασφαλής περιήγηση</translation>
-<translation id="7454057999980797137">Νομός/Επαρχία</translation>
+<translation id="7454057999980797137">Νομός/κομητεία</translation>
 <translation id="7458706065921255639">Εξατομίκευση και σύνδεση</translation>
 <translation id="745899714366929493">Όλη την ημέρα</translation>
 <translation id="7460698861522306757">Αίτημα ιστοτόπου για κινητά</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_en-GB.xtb b/ios/chrome/app/strings/resources/ios_strings_en-GB.xtb
index b75fe4af..c3bde41d 100644
--- a/ios/chrome/app/strings/resources/ios_strings_en-GB.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_en-GB.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">Block in Incognito</translation>
 <translation id="6625830436658400045">Your sync settings will be restored based on your last backup. You can always choose what to sync in <ph name="BEGIN_LINK" />settings<ph name="END_LINK" />.</translation>
 <translation id="6627583120233659107">Edit folder</translation>
+<translation id="6629759408545977279">From: <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">Your organisation turned off Incognito mode</translation>
 <translation id="6638511529934826365">Zoom text…</translation>
 <translation id="6640268266988685324">Open tab</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_es.xtb b/ios/chrome/app/strings/resources/ios_strings_es.xtb
index 248193f..8bb903e 100644
--- a/ios/chrome/app/strings/resources/ios_strings_es.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_es.xtb
@@ -716,7 +716,7 @@
 <translation id="4322394346347055525">Cerrar las demás pestañas</translation>
 <translation id="4324735664183300693">Activar notificaciones</translation>
 <translation id="4326912346867677256">Toca Usar contraseña para iniciar sesión de forma segura.</translation>
-<translation id="4328843285884395590">Mi unidad</translation>
+<translation id="4328843285884395590">Mi Drive</translation>
 <translation id="4331177082088332784">Puedes gestionar esto en BEGIN_LINKConfiguración de contenidoEND_LINK</translation>
 <translation id="4334428914252001502">1 artículo no leído.</translation>
 <translation id="4338258232580025606">No puedo acceder</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_gu.xtb b/ios/chrome/app/strings/resources/ios_strings_gu.xtb
index e4c1227..9ca2e516 100644
--- a/ios/chrome/app/strings/resources/ios_strings_gu.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_gu.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">છૂપા મોડમાં બ્લૉક કરો</translation>
 <translation id="6625830436658400045">તમારા છેલ્લા બૅકઅપના આધારે તમારા સિંક કરેલા સેટિંગ રિસ્ટોર કરવામાં આવશે. શું સિંક કરવું, તે તમે <ph name="BEGIN_LINK" />સેટિંગ<ph name="END_LINK" />માં જઈને કોઈપણ સમયે પસંદ કરી શકો છો.</translation>
 <translation id="6627583120233659107">ફોલ્ડરમાં ફેરફાર કરો</translation>
+<translation id="6629759408545977279">મોકલનાર: <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">તમારી સંસ્થાએ છૂપો મોડ બંધ કર્યો છે</translation>
 <translation id="6638511529934826365">ટેક્સ્ટ નાની-મોટી કરો…</translation>
 <translation id="6640268266988685324">ટૅબ ખોલો</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_hy.xtb b/ios/chrome/app/strings/resources/ios_strings_hy.xtb
index 12affde4..9817b55 100644
--- a/ios/chrome/app/strings/resources/ios_strings_hy.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_hy.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">Արգելափակել ինկոգնիտո ռեժիմում</translation>
 <translation id="6625830436658400045">Համաժամացման ձեր կարգավորումները կվերականգնվեն վերջին պահուստավորված տվյալների հիման վրա։ Դուք ցանկացած ժամանակ կարող եք անցնել <ph name="BEGIN_LINK" />կարգավորումներ<ph name="END_LINK" /> և ընտրել, թե ինչն եք ուզում համաժամացնել։</translation>
 <translation id="6627583120233659107">Փոփոխել պանակը</translation>
+<translation id="6629759408545977279">Աղբյուրը՝ <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">Ձեր կազմակերպությունն անջատել է ինկոգնիտո ռեժիմը</translation>
 <translation id="6638511529934826365">Մեծացնել տեքստը…</translation>
 <translation id="6640268266988685324">Բացել ներդիր</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_id.xtb b/ios/chrome/app/strings/resources/ios_strings_id.xtb
index 161aa47..55742bb 100644
--- a/ios/chrome/app/strings/resources/ios_strings_id.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_id.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">Blokir dalam mode Samaran</translation>
 <translation id="6625830436658400045">Setelan sinkronisasi akan dipulihkan berdasarkan cadangan terakhir Anda. Anda dapat memilih jenis data yang akan disinkronkan di <ph name="BEGIN_LINK" />setelan<ph name="END_LINK" /> kapan saja.</translation>
 <translation id="6627583120233659107">Edit folder</translation>
+<translation id="6629759408545977279">Dari: <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">Organisasi Anda menonaktifkan mode Samaran</translation>
 <translation id="6638511529934826365">Zoom Teks…</translation>
 <translation id="6640268266988685324">Tab Terbuka</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ja.xtb b/ios/chrome/app/strings/resources/ios_strings_ja.xtb
index 96ab98a..6737f98 100644
--- a/ios/chrome/app/strings/resources/ios_strings_ja.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_ja.xtb
@@ -1311,7 +1311,7 @@
 <translation id="6899890595581608884">安全チェックの通知がオフになっています</translation>
 <translation id="6900532703269623216">保護強化機能</translation>
 <translation id="6900702165119149418">ログアウトしました</translation>
-<translation id="6903907808598579934">同期を ON にする</translation>
+<translation id="6903907808598579934">同期をオンにする</translation>
 <translation id="6906448540340261898">Google アカウントのパスワードを常に使用できるようにしてください</translation>
 <translation id="6908734251759299256">ブラウザを更新してください</translation>
 <translation id="6913136913033237761"><ph name="FOLDER_NAME" />、このデバイスのみ。</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ko.xtb b/ios/chrome/app/strings/resources/ios_strings_ko.xtb
index 6637428a..e8f2ee0a 100644
--- a/ios/chrome/app/strings/resources/ios_strings_ko.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_ko.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">시크릿 모드에서 차단</translation>
 <translation id="6625830436658400045">마지막 백업에 따라 동기화 설정이 복원됩니다. 언제든지 <ph name="BEGIN_LINK" />설정<ph name="END_LINK" />에서 동기화할 항목을 선택할 수 있습니다.</translation>
 <translation id="6627583120233659107">폴더 수정</translation>
+<translation id="6629759408545977279">호스트: <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">조직에서 시크릿 모드를 사용 중지함</translation>
 <translation id="6638511529934826365">텍스트 확대/축소…</translation>
 <translation id="6640268266988685324">탭 열기</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_lt.xtb b/ios/chrome/app/strings/resources/ios_strings_lt.xtb
index 3f75bf6..87ac03b 100644
--- a/ios/chrome/app/strings/resources/ios_strings_lt.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_lt.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">Blokuoti inkognito režimu</translation>
 <translation id="6625830436658400045">Sinchronizavimo nustatymai bus atkurti pagal paskutinę atsarginę kopiją. Bet kada galite pasirinkti, ką norite sinchronizuoti, skiltyje <ph name="BEGIN_LINK" />„Nustatymai“<ph name="END_LINK" />.</translation>
 <translation id="6627583120233659107">Redaguoti aplanką</translation>
+<translation id="6629759408545977279">Iš: <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">Jūsų organizacija išjungė inkognito režimą</translation>
 <translation id="6638511529934826365">Keisti teksto mastelį…</translation>
 <translation id="6640268266988685324">Atidarytas skirtukas</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_lv.xtb b/ios/chrome/app/strings/resources/ios_strings_lv.xtb
index 49b2ab15..8591e0d 100644
--- a/ios/chrome/app/strings/resources/ios_strings_lv.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_lv.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">Bloķēt inkognito režīmā</translation>
 <translation id="6625830436658400045">Jūsu sinhronizācijas iestatījumi tiks atjaunoti, pamatojoties uz pēdējo dublējumu. <ph name="BEGIN_LINK" />Iestatījumos<ph name="END_LINK" /> varat jebkurā laikā izvēlēties, ko sinhronizēt.</translation>
 <translation id="6627583120233659107">Rediģēt mapi</translation>
+<translation id="6629759408545977279">No: <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">Jūsu organizācija izslēdza inkognito režīmu.</translation>
 <translation id="6638511529934826365">Veikt teksta tālummaiņu…</translation>
 <translation id="6640268266988685324">Atvērta cilne</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_mn.xtb b/ios/chrome/app/strings/resources/ios_strings_mn.xtb
index 95eca07..6a9f466 100644
--- a/ios/chrome/app/strings/resources/ios_strings_mn.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_mn.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">Нууцлалын горимд блоклосон</translation>
 <translation id="6625830436658400045">Таны синк хийх тохиргоог сүүлийн нөөцлөлтөд тань тулгуурлан сэргээнэ. Та синк хийх зүйлээ <ph name="BEGIN_LINK" />тохиргоо<ph name="END_LINK" /> хэсгээс хүссэн үедээ сонгох боломжтой.</translation>
 <translation id="6627583120233659107">Хавтас засах</translation>
+<translation id="6629759408545977279">Дараахаас: <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">Танай байгууллага Нууцлалын горимыг унтраасан</translation>
 <translation id="6638511529934826365">Текстийг томруулах…</translation>
 <translation id="6640268266988685324">Нээлттэй таб</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_mr.xtb b/ios/chrome/app/strings/resources/ios_strings_mr.xtb
index e7db500..91d53e4 100644
--- a/ios/chrome/app/strings/resources/ios_strings_mr.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_mr.xtb
@@ -1251,6 +1251,7 @@
 <translation id="6624219055418309072">गुप्त मोडमध्ये ब्लॉक करा</translation>
 <translation id="6625830436658400045">तुमच्या शेवटच्या बॅकअपच्या आधारावर तुमची सिंक सेटिंग्ज रिस्टोअर केली जातील. काय सिंक करायचे हे तुम्ही <ph name="BEGIN_LINK" />सेटिंग्ज<ph name="END_LINK" /> मध्ये कधीही निवडू शकता.</translation>
 <translation id="6627583120233659107">फोल्डर संपादित करा</translation>
+<translation id="6629759408545977279">प्रेषक: <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">तुमच्या संस्थेने गुप्त मोड बंद केलेला आहे</translation>
 <translation id="6638511529934826365">मजकूर झूम करा…</translation>
 <translation id="6640268266988685324">टॅब उघडा</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ne.xtb b/ios/chrome/app/strings/resources/ios_strings_ne.xtb
index 56ed8e27..01332f1b 100644
--- a/ios/chrome/app/strings/resources/ios_strings_ne.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_ne.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">इन्कोग्निटो मोडमा रोक लगाउनुहोस्</translation>
 <translation id="6625830436658400045">तपाईंको पछिल्लो ब्याकअपका आधारमा तपाईंले तय गर्नुभएका सिंकसम्बन्धी सेटिङ रिस्टोर गरिने छ। तपाईं जुनसुकै बेला <ph name="BEGIN_LINK" />सेटिङ<ph name="END_LINK" />मा गई आफूले सिंक गर्न चाहेका कुराहरू छनौट गर्न सक्नुहुन्छ।</translation>
 <translation id="6627583120233659107">फोल्डर सम्पादन गर्नुहोस्</translation>
+<translation id="6629759408545977279">होस्ट: <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">तपाईंको सङ्गठनले इन्कोग्निटो मोड अफ गरेको छ</translation>
 <translation id="6638511529934826365">पाठ जुम गर्नुहोस्…</translation>
 <translation id="6640268266988685324">ट्याब खोल्नुहोस्</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_pl.xtb b/ios/chrome/app/strings/resources/ios_strings_pl.xtb
index 40fb3c61..0710a448 100644
--- a/ios/chrome/app/strings/resources/ios_strings_pl.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_pl.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">Blokuj w trybie incognito</translation>
 <translation id="6625830436658400045">Ustawienia synchronizacji zostaną przywrócone na podstawie ostatniej kopii zapasowej. W <ph name="BEGIN_LINK" />ustawieniach<ph name="END_LINK" /> możesz wybrać, co chcesz synchronizować.</translation>
 <translation id="6627583120233659107">Edytuj folder</translation>
+<translation id="6629759408545977279">Od: <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">Twoja organizacja wyłączyła tryb incognito</translation>
 <translation id="6638511529934826365">Powiększ tekst…</translation>
 <translation id="6640268266988685324">Otwórz kartę</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_pt-BR.xtb b/ios/chrome/app/strings/resources/ios_strings_pt-BR.xtb
index d1cae36..ce28e96 100644
--- a/ios/chrome/app/strings/resources/ios_strings_pt-BR.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_pt-BR.xtb
@@ -1065,7 +1065,7 @@
 <translation id="5888889603768021126">Login feito com</translation>
 <translation id="5889333064153755823">Excluir dados de navegação</translation>
 <translation id="5896576662943111387">Desenvolvido para iOS</translation>
-<translation id="5897749768294722429">Para voltar rapidamente aos sites visitados, sincronize as guias e o histórico</translation>
+<translation id="5897749768294722429">Para voltar rapidamente aos sites visitados, sincronize as guias e o histórico.</translation>
 <translation id="5898848375214731122">Massa</translation>
 <translation id="5899314093904173337">Para compartilhar com pessoas próximas, permita que elas leiam esse QR code com a câmera ou um app adequado</translation>
 <translation id="5911030830365207728">Google Tradutor</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ro.xtb b/ios/chrome/app/strings/resources/ios_strings_ro.xtb
index 71de133..a3a4ce8 100644
--- a/ios/chrome/app/strings/resources/ios_strings_ro.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_ro.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">Blochează în modul incognito</translation>
 <translation id="6625830436658400045">Setările de sincronizare vor fi restabilite pe baza ultimului backup. Poți să alegi oricând ce să sincronizezi în <ph name="BEGIN_LINK" />setări<ph name="END_LINK" />.</translation>
 <translation id="6627583120233659107">Editați dosarul</translation>
+<translation id="6629759408545977279">De la: <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">Organizația ta a dezactivat modul incognito</translation>
 <translation id="6638511529934826365">Fă zoom pe text…</translation>
 <translation id="6640268266988685324">Filă deschisă</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ru.xtb b/ios/chrome/app/strings/resources/ios_strings_ru.xtb
index 9deb514b..c5301478 100644
--- a/ios/chrome/app/strings/resources/ios_strings_ru.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_ru.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">Запретить использование в режиме инкогнито</translation>
 <translation id="6625830436658400045">Ваши настройки синхронизации будут восстановлены на основе данных из последней резервной копии. Вы всегда можете выбрать, что синхронизировать, в <ph name="BEGIN_LINK" />настройках<ph name="END_LINK" />.</translation>
 <translation id="6627583120233659107">Изменить папку</translation>
+<translation id="6629759408545977279">Откуда: <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">В вашей организации режим инкогнито отключен.</translation>
 <translation id="6638511529934826365">Изменить масштаб текста</translation>
 <translation id="6640268266988685324">Открытая вкладка</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_sl.xtb b/ios/chrome/app/strings/resources/ios_strings_sl.xtb
index 9588cce..fffce1d3 100644
--- a/ios/chrome/app/strings/resources/ios_strings_sl.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_sl.xtb
@@ -565,7 +565,7 @@
 <translation id="3588820906588687999">Odpri sliko na novem zavihku</translation>
 <translation id="3591006724568464696">Nedavni zavihki niso na voljo</translation>
 <translation id="3595252146048399851">V <ph name="BEGIN_LINK" />nastavitvah<ph name="END_LINK" /> lahko kadar koli izberete, kaj želite sinhronizirati. Google lahko prilagodi Iskanje Google in druge storitve glede na vašo zgodovino.</translation>
-<translation id="3596414637720633074">Blokiranje piškotkov drugih mest v anonimnem načinu</translation>
+<translation id="3596414637720633074">Blokiranje piškotkov tretjih oseb v anonimnem načinu</translation>
 <translation id="3602260545951981695">Izberite »Izboljšana zaščita«</translation>
 <translation id="3622175633937495219">Zgodovina iskanja (najdeno: <ph name="COUNT" />)</translation>
 <translation id="3625008969091706597">Za premik nazaj lahko povlečete po robu.</translation>
@@ -1136,7 +1136,7 @@
 <translation id="6189413832092199491">Neprebrano</translation>
 <translation id="6193448654517602979">Izberite zavihke</translation>
 <translation id="6196207969502475924">Glasovno iskanje</translation>
-<translation id="6196640612572343990">Blokiraj piškotke drugih spletnih mest</translation>
+<translation id="6196640612572343990">Blokiraj piškotke tretjih oseb</translation>
 <translation id="6198252989419008588">Spremeni PIN</translation>
 <translation id="6210079381482819663">Sem so premaknjeni zavihki, ki jih ne uporabljate najmanj toliko dni: <ph name="THRESHOLD" />. To lahko kadar koli spremenite v <ph name="BEGIN_LINK" />nastavitvah<ph name="END_LINK" />.</translation>
 <translation id="6213281885682386884">Najden ni bil noben naslov</translation>
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">Blokirano v anonimnem načinu</translation>
 <translation id="6625830436658400045">Nastavitve sinhronizacije bodo obnovljene na podlagi zadnjega varnostnega kopiranja. V <ph name="BEGIN_LINK" />nastavitvah<ph name="END_LINK" /> lahko kadar koli izberete, kaj želite sinhronizirati.</translation>
 <translation id="6627583120233659107">Uredi mapo</translation>
+<translation id="6629759408545977279">Od: <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">Vaša organizacija je izklopila anonimni način.</translation>
 <translation id="6638511529934826365">Povečaj/pomanjšaj besedilo …</translation>
 <translation id="6640268266988685324">Odprti zavihek</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_sw.xtb b/ios/chrome/app/strings/resources/ios_strings_sw.xtb
index 682b77f..fbb62949 100644
--- a/ios/chrome/app/strings/resources/ios_strings_sw.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_sw.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">Zuia katika Hali Fiche</translation>
 <translation id="6625830436658400045">Mipangilio yako ya usawazishaji itarejeshwa kulingana na nakala uliyohifadhi mara ya mwisho. Unaweza kuchagua unachotaka kusawazisha wakati wowote kwenye <ph name="BEGIN_LINK" />mipangilio<ph name="END_LINK" />.</translation>
 <translation id="6627583120233659107">Badilisha folda</translation>
+<translation id="6629759408545977279">Kutoka: <ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">Shirika lako limezima Hali fiche</translation>
 <translation id="6638511529934826365">Kuza Maandishi…</translation>
 <translation id="6640268266988685324">Fungua Kichupo</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_zh-HK.xtb b/ios/chrome/app/strings/resources/ios_strings_zh-HK.xtb
index e6d46ca..f4a826b 100644
--- a/ios/chrome/app/strings/resources/ios_strings_zh-HK.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_zh-HK.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">在無痕模式中封鎖</translation>
 <translation id="6625830436658400045">系統會根據上次的備份還原同步處理設定。您隨時可在<ph name="BEGIN_LINK" />設定<ph name="END_LINK" />中選擇要同步的資料。</translation>
 <translation id="6627583120233659107">編輯資料夾</translation>
+<translation id="6629759408545977279">來源:<ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">您的機構已關閉無痕模式</translation>
 <translation id="6638511529934826365">縮放文字…</translation>
 <translation id="6640268266988685324">開啟分頁</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_zh-TW.xtb b/ios/chrome/app/strings/resources/ios_strings_zh-TW.xtb
index 655ccb2..d4014c40 100644
--- a/ios/chrome/app/strings/resources/ios_strings_zh-TW.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_zh-TW.xtb
@@ -1250,6 +1250,7 @@
 <translation id="6624219055418309072">在無痕模式中封鎖</translation>
 <translation id="6625830436658400045">系統會根據上次的備份記錄還原同步處理設定。你隨時可以前往<ph name="BEGIN_LINK" />設定<ph name="END_LINK" />選擇要同步的資料。</translation>
 <translation id="6627583120233659107">編輯資料夾</translation>
+<translation id="6629759408545977279">來源:<ph name="ORIGINATING_HOST" /></translation>
 <translation id="6634432609054530164">貴機構已關閉無痕模式</translation>
 <translation id="6638511529934826365">縮放文字…</translation>
 <translation id="6640268266988685324">開啟分頁</translation>
diff --git a/ios/chrome/browser/affiliations/model/BUILD.gn b/ios/chrome/browser/affiliations/model/BUILD.gn
index a338b798..282da08c 100644
--- a/ios/chrome/browser/affiliations/model/BUILD.gn
+++ b/ios/chrome/browser/affiliations/model/BUILD.gn
@@ -12,8 +12,8 @@
     "//components/keyed_service/core",
     "//components/password_manager/core/browser",
     "//ios/chrome/browser/shared/model/application_context",
-    "//ios/chrome/browser/shared/model/browser_state",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
     "//services/network/public/cpp",
   ]
   public_deps = [
diff --git a/ios/chrome/browser/affiliations/model/ios_chrome_affiliation_service_factory.h b/ios/chrome/browser/affiliations/model/ios_chrome_affiliation_service_factory.h
index c603578c..8a60ccd 100644
--- a/ios/chrome/browser/affiliations/model/ios_chrome_affiliation_service_factory.h
+++ b/ios/chrome/browser/affiliations/model/ios_chrome_affiliation_service_factory.h
@@ -6,16 +6,14 @@
 #define IOS_CHROME_BROWSER_AFFILIATIONS_MODEL_IOS_CHROME_AFFILIATION_SERVICE_FACTORY_H_
 
 #include "base/no_destructor.h"
-#include "components/keyed_service/ios/browser_state_keyed_service_factory.h"
-
-class ProfileIOS;
+#include "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
 namespace affiliations {
 class AffiliationService;
 }
 
 class IOSChromeAffiliationServiceFactory
-    : public BrowserStateKeyedServiceFactory {
+    : public ProfileKeyedServiceFactoryIOS {
  public:
   static IOSChromeAffiliationServiceFactory* GetInstance();
   static affiliations::AffiliationService* GetForProfile(ProfileIOS* profile);
@@ -28,7 +26,6 @@
 
   std::unique_ptr<KeyedService> BuildServiceInstanceFor(
       web::BrowserState* context) const override;
-  web::BrowserState* GetBrowserStateToUse(web::BrowserState*) const override;
 };
 
 #endif  // IOS_CHROME_BROWSER_AFFILIATIONS_MODEL_IOS_CHROME_AFFILIATION_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/affiliations/model/ios_chrome_affiliation_service_factory.mm b/ios/chrome/browser/affiliations/model/ios_chrome_affiliation_service_factory.mm
index bedae5f..8ad6a3fcb 100644
--- a/ios/chrome/browser/affiliations/model/ios_chrome_affiliation_service_factory.mm
+++ b/ios/chrome/browser/affiliations/model/ios_chrome_affiliation_service_factory.mm
@@ -7,16 +7,12 @@
 #import <memory>
 #import <utility>
 
-#import "base/no_destructor.h"
 #import "base/not_fatal_until.h"
 #import "base/task/sequenced_task_runner.h"
 #import "base/task/thread_pool.h"
 #import "components/affiliations/core/browser/affiliation_constants.h"
 #import "components/affiliations/core/browser/affiliation_service_impl.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
-#import "ios/chrome/browser/shared/model/browser_state/browser_state_otr_helper.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "services/network/public/cpp/shared_url_loader_factory.h"
 
@@ -37,9 +33,8 @@
 }
 
 IOSChromeAffiliationServiceFactory::IOSChromeAffiliationServiceFactory()
-    : BrowserStateKeyedServiceFactory(
-          "AffiliationService",
-          BrowserStateDependencyManager::GetInstance()) {}
+    : ProfileKeyedServiceFactoryIOS("AffiliationService",
+                                    ProfileSelection::kRedirectedInIncognito) {}
 
 IOSChromeAffiliationServiceFactory::~IOSChromeAffiliationServiceFactory() =
     default;
@@ -61,8 +56,3 @@
 
   return affiliation_service;
 }
-
-web::BrowserState* IOSChromeAffiliationServiceFactory::GetBrowserStateToUse(
-    web::BrowserState* context) const {
-  return GetBrowserStateRedirectedInIncognito(context);
-}
diff --git a/ios/chrome/browser/autofill/model/address_normalizer_factory.h b/ios/chrome/browser/autofill/model/address_normalizer_factory.h
index 1382b09..fda9a85 100644
--- a/ios/chrome/browser/autofill/model/address_normalizer_factory.h
+++ b/ios/chrome/browser/autofill/model/address_normalizer_factory.h
@@ -6,7 +6,7 @@
 #define IOS_CHROME_BROWSER_AUTOFILL_MODEL_ADDRESS_NORMALIZER_FACTORY_H_
 
 #include "base/no_destructor.h"
-#include "components/autofill/core/browser/address_normalizer_impl.h"
+#include "components/autofill/core/browser/data_quality/addresses/address_normalizer_impl.h"
 
 namespace autofill {
 
diff --git a/ios/chrome/browser/autofill/ui_bundled/address_editor/autofill_profile_edit_mediator.mm b/ios/chrome/browser/autofill/ui_bundled/address_editor/autofill_profile_edit_mediator.mm
index 783c2a0..f4a297c 100644
--- a/ios/chrome/browser/autofill/ui_bundled/address_editor/autofill_profile_edit_mediator.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/address_editor/autofill_profile_edit_mediator.mm
@@ -8,10 +8,10 @@
 #import "base/strings/sys_string_conversions.h"
 #import "components/autofill/core/browser/address_data_manager.h"
 #import "components/autofill/core/browser/autofill_address_util.h"
-#import "components/autofill/core/browser/autofill_data_util.h"
+#import "components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.h"
+#import "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #import "components/autofill/core/browser/geo/autofill_country.h"
 #import "components/autofill/core/browser/personal_data_manager.h"
-#import "components/autofill/core/browser/profile_requirement_utils.h"
 #import "components/autofill/core/browser/ui/country_combobox_model.h"
 #import "components/autofill/ios/common/features.h"
 #import "ios/chrome/browser/autofill/ui_bundled/address_editor/autofill_profile_edit_consumer.h"
diff --git a/ios/chrome/browser/autofill/ui_bundled/chrome_autofill_client_ios.mm b/ios/chrome/browser/autofill/ui_bundled/chrome_autofill_client_ios.mm
index dc09428..29b9b9c 100644
--- a/ios/chrome/browser/autofill/ui_bundled/chrome_autofill_client_ios.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/chrome_autofill_client_ios.mm
@@ -143,8 +143,8 @@
 ChromeAutofillClientIOS::GetCrowdsourcingManager() {
   if (!crowdsourcing_manager_) {
     // Lazy initialization to avoid virtual function calls in the constructor.
-    crowdsourcing_manager_ = std::make_unique<AutofillCrowdsourcingManager>(
-        this, GetChannel(), GetLogManager());
+    crowdsourcing_manager_ =
+        std::make_unique<AutofillCrowdsourcingManager>(this, GetChannel());
   }
   return *crowdsourcing_manager_;
 }
diff --git a/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_suggestion_label.mm b/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_suggestion_label.mm
index ade4026..d2e97346 100644
--- a/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_suggestion_label.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_suggestion_label.mm
@@ -6,12 +6,13 @@
 
 #import <QuartzCore/QuartzCore.h>
 #import <stddef.h>
+
 #import <cmath>
 
 #import "base/strings/string_number_conversions.h"
 #import "base/strings/sys_string_conversions.h"
-#import "components/autofill/core/browser/autofill_data_util.h"
 #import "components/autofill/core/browser/data_model/credit_card.h"
+#import "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #import "components/autofill/ios/browser/form_suggestion.h"
 #import "components/password_manager/ios/shared_password_controller.h"
 #import "ios/chrome/browser/autofill/model/form_suggestion_constants.h"
diff --git a/ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_address_mediator.mm b/ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_address_mediator.mm
index 05335f81..f0ffc67 100644
--- a/ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_address_mediator.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_address_mediator.mm
@@ -8,8 +8,8 @@
 #import "base/metrics/user_metrics.h"
 #import "base/strings/sys_string_conversions.h"
 #import "components/autofill/core/browser/data_model/autofill_profile.h"
+#import "components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.h"
 #import "components/autofill/core/browser/personal_data_manager.h"
-#import "components/autofill/core/browser/profile_requirement_utils.h"
 #import "components/autofill/ios/browser/personal_data_manager_observer_bridge.h"
 #import "ios/chrome/browser/autofill/ui_bundled/manual_fill/address_consumer.h"
 #import "ios/chrome/browser/autofill/ui_bundled/manual_fill/address_list_delegate.h"
diff --git a/ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_credit_card+CreditCard.mm b/ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_credit_card+CreditCard.mm
index 04eb2134..2a1f29dc 100644
--- a/ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_credit_card+CreditCard.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_credit_card+CreditCard.mm
@@ -4,9 +4,9 @@
 
 #import "base/strings/sys_string_conversions.h"
 #import "base/strings/utf_string_conversions.h"
-#import "components/autofill/core/browser/autofill_data_util.h"
 #import "components/autofill/core/browser/data_model/credit_card.h"
-#import "components/autofill/core/browser/validation.h"
+#import "components/autofill/core/browser/data_quality/autofill_data_util.h"
+#import "components/autofill/core/browser/data_quality/validation.h"
 #import "components/autofill/core/common/credit_card_number_validation.h"
 #import "components/autofill/ios/browser/credit_card_util.h"
 #import "ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_credit_card+CreditCard.h"
diff --git a/ios/chrome/browser/bookmarks/model/BUILD.gn b/ios/chrome/browser/bookmarks/model/BUILD.gn
index c759ceb9..9d0cfb28 100644
--- a/ios/chrome/browser/bookmarks/model/BUILD.gn
+++ b/ios/chrome/browser/bookmarks/model/BUILD.gn
@@ -32,8 +32,6 @@
     "//components/favicon/core",
     "//components/favicon_base",
     "//components/history/core/browser",
-    "//components/keyed_service/core",
-    "//components/keyed_service/ios",
     "//components/power_bookmarks/core",
     "//components/prefs",
     "//components/sync_bookmarks",
diff --git a/ios/chrome/browser/bookmarks/model/managed_bookmark_service_factory.h b/ios/chrome/browser/bookmarks/model/managed_bookmark_service_factory.h
index 9f5f39b..dfe1ffe 100644
--- a/ios/chrome/browser/bookmarks/model/managed_bookmark_service_factory.h
+++ b/ios/chrome/browser/bookmarks/model/managed_bookmark_service_factory.h
@@ -6,9 +6,7 @@
 #define IOS_CHROME_BROWSER_BOOKMARKS_MODEL_MANAGED_BOOKMARK_SERVICE_FACTORY_H_
 
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
-
-class ProfileIOS;
+#import "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
 namespace bookmarks {
 class ManagedBookmarkService;
@@ -16,15 +14,11 @@
 
 // Singleton that owns all ManagedBookmarkService and associates them with
 // profiles.
-class ManagedBookmarkServiceFactory : public BrowserStateKeyedServiceFactory {
+class ManagedBookmarkServiceFactory : public ProfileKeyedServiceFactoryIOS {
  public:
   static bookmarks::ManagedBookmarkService* GetForProfile(ProfileIOS* profile);
   static ManagedBookmarkServiceFactory* GetInstance();
 
-  ManagedBookmarkServiceFactory(const ManagedBookmarkServiceFactory&) = delete;
-  ManagedBookmarkServiceFactory& operator=(
-      const ManagedBookmarkServiceFactory&) = delete;
-
   // Returns the default factory, useful in tests where it's null by default.
   static TestingFactory GetDefaultFactory();
 
@@ -37,7 +31,6 @@
   // BrowserStateKeyedServiceFactory implementation.
   std::unique_ptr<KeyedService> BuildServiceInstanceFor(
       web::BrowserState* context) const override;
-  bool ServiceIsNULLWhileTesting() const override;
 };
 
 #endif  // IOS_CHROME_BROWSER_BOOKMARKS_MODEL_MANAGED_BOOKMARK_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/bookmarks/model/managed_bookmark_service_factory.mm b/ios/chrome/browser/bookmarks/model/managed_bookmark_service_factory.mm
index 11f752fa..9e40ec2 100644
--- a/ios/chrome/browser/bookmarks/model/managed_bookmark_service_factory.mm
+++ b/ios/chrome/browser/bookmarks/model/managed_bookmark_service_factory.mm
@@ -7,7 +7,6 @@
 #import "base/no_destructor.h"
 #import "base/strings/sys_string_conversions.h"
 #import "components/bookmarks/managed/managed_bookmark_service.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service_factory.h"
@@ -48,8 +47,9 @@
 // static
 bookmarks::ManagedBookmarkService* ManagedBookmarkServiceFactory::GetForProfile(
     ProfileIOS* profile) {
-  return static_cast<bookmarks::ManagedBookmarkService*>(
-      GetInstance()->GetServiceForBrowserState(profile, true));
+  return GetInstance()
+      ->GetServiceForProfileAs<bookmarks::ManagedBookmarkService>(
+          profile, /*create=*/true);
 }
 
 // static
@@ -65,9 +65,8 @@
 }
 
 ManagedBookmarkServiceFactory::ManagedBookmarkServiceFactory()
-    : BrowserStateKeyedServiceFactory(
-          "ManagedBookmarkService",
-          BrowserStateDependencyManager::GetInstance()) {}
+    : ProfileKeyedServiceFactoryIOS("ManagedBookmarkService",
+                                    TestingCreation::kNoServiceForTests) {}
 
 ManagedBookmarkServiceFactory::~ManagedBookmarkServiceFactory() {}
 
@@ -76,7 +75,3 @@
     web::BrowserState* context) const {
   return BuildManagedBookmarkModel(context);
 }
-
-bool ManagedBookmarkServiceFactory::ServiceIsNULLWhileTesting() const {
-  return true;
-}
diff --git a/ios/chrome/browser/consent_auditor/model/BUILD.gn b/ios/chrome/browser/consent_auditor/model/BUILD.gn
index 8969c43..b162c51 100644
--- a/ios/chrome/browser/consent_auditor/model/BUILD.gn
+++ b/ios/chrome/browser/consent_auditor/model/BUILD.gn
@@ -10,12 +10,12 @@
   deps = [
     "//base",
     "//components/consent_auditor",
-    "//components/keyed_service/ios",
     "//components/pref_registry",
     "//components/sync/model",
     "//components/version_info",
     "//ios/chrome/browser/shared/model/application_context",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
     "//ios/chrome/browser/sync/model:data_type_store_service_factory",
     "//ios/chrome/common",
     "//ios/web/public",
diff --git a/ios/chrome/browser/consent_auditor/model/consent_auditor_factory.h b/ios/chrome/browser/consent_auditor/model/consent_auditor_factory.h
index feaafc9..4ebbd7a 100644
--- a/ios/chrome/browser/consent_auditor/model/consent_auditor_factory.h
+++ b/ios/chrome/browser/consent_auditor/model/consent_auditor_factory.h
@@ -6,9 +6,7 @@
 #define IOS_CHROME_BROWSER_CONSENT_AUDITOR_MODEL_CONSENT_AUDITOR_FACTORY_H_
 
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
-
-class ProfileIOS;
+#import "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
 namespace consent_auditor {
 class ConsentAuditor;
@@ -16,16 +14,11 @@
 
 // Singleton that owns all ConsentAuditors and associates them with
 // ProfileIOS.
-class ConsentAuditorFactory : public BrowserStateKeyedServiceFactory {
+class ConsentAuditorFactory : public ProfileKeyedServiceFactoryIOS {
  public:
   static consent_auditor::ConsentAuditor* GetForProfile(ProfileIOS* profile);
-  static consent_auditor::ConsentAuditor* GetForProfileIfExists(
-      ProfileIOS* profile);
   static ConsentAuditorFactory* GetInstance();
 
-  ConsentAuditorFactory(const ConsentAuditorFactory&) = delete;
-  ConsentAuditorFactory& operator=(const ConsentAuditorFactory&) = delete;
-
  private:
   friend class base::NoDestructor<ConsentAuditorFactory>;
 
diff --git a/ios/chrome/browser/consent_auditor/model/consent_auditor_factory.mm b/ios/chrome/browser/consent_auditor/model/consent_auditor_factory.mm
index 035b5ac..fe8a080 100644
--- a/ios/chrome/browser/consent_auditor/model/consent_auditor_factory.mm
+++ b/ios/chrome/browser/consent_auditor/model/consent_auditor_factory.mm
@@ -16,7 +16,6 @@
 #import "components/consent_auditor/consent_auditor_impl.h"
 #import "components/consent_auditor/consent_sync_bridge.h"
 #import "components/consent_auditor/consent_sync_bridge_impl.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "components/sync/base/report_unrecoverable_error.h"
 #import "components/sync/model/client_tag_based_data_type_processor.h"
 #import "components/sync/model/data_type_store_service.h"
@@ -30,15 +29,8 @@
 // static
 consent_auditor::ConsentAuditor* ConsentAuditorFactory::GetForProfile(
     ProfileIOS* profile) {
-  return static_cast<consent_auditor::ConsentAuditor*>(
-      GetInstance()->GetServiceForBrowserState(profile, true));
-}
-
-// static
-consent_auditor::ConsentAuditor* ConsentAuditorFactory::GetForProfileIfExists(
-    ProfileIOS* profile) {
-  return static_cast<consent_auditor::ConsentAuditor*>(
-      GetInstance()->GetServiceForBrowserState(profile, false));
+  return GetInstance()->GetServiceForProfileAs<consent_auditor::ConsentAuditor>(
+      profile, /*create=*/true);
 }
 
 // static
@@ -48,9 +40,7 @@
 }
 
 ConsentAuditorFactory::ConsentAuditorFactory()
-    : BrowserStateKeyedServiceFactory(
-          "ConsentAuditor",
-          BrowserStateDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactoryIOS("ConsentAuditor") {
   DependsOn(DataTypeStoreServiceFactory::GetInstance());
 }
 
@@ -73,9 +63,9 @@
       std::make_unique<consent_auditor::ConsentSyncBridgeImpl>(
           std::move(store_factory), std::move(change_processor));
 
+  // The locale doesn't change at runtime, so we can pass it directly.
   return std::make_unique<consent_auditor::ConsentAuditorImpl>(
       std::move(consent_sync_bridge),
-      // The locale doesn't change at runtime, so we can pass it directly.
       GetApplicationContext()->GetApplicationLocale(),
       base::DefaultClock::GetInstance());
 }
diff --git a/ios/chrome/browser/contextual_panel/sample/model/BUILD.gn b/ios/chrome/browser/contextual_panel/sample/model/BUILD.gn
index 9f7aaef..57698e6 100644
--- a/ios/chrome/browser/contextual_panel/sample/model/BUILD.gn
+++ b/ios/chrome/browser/contextual_panel/sample/model/BUILD.gn
@@ -14,10 +14,10 @@
     "//base",
     "//components/feature_engagement/public",
     "//components/keyed_service/core",
-    "//components/keyed_service/ios",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser/contextual_panel/model:public",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
     "//ios/chrome/browser/shared/model/url",
     "//ios/chrome/browser/shared/ui/symbols:buildflags",
     "//ios/web/public",
diff --git a/ios/chrome/browser/contextual_panel/sample/model/sample_panel_model_factory.h b/ios/chrome/browser/contextual_panel/sample/model/sample_panel_model_factory.h
index 6147693..e4b00c0 100644
--- a/ios/chrome/browser/contextual_panel/sample/model/sample_panel_model_factory.h
+++ b/ios/chrome/browser/contextual_panel/sample/model/sample_panel_model_factory.h
@@ -6,21 +6,17 @@
 #define IOS_CHROME_BROWSER_CONTEXTUAL_PANEL_SAMPLE_MODEL_SAMPLE_PANEL_MODEL_FACTORY_H_
 
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
+#import "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
-class ProfileIOS;
 class SamplePanelModel;
 
 // Singleton that owns all SamplePanelModels and associates them with
 // profiles.
-class SamplePanelModelFactory : public BrowserStateKeyedServiceFactory {
+class SamplePanelModelFactory : public ProfileKeyedServiceFactoryIOS {
  public:
   static SamplePanelModel* GetForProfile(ProfileIOS* profile);
   static SamplePanelModelFactory* GetInstance();
 
-  SamplePanelModelFactory(const SamplePanelModelFactory&) = delete;
-  SamplePanelModelFactory& operator=(const SamplePanelModelFactory&) = delete;
-
  private:
   friend class base::NoDestructor<SamplePanelModelFactory>;
 
diff --git a/ios/chrome/browser/contextual_panel/sample/model/sample_panel_model_factory.mm b/ios/chrome/browser/contextual_panel/sample/model/sample_panel_model_factory.mm
index 7177db2a..f1afefb 100644
--- a/ios/chrome/browser/contextual_panel/sample/model/sample_panel_model_factory.mm
+++ b/ios/chrome/browser/contextual_panel/sample/model/sample_panel_model_factory.mm
@@ -5,14 +5,13 @@
 #import "ios/chrome/browser/contextual_panel/sample/model/sample_panel_model_factory.h"
 
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "ios/chrome/browser/contextual_panel/sample/model/sample_panel_model.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 
 // static
 SamplePanelModel* SamplePanelModelFactory::GetForProfile(ProfileIOS* profile) {
-  return static_cast<SamplePanelModel*>(
-      GetInstance()->GetServiceForBrowserState(profile, true));
+  return GetInstance()->GetServiceForProfileAs<SamplePanelModel>(
+      profile, /*create=*/true);
 }
 
 // static
@@ -22,9 +21,7 @@
 }
 
 SamplePanelModelFactory::SamplePanelModelFactory()
-    : BrowserStateKeyedServiceFactory(
-          "SamplePanelModel",
-          BrowserStateDependencyManager::GetInstance()) {}
+    : ProfileKeyedServiceFactoryIOS("SamplePanelModel") {}
 
 SamplePanelModelFactory::~SamplePanelModelFactory() {}
 
diff --git a/ios/chrome/browser/discover_feed/model/BUILD.gn b/ios/chrome/browser/discover_feed/model/BUILD.gn
index ea0a7b7..663dcb3 100644
--- a/ios/chrome/browser/discover_feed/model/BUILD.gn
+++ b/ios/chrome/browser/discover_feed/model/BUILD.gn
@@ -47,12 +47,12 @@
   deps = [
     ":model",
     "//base",
-    "//components/keyed_service/ios",
     "//components/signin/public/identity_manager",
     "//ios/chrome/browser/ntp/shared/metrics",
     "//ios/chrome/browser/search_engines/model:template_url_service_factory",
     "//ios/chrome/browser/shared/model/application_context",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
     "//ios/chrome/browser/signin/model",
     "//ios/chrome/browser/signin/model:authentication_service_factory",
     "//ios/chrome/browser/sync/model",
diff --git a/ios/chrome/browser/discover_feed/model/discover_feed_service_factory.h b/ios/chrome/browser/discover_feed/model/discover_feed_service_factory.h
index 4f37a83..92a1295 100644
--- a/ios/chrome/browser/discover_feed/model/discover_feed_service_factory.h
+++ b/ios/chrome/browser/discover_feed/model/discover_feed_service_factory.h
@@ -6,24 +6,20 @@
 #define IOS_CHROME_BROWSER_DISCOVER_FEED_MODEL_DISCOVER_FEED_SERVICE_FACTORY_H_
 
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
+#import "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
 class DiscoverFeedService;
 class ProfileIOS;
 
 // Singleton that owns all DiscoverFeedServices and associates them with
 // Profile.
-class DiscoverFeedServiceFactory : public BrowserStateKeyedServiceFactory {
+class DiscoverFeedServiceFactory : public ProfileKeyedServiceFactoryIOS {
  public:
   static DiscoverFeedService* GetForProfile(ProfileIOS* profile);
   static DiscoverFeedService* GetForProfileIfExists(ProfileIOS* profile);
 
   static DiscoverFeedServiceFactory* GetInstance();
 
-  DiscoverFeedServiceFactory(const DiscoverFeedServiceFactory&) = delete;
-  DiscoverFeedServiceFactory& operator=(const DiscoverFeedServiceFactory&) =
-      delete;
-
  private:
   friend class base::NoDestructor<DiscoverFeedServiceFactory>;
 
diff --git a/ios/chrome/browser/discover_feed/model/discover_feed_service_factory.mm b/ios/chrome/browser/discover_feed/model/discover_feed_service_factory.mm
index afbe517..8a137339 100644
--- a/ios/chrome/browser/discover_feed/model/discover_feed_service_factory.mm
+++ b/ios/chrome/browser/discover_feed/model/discover_feed_service_factory.mm
@@ -4,8 +4,6 @@
 
 #import "ios/chrome/browser/discover_feed/model/discover_feed_service_factory.h"
 
-#import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "ios/chrome/browser/discover_feed/model/discover_feed_configuration.h"
 #import "ios/chrome/browser/discover_feed/model/discover_feed_service.h"
 #import "ios/chrome/browser/ntp/shared/metrics/feed_metrics_recorder.h"
@@ -20,15 +18,15 @@
 // static
 DiscoverFeedService* DiscoverFeedServiceFactory::GetForProfile(
     ProfileIOS* profile) {
-  return static_cast<DiscoverFeedService*>(
-      GetInstance()->GetServiceForBrowserState(profile, /*create=*/true));
+  return GetInstance()->GetServiceForProfileAs<DiscoverFeedService>(
+      profile, /*create=*/true);
 }
 
 // static
 DiscoverFeedService* DiscoverFeedServiceFactory::GetForProfileIfExists(
     ProfileIOS* profile) {
-  return static_cast<DiscoverFeedService*>(
-      GetInstance()->GetServiceForBrowserState(profile, /*create=*/false));
+  return GetInstance()->GetServiceForProfileAs<DiscoverFeedService>(
+      profile, /*create=*/false);
 }
 
 // static
@@ -38,9 +36,7 @@
 }
 
 DiscoverFeedServiceFactory::DiscoverFeedServiceFactory()
-    : BrowserStateKeyedServiceFactory(
-          "DiscoverFeedService",
-          BrowserStateDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactoryIOS("DiscoverFeedService") {
   DependsOn(AuthenticationServiceFactory::GetInstance());
   DependsOn(IdentityManagerFactory::GetInstance());
   DependsOn(ios::TemplateURLServiceFactory::GetInstance());
diff --git a/ios/chrome/browser/external_files/model/BUILD.gn b/ios/chrome/browser/external_files/model/BUILD.gn
index cfdef7aa..4a43888 100644
--- a/ios/chrome/browser/external_files/model/BUILD.gn
+++ b/ios/chrome/browser/external_files/model/BUILD.gn
@@ -14,12 +14,12 @@
     "//base",
     "//components/bookmarks/browser",
     "//components/keyed_service/core",
-    "//components/keyed_service/ios",
     "//components/sessions",
     "//ios/chrome/browser/bookmarks/model",
     "//ios/chrome/browser/sessions/model",
     "//ios/chrome/browser/shared/model/browser",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
     "//ios/chrome/browser/shared/model/url",
     "//ios/chrome/browser/shared/model/web_state_list",
   ]
diff --git a/ios/chrome/browser/external_files/model/external_file_remover_factory.h b/ios/chrome/browser/external_files/model/external_file_remover_factory.h
index 3dd80b2..9fea847e 100644
--- a/ios/chrome/browser/external_files/model/external_file_remover_factory.h
+++ b/ios/chrome/browser/external_files/model/external_file_remover_factory.h
@@ -5,10 +5,8 @@
 #ifndef IOS_CHROME_BROWSER_EXTERNAL_FILES_MODEL_EXTERNAL_FILE_REMOVER_FACTORY_H_
 #define IOS_CHROME_BROWSER_EXTERNAL_FILES_MODEL_EXTERNAL_FILE_REMOVER_FACTORY_H_
 
-#import <memory>
-
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
+#import "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
 class ExternalFileRemover;
 class ProfileIOS;
@@ -16,15 +14,11 @@
 // Singleton that owns all `ExternalFileRemover` and associates them with
 // profiles. Listens for the `ProfileIOS`'s destruction notification and
 // cleans up the associated `ExternalFileRemover`.
-class ExternalFileRemoverFactory : public BrowserStateKeyedServiceFactory {
+class ExternalFileRemoverFactory : public ProfileKeyedServiceFactoryIOS {
  public:
   static ExternalFileRemover* GetForProfile(ProfileIOS* profile);
   static ExternalFileRemoverFactory* GetInstance();
 
-  ExternalFileRemoverFactory(const ExternalFileRemoverFactory&) = delete;
-  ExternalFileRemoverFactory& operator=(const ExternalFileRemoverFactory&) =
-      delete;
-
  private:
   friend class base::NoDestructor<ExternalFileRemoverFactory>;
 
diff --git a/ios/chrome/browser/external_files/model/external_file_remover_factory.mm b/ios/chrome/browser/external_files/model/external_file_remover_factory.mm
index e00e871..005694037 100644
--- a/ios/chrome/browser/external_files/model/external_file_remover_factory.mm
+++ b/ios/chrome/browser/external_files/model/external_file_remover_factory.mm
@@ -7,8 +7,6 @@
 #import <memory>
 #import <utility>
 
-#import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "ios/chrome/browser/external_files/model/external_file_remover_impl.h"
 #import "ios/chrome/browser/sessions/model/ios_chrome_tab_restore_service_factory.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
@@ -16,8 +14,8 @@
 // static
 ExternalFileRemover* ExternalFileRemoverFactory::GetForProfile(
     ProfileIOS* profile) {
-  return static_cast<ExternalFileRemover*>(
-      GetInstance()->GetServiceForBrowserState(profile, true));
+  return GetInstance()->GetServiceForProfileAs<ExternalFileRemover>(
+      profile, /*create=*/true);
 }
 
 // static
@@ -27,13 +25,11 @@
 }
 
 ExternalFileRemoverFactory::ExternalFileRemoverFactory()
-    : BrowserStateKeyedServiceFactory(
-          "ExternalFileRemoverService",
-          BrowserStateDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactoryIOS("ExternalFileRemoverService") {
   DependsOn(IOSChromeTabRestoreServiceFactory::GetInstance());
 }
 
-ExternalFileRemoverFactory::~ExternalFileRemoverFactory() {}
+ExternalFileRemoverFactory::~ExternalFileRemoverFactory() = default;
 
 std::unique_ptr<KeyedService>
 ExternalFileRemoverFactory::BuildServiceInstanceFor(
diff --git a/ios/chrome/browser/favicon/model/ios_chrome_favicon_loader_factory.h b/ios/chrome/browser/favicon/model/ios_chrome_favicon_loader_factory.h
index 27912ac..111550f3 100644
--- a/ios/chrome/browser/favicon/model/ios_chrome_favicon_loader_factory.h
+++ b/ios/chrome/browser/favicon/model/ios_chrome_favicon_loader_factory.h
@@ -5,17 +5,15 @@
 #ifndef IOS_CHROME_BROWSER_FAVICON_MODEL_IOS_CHROME_FAVICON_LOADER_FACTORY_H_
 #define IOS_CHROME_BROWSER_FAVICON_MODEL_IOS_CHROME_FAVICON_LOADER_FACTORY_H_
 
-#import <memory>
-
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
+#import "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
 class FaviconLoader;
 class ProfileIOS;
 
 // Singleton that owns all FaviconLoaders and associates them with
 // ProfileIOS.
-class IOSChromeFaviconLoaderFactory : public BrowserStateKeyedServiceFactory {
+class IOSChromeFaviconLoaderFactory : public ProfileKeyedServiceFactoryIOS {
  public:
   static FaviconLoader* GetForProfile(ProfileIOS* profile);
   static FaviconLoader* GetForProfileIfExists(ProfileIOS* profile);
@@ -25,10 +23,6 @@
   // with SetTestingFactory to use the FaviconService instance during testing.
   static TestingFactory GetDefaultFactory();
 
-  IOSChromeFaviconLoaderFactory(const IOSChromeFaviconLoaderFactory&) = delete;
-  IOSChromeFaviconLoaderFactory& operator=(
-      const IOSChromeFaviconLoaderFactory&) = delete;
-
  private:
   friend class base::NoDestructor<IOSChromeFaviconLoaderFactory>;
 
@@ -38,9 +32,6 @@
   // BrowserStateKeyedServiceFactory implementation.
   std::unique_ptr<KeyedService> BuildServiceInstanceFor(
       web::BrowserState* context) const override;
-  web::BrowserState* GetBrowserStateToUse(
-      web::BrowserState* context) const override;
-  bool ServiceIsNULLWhileTesting() const override;
 };
 
 #endif  // IOS_CHROME_BROWSER_FAVICON_MODEL_IOS_CHROME_FAVICON_LOADER_FACTORY_H_
diff --git a/ios/chrome/browser/favicon/model/ios_chrome_favicon_loader_factory.mm b/ios/chrome/browser/favicon/model/ios_chrome_favicon_loader_factory.mm
index 8d88720c..330780d 100644
--- a/ios/chrome/browser/favicon/model/ios_chrome_favicon_loader_factory.mm
+++ b/ios/chrome/browser/favicon/model/ios_chrome_favicon_loader_factory.mm
@@ -4,12 +4,9 @@
 
 #import "ios/chrome/browser/favicon/model/ios_chrome_favicon_loader_factory.h"
 
-#import "base/no_destructor.h"
 #import "components/keyed_service/core/service_access_type.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "ios/chrome/browser/favicon/model/favicon_loader.h"
 #import "ios/chrome/browser/favicon/model/ios_chrome_large_icon_service_factory.h"
-#import "ios/chrome/browser/shared/model/browser_state/browser_state_otr_helper.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 
 namespace {
@@ -25,15 +22,15 @@
 // static
 FaviconLoader* IOSChromeFaviconLoaderFactory::GetForProfileIfExists(
     ProfileIOS* profile) {
-  return static_cast<FaviconLoader*>(
-      GetInstance()->GetServiceForBrowserState(profile, false));
+  return GetInstance()->GetServiceForProfileAs<FaviconLoader>(profile,
+                                                              /*create=*/false);
 }
 
 // static
 FaviconLoader* IOSChromeFaviconLoaderFactory::GetForProfile(
     ProfileIOS* profile) {
-  return static_cast<FaviconLoader*>(
-      GetInstance()->GetServiceForBrowserState(profile, true));
+  return GetInstance()->GetServiceForProfileAs<FaviconLoader>(profile,
+                                                              /*create=*/true);
 }
 
 // static
@@ -49,25 +46,16 @@
 }
 
 IOSChromeFaviconLoaderFactory::IOSChromeFaviconLoaderFactory()
-    : BrowserStateKeyedServiceFactory(
-          "FaviconLoader",
-          BrowserStateDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactoryIOS("FaviconLoader",
+                                    ProfileSelection::kRedirectedInIncognito,
+                                    TestingCreation::kNoServiceForTests) {
   DependsOn(IOSChromeLargeIconServiceFactory::GetInstance());
 }
 
-IOSChromeFaviconLoaderFactory::~IOSChromeFaviconLoaderFactory() {}
+IOSChromeFaviconLoaderFactory::~IOSChromeFaviconLoaderFactory() = default;
 
 std::unique_ptr<KeyedService>
 IOSChromeFaviconLoaderFactory::BuildServiceInstanceFor(
     web::BrowserState* context) const {
   return BuildFaviconLoader(context);
 }
-
-web::BrowserState* IOSChromeFaviconLoaderFactory::GetBrowserStateToUse(
-    web::BrowserState* context) const {
-  return GetBrowserStateRedirectedInIncognito(context);
-}
-
-bool IOSChromeFaviconLoaderFactory::ServiceIsNULLWhileTesting() const {
-  return true;
-}
diff --git a/ios/chrome/browser/favicon/model/ios_chrome_large_icon_service_factory.cc b/ios/chrome/browser/favicon/model/ios_chrome_large_icon_service_factory.cc
index 62860b4..4dffd3c 100644
--- a/ios/chrome/browser/favicon/model/ios_chrome_large_icon_service_factory.cc
+++ b/ios/chrome/browser/favicon/model/ios_chrome_large_icon_service_factory.cc
@@ -5,14 +5,11 @@
 #include "ios/chrome/browser/favicon/model/ios_chrome_large_icon_service_factory.h"
 
 #include "base/functional/bind.h"
-#include "base/no_destructor.h"
 #include "components/favicon/core/large_icon_service_impl.h"
 #include "components/image_fetcher/core/image_fetcher_impl.h"
 #include "components/image_fetcher/ios/ios_image_decoder_impl.h"
 #include "components/keyed_service/core/service_access_type.h"
-#include "components/keyed_service/ios/browser_state_dependency_manager.h"
 #include "ios/chrome/browser/favicon/model/favicon_service_factory.h"
-#include "ios/chrome/browser/shared/model/browser_state/browser_state_otr_helper.h"
 #include "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
@@ -41,8 +38,8 @@
 // static
 favicon::LargeIconService* IOSChromeLargeIconServiceFactory::GetForProfile(
     ProfileIOS* profile) {
-  return static_cast<favicon::LargeIconService*>(
-      GetInstance()->GetServiceForBrowserState(profile, true));
+  return GetInstance()->GetServiceForProfileAs<favicon::LargeIconService>(
+      profile, /*create=*/true);
 }
 
 // static
@@ -59,25 +56,16 @@
 }
 
 IOSChromeLargeIconServiceFactory::IOSChromeLargeIconServiceFactory()
-    : BrowserStateKeyedServiceFactory(
-          "LargeIconService",
-          BrowserStateDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactoryIOS("LargeIconService",
+                                    ProfileSelection::kOwnInstanceInIncognito,
+                                    TestingCreation::kNoServiceForTests) {
   DependsOn(ios::FaviconServiceFactory::GetInstance());
 }
 
-IOSChromeLargeIconServiceFactory::~IOSChromeLargeIconServiceFactory() {}
+IOSChromeLargeIconServiceFactory::~IOSChromeLargeIconServiceFactory() = default;
 
 std::unique_ptr<KeyedService>
 IOSChromeLargeIconServiceFactory::BuildServiceInstanceFor(
     web::BrowserState* context) const {
   return BuildLargeIconService(context);
 }
-
-web::BrowserState* IOSChromeLargeIconServiceFactory::GetBrowserStateToUse(
-    web::BrowserState* context) const {
-  return GetBrowserStateOwnInstanceInIncognito(context);
-}
-
-bool IOSChromeLargeIconServiceFactory::ServiceIsNULLWhileTesting() const {
-  return true;
-}
diff --git a/ios/chrome/browser/favicon/model/ios_chrome_large_icon_service_factory.h b/ios/chrome/browser/favicon/model/ios_chrome_large_icon_service_factory.h
index b2fa047e..9be8a489 100644
--- a/ios/chrome/browser/favicon/model/ios_chrome_large_icon_service_factory.h
+++ b/ios/chrome/browser/favicon/model/ios_chrome_large_icon_service_factory.h
@@ -5,10 +5,8 @@
 #ifndef IOS_CHROME_BROWSER_FAVICON_MODEL_IOS_CHROME_LARGE_ICON_SERVICE_FACTORY_H_
 #define IOS_CHROME_BROWSER_FAVICON_MODEL_IOS_CHROME_LARGE_ICON_SERVICE_FACTORY_H_
 
-#import <memory>
-
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
+#import "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
 class KeyedService;
 class ProfileIOS;
@@ -19,8 +17,7 @@
 
 // Singleton that owns all LargeIconService and associates them with
 // ProfileIOS.
-class IOSChromeLargeIconServiceFactory
-    : public BrowserStateKeyedServiceFactory {
+class IOSChromeLargeIconServiceFactory : public ProfileKeyedServiceFactoryIOS {
  public:
   static favicon::LargeIconService* GetForProfile(ProfileIOS* profile);
 
@@ -30,11 +27,6 @@
   // registered with SetTestingFactory to use real instances during testing.
   static TestingFactory GetDefaultFactory();
 
-  IOSChromeLargeIconServiceFactory(const IOSChromeLargeIconServiceFactory&) =
-      delete;
-  IOSChromeLargeIconServiceFactory& operator=(
-      const IOSChromeLargeIconServiceFactory&) = delete;
-
  private:
   friend class base::NoDestructor<IOSChromeLargeIconServiceFactory>;
 
@@ -44,9 +36,6 @@
   // BrowserStateKeyedServiceFactory implementation.
   std::unique_ptr<KeyedService> BuildServiceInstanceFor(
       web::BrowserState* context) const override;
-  web::BrowserState* GetBrowserStateToUse(
-      web::BrowserState* context) const override;
-  bool ServiceIsNULLWhileTesting() const override;
 };
 
 #endif  // IOS_CHROME_BROWSER_FAVICON_MODEL_IOS_CHROME_LARGE_ICON_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/first_run/ui_bundled/BUILD.gn b/ios/chrome/browser/first_run/ui_bundled/BUILD.gn
index 5709b749..b965ed0 100644
--- a/ios/chrome/browser/first_run/ui_bundled/BUILD.gn
+++ b/ios/chrome/browser/first_run/ui_bundled/BUILD.gn
@@ -62,6 +62,7 @@
     "//ios/chrome/browser/shared/ui/util",
     "//ios/chrome/browser/shared/ui/util:terms_util",
     "//ios/chrome/browser/ui/authentication/history_sync",
+    "//ios/chrome/browser/ui/authentication/signin:interruptible_chrome_coordinator",
     "//ios/public/provider/chrome/browser/signin:choice_api",
     "//ui/base",
     "//ui/gfx",
diff --git a/ios/chrome/browser/first_run/ui_bundled/signin/signin_screen_coordinator.mm b/ios/chrome/browser/first_run/ui_bundled/signin/signin_screen_coordinator.mm
index b5712e5..670abe3 100644
--- a/ios/chrome/browser/first_run/ui_bundled/signin/signin_screen_coordinator.mm
+++ b/ios/chrome/browser/first_run/ui_bundled/signin/signin_screen_coordinator.mm
@@ -29,6 +29,7 @@
 #import "ios/chrome/browser/ui/authentication/authentication_flow.h"
 #import "ios/chrome/browser/ui/authentication/identity_chooser/identity_chooser_coordinator.h"
 #import "ios/chrome/browser/ui/authentication/identity_chooser/identity_chooser_coordinator_delegate.h"
+#import "ios/chrome/browser/ui/authentication/signin/interruptible_chrome_coordinator.h"
 #import "ios/chrome/browser/ui/authentication/signin/signin_constants.h"
 #import "ios/chrome/browser/ui/authentication/signin/signin_coordinator.h"
 
@@ -147,8 +148,18 @@
 - (void)interruptWithAction:(SigninCoordinatorInterrupt)action
                  completion:(ProceduralBlock)completion {
   if (self.addAccountSigninCoordinator) {
-    [self.addAccountSigninCoordinator interruptWithAction:action
-                                               completion:completion];
+    if (base::FeatureList::IsEnabled(
+            kIOSInterruptibleChromeStoppedSynchronously)) {
+      [self.addAccountSigninCoordinator interruptWithAction:action
+                                                 completion:nil];
+
+      if (completion) {
+        completion();
+      }
+    } else {
+      [self.addAccountSigninCoordinator interruptWithAction:action
+                                                 completion:completion];
+    }
   } else if (completion) {
     completion();
   }
diff --git a/ios/chrome/browser/gcm/model/BUILD.gn b/ios/chrome/browser/gcm/model/BUILD.gn
index 1b979d8..c13586e 100644
--- a/ios/chrome/browser/gcm/model/BUILD.gn
+++ b/ios/chrome/browser/gcm/model/BUILD.gn
@@ -11,9 +11,9 @@
     "//base",
     "//build:branding_buildflags",
     "//components/gcm_driver",
-    "//components/keyed_service/ios",
     "//ios/chrome/browser/shared/model/application_context",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
     "//ios/chrome/browser/signin/model",
     "//ios/chrome/common",
     "//ios/web",
diff --git a/ios/chrome/browser/gcm/model/ios_chrome_gcm_profile_service_factory.h b/ios/chrome/browser/gcm/model/ios_chrome_gcm_profile_service_factory.h
index 9f8d8b3e..a27f2b4c 100644
--- a/ios/chrome/browser/gcm/model/ios_chrome_gcm_profile_service_factory.h
+++ b/ios/chrome/browser/gcm/model/ios_chrome_gcm_profile_service_factory.h
@@ -9,9 +9,7 @@
 #import <string>
 
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
-
-class ProfileIOS;
+#import "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
 namespace gcm {
 class GCMProfileService;
@@ -19,17 +17,11 @@
 
 // Singleton that owns all GCMProfileService and associates them with
 // profiles.
-class IOSChromeGCMProfileServiceFactory
-    : public BrowserStateKeyedServiceFactory {
+class IOSChromeGCMProfileServiceFactory : public ProfileKeyedServiceFactoryIOS {
  public:
   static gcm::GCMProfileService* GetForProfile(ProfileIOS* profile);
   static IOSChromeGCMProfileServiceFactory* GetInstance();
 
-  IOSChromeGCMProfileServiceFactory(const IOSChromeGCMProfileServiceFactory&) =
-      delete;
-  IOSChromeGCMProfileServiceFactory& operator=(
-      const IOSChromeGCMProfileServiceFactory&) = delete;
-
   // Returns a string like "com.chrome.ios" that should be used as the GCM
   // category when an app_id is sent as a subtype instead of as a category. This
   // string must never change during the lifetime of a Chrome install, since
diff --git a/ios/chrome/browser/gcm/model/ios_chrome_gcm_profile_service_factory.mm b/ios/chrome/browser/gcm/model/ios_chrome_gcm_profile_service_factory.mm
index 71f4841..b32edf84 100644
--- a/ios/chrome/browser/gcm/model/ios_chrome_gcm_profile_service_factory.mm
+++ b/ios/chrome/browser/gcm/model/ios_chrome_gcm_profile_service_factory.mm
@@ -5,7 +5,6 @@
 #import "ios/chrome/browser/gcm/model/ios_chrome_gcm_profile_service_factory.h"
 
 #import "base/functional/bind.h"
-#import "base/memory/ptr_util.h"
 #import "base/memory/ref_counted.h"
 #import "base/no_destructor.h"
 #import "base/task/sequenced_task_runner.h"
@@ -13,7 +12,6 @@
 #import "build/branding_buildflags.h"
 #import "components/gcm_driver/gcm_client_factory.h"
 #import "components/gcm_driver/gcm_profile_service.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/signin/model/identity_manager_factory.h"
@@ -58,8 +56,8 @@
 // static
 gcm::GCMProfileService* IOSChromeGCMProfileServiceFactory::GetForProfile(
     ProfileIOS* profile) {
-  return static_cast<gcm::GCMProfileService*>(
-      GetInstance()->GetServiceForBrowserState(profile, true));
+  return GetInstance()->GetServiceForProfileAs<gcm::GCMProfileService>(
+      profile, /*create=*/true);
 }
 
 // static
@@ -79,9 +77,7 @@
 }
 
 IOSChromeGCMProfileServiceFactory::IOSChromeGCMProfileServiceFactory()
-    : BrowserStateKeyedServiceFactory(
-          "GCMProfileService",
-          BrowserStateDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactoryIOS("GCMProfileService") {
   DependsOn(IdentityManagerFactory::GetInstance());
 }
 
@@ -104,7 +100,6 @@
       GetApplicationContext()->GetNetworkConnectionTracker(), ::GetChannel(),
       GetProductCategoryForSubtypes(),
       IdentityManagerFactory::GetForProfile(profile),
-      base::WrapUnique(new gcm::GCMClientFactory),
-      web::GetUIThreadTaskRunner({}), web::GetIOThreadTaskRunner({}),
-      blocking_task_runner);
+      std::make_unique<gcm::GCMClientFactory>(), web::GetUIThreadTaskRunner({}),
+      web::GetIOThreadTaskRunner({}), blocking_task_runner);
 }
diff --git a/ios/chrome/browser/google/model/BUILD.gn b/ios/chrome/browser/google/model/BUILD.gn
index cb69d46..6a33f5d7 100644
--- a/ios/chrome/browser/google/model/BUILD.gn
+++ b/ios/chrome/browser/google/model/BUILD.gn
@@ -20,12 +20,11 @@
     "//base",
     "//components/image_fetcher/ios",
     "//components/keyed_service/core",
-    "//components/keyed_service/ios",
     "//components/search_engines",
     "//components/search_provider_logos",
     "//ios/chrome/browser/search_engines/model",
-    "//ios/chrome/browser/shared/model/browser_state",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
     "//ios/chrome/browser/signin/model",
     "//ios/web",
     "//net",
diff --git a/ios/chrome/browser/google/model/google_logo_service_factory.h b/ios/chrome/browser/google/model/google_logo_service_factory.h
index f850996..296c831 100644
--- a/ios/chrome/browser/google/model/google_logo_service_factory.h
+++ b/ios/chrome/browser/google/model/google_logo_service_factory.h
@@ -5,10 +5,8 @@
 #ifndef IOS_CHROME_BROWSER_GOOGLE_MODEL_GOOGLE_LOGO_SERVICE_FACTORY_H_
 #define IOS_CHROME_BROWSER_GOOGLE_MODEL_GOOGLE_LOGO_SERVICE_FACTORY_H_
 
-#import <memory>
-
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
+#import "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
 class GoogleLogoService;
 class KeyedService;
@@ -16,14 +14,11 @@
 
 // Singleton that owns all GoogleLogoServices and associates them with
 // profiles.
-class GoogleLogoServiceFactory : public BrowserStateKeyedServiceFactory {
+class GoogleLogoServiceFactory : public ProfileKeyedServiceFactoryIOS {
  public:
   static GoogleLogoService* GetForProfile(ProfileIOS* profile);
   static GoogleLogoServiceFactory* GetInstance();
 
-  GoogleLogoServiceFactory(const GoogleLogoServiceFactory&) = delete;
-  GoogleLogoServiceFactory& operator=(const GoogleLogoServiceFactory&) = delete;
-
  private:
   friend class base::NoDestructor<GoogleLogoServiceFactory>;
 
@@ -33,8 +28,6 @@
   // BrowserStateKeyedServiceFactory implementation.
   std::unique_ptr<KeyedService> BuildServiceInstanceFor(
       web::BrowserState* context) const override;
-  web::BrowserState* GetBrowserStateToUse(
-      web::BrowserState* context) const override;
 };
 
 #endif  // IOS_CHROME_BROWSER_GOOGLE_MODEL_GOOGLE_LOGO_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/google/model/google_logo_service_factory.mm b/ios/chrome/browser/google/model/google_logo_service_factory.mm
index 84f369c..6498720 100644
--- a/ios/chrome/browser/google/model/google_logo_service_factory.mm
+++ b/ios/chrome/browser/google/model/google_logo_service_factory.mm
@@ -4,11 +4,8 @@
 
 #import "ios/chrome/browser/google/model/google_logo_service_factory.h"
 
-#import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "ios/chrome/browser/google/model/google_logo_service.h"
 #import "ios/chrome/browser/search_engines/model/template_url_service_factory.h"
-#import "ios/chrome/browser/shared/model/browser_state/browser_state_otr_helper.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/signin/model/identity_manager_factory.h"
 #import "services/network/public/cpp/shared_url_loader_factory.h"
@@ -16,8 +13,8 @@
 // static
 GoogleLogoService* GoogleLogoServiceFactory::GetForProfile(
     ProfileIOS* profile) {
-  return static_cast<GoogleLogoService*>(
-      GetInstance()->GetServiceForBrowserState(profile, true));
+  return GetInstance()->GetServiceForProfileAs<GoogleLogoService>(
+      profile, /*create=*/true);
 }
 
 // static
@@ -27,14 +24,13 @@
 }
 
 GoogleLogoServiceFactory::GoogleLogoServiceFactory()
-    : BrowserStateKeyedServiceFactory(
-          "GoogleLogoService",
-          BrowserStateDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactoryIOS("GoogleLogoService",
+                                    ProfileSelection::kOwnInstanceInIncognito) {
   DependsOn(ios::TemplateURLServiceFactory::GetInstance());
   DependsOn(IdentityManagerFactory::GetInstance());
 }
 
-GoogleLogoServiceFactory::~GoogleLogoServiceFactory() {}
+GoogleLogoServiceFactory::~GoogleLogoServiceFactory() = default;
 
 std::unique_ptr<KeyedService> GoogleLogoServiceFactory::BuildServiceInstanceFor(
     web::BrowserState* context) const {
@@ -44,8 +40,3 @@
       IdentityManagerFactory::GetForProfile(profile),
       profile->GetSharedURLLoaderFactory());
 }
-
-web::BrowserState* GoogleLogoServiceFactory::GetBrowserStateToUse(
-    web::BrowserState* context) const {
-  return GetBrowserStateOwnInstanceInIncognito(context);
-}
diff --git a/ios/chrome/browser/history/model/BUILD.gn b/ios/chrome/browser/history/model/BUILD.gn
index 5a2319a..1e15b11 100644
--- a/ios/chrome/browser/history/model/BUILD.gn
+++ b/ios/chrome/browser/history/model/BUILD.gn
@@ -27,13 +27,11 @@
     "//components/history/core/common",
     "//components/history/ios/browser",
     "//components/history/metrics",
-    "//components/keyed_service/ios",
     "//components/pref_registry",
     "//components/prefs",
     "//components/sync",
     "//components/version_info",
     "//ios/chrome/browser/search_engines/model:template_url_service_factory",
-    "//ios/chrome/browser/shared/model/browser_state",
     "//ios/chrome/browser/shared/model/profile",
     "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
     "//ios/chrome/browser/shared/model/url:constants",
diff --git a/ios/chrome/browser/history/model/domain_diversity_reporter_factory.h b/ios/chrome/browser/history/model/domain_diversity_reporter_factory.h
index 15a595f..1d522c7c 100644
--- a/ios/chrome/browser/history/model/domain_diversity_reporter_factory.h
+++ b/ios/chrome/browser/history/model/domain_diversity_reporter_factory.h
@@ -5,13 +5,10 @@
 #ifndef IOS_CHROME_BROWSER_HISTORY_MODEL_DOMAIN_DIVERSITY_REPORTER_FACTORY_H_
 #define IOS_CHROME_BROWSER_HISTORY_MODEL_DOMAIN_DIVERSITY_REPORTER_FACTORY_H_
 
-#include <memory>
-
 #include "base/no_destructor.h"
-#include "components/keyed_service/ios/browser_state_keyed_service_factory.h"
+#include "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
 class DomainDiversityReporter;
-class ProfileIOS;
 
 namespace user_prefs {
 class PrefRegistrySyncable;
@@ -19,7 +16,7 @@
 
 // Singleton that creates all DomainDiversityReporter instances and associates
 // them with BrowserState.
-class DomainDiversityReporterFactory : public BrowserStateKeyedServiceFactory {
+class DomainDiversityReporterFactory : public ProfileKeyedServiceFactoryIOS {
  public:
   static DomainDiversityReporter* GetForProfile(ProfileIOS* profile);
 
@@ -37,11 +34,6 @@
 
   std::unique_ptr<KeyedService> BuildServiceInstanceFor(
       web::BrowserState* browser_state) const override;
-
-  web::BrowserState* GetBrowserStateToUse(
-      web::BrowserState* browser_state) const override;
-  bool ServiceIsNULLWhileTesting() const override;
-  bool ServiceIsCreatedWithBrowserState() const override;
 };
 
 #endif  // IOS_CHROME_BROWSER_HISTORY_MODEL_DOMAIN_DIVERSITY_REPORTER_FACTORY_H_
diff --git a/ios/chrome/browser/history/model/domain_diversity_reporter_factory.mm b/ios/chrome/browser/history/model/domain_diversity_reporter_factory.mm
index 91403d52..b7c63fb7 100644
--- a/ios/chrome/browser/history/model/domain_diversity_reporter_factory.mm
+++ b/ios/chrome/browser/history/model/domain_diversity_reporter_factory.mm
@@ -5,23 +5,20 @@
 #import "ios/chrome/browser/history/model/domain_diversity_reporter_factory.h"
 
 #import "base/functional/bind.h"
-#import "base/no_destructor.h"
 #import "base/time/default_clock.h"
 #import "build/build_config.h"
 #import "components/history/metrics/domain_diversity_reporter.h"
 #import "components/keyed_service/core/service_access_type.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "components/pref_registry/pref_registry_syncable.h"
 #import "components/prefs/pref_service.h"
 #import "ios/chrome/browser/history/model/history_service_factory.h"
-#import "ios/chrome/browser/shared/model/browser_state/browser_state_otr_helper.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 
 // static
 DomainDiversityReporter* DomainDiversityReporterFactory::GetForProfile(
     ProfileIOS* profile) {
-  return static_cast<DomainDiversityReporter*>(
-      GetInstance()->GetServiceForBrowserState(profile, /*create=*/true));
+  return GetInstance()->GetServiceForProfileAs<DomainDiversityReporter>(
+      profile, /*create=*/true);
 }
 
 // static
@@ -31,9 +28,10 @@
 }
 
 DomainDiversityReporterFactory::DomainDiversityReporterFactory()
-    : BrowserStateKeyedServiceFactory(
-          "DomainDiversityReporter",
-          BrowserStateDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactoryIOS("DomainDiversityReporter",
+                                    ProfileSelection::kRedirectedInIncognito,
+                                    ServiceCreation::kCreateWithProfile,
+                                    TestingCreation::kNoServiceForTests) {
   DependsOn(ios::HistoryServiceFactory::GetInstance());
 }
 
@@ -63,16 +61,3 @@
     user_prefs::PrefRegistrySyncable* registry) {
   DomainDiversityReporter::RegisterProfilePrefs(registry);
 }
-
-web::BrowserState* DomainDiversityReporterFactory::GetBrowserStateToUse(
-    web::BrowserState* context) const {
-  return GetBrowserStateRedirectedInIncognito(context);
-}
-
-bool DomainDiversityReporterFactory::ServiceIsNULLWhileTesting() const {
-  return true;
-}
-
-bool DomainDiversityReporterFactory::ServiceIsCreatedWithBrowserState() const {
-  return true;
-}
diff --git a/ios/chrome/browser/https_upgrades/model/BUILD.gn b/ios/chrome/browser/https_upgrades/model/BUILD.gn
index f19785f..51781e4 100644
--- a/ios/chrome/browser/https_upgrades/model/BUILD.gn
+++ b/ios/chrome/browser/https_upgrades/model/BUILD.gn
@@ -16,14 +16,13 @@
   deps = [
     "//base",
     "//components/keyed_service/core",
-    "//components/keyed_service/ios",
     "//components/prefs:prefs",
     "//components/security_interstitials/core",
     "//ios/chrome/browser/content_settings/model:model",
     "//ios/chrome/browser/prerender/model",
-    "//ios/chrome/browser/shared/model/browser_state",
     "//ios/chrome/browser/shared/model/prefs:pref_names",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
     "//ios/components/security_interstitials",
     "//ios/components/security_interstitials/https_only_mode",
     "//ios/components/security_interstitials/https_only_mode:feature",
diff --git a/ios/chrome/browser/https_upgrades/model/https_upgrade_service_factory.h b/ios/chrome/browser/https_upgrades/model/https_upgrade_service_factory.h
index b57772c..a0fc9b5 100644
--- a/ios/chrome/browser/https_upgrades/model/https_upgrade_service_factory.h
+++ b/ios/chrome/browser/https_upgrades/model/https_upgrade_service_factory.h
@@ -5,25 +5,19 @@
 #ifndef IOS_CHROME_BROWSER_HTTPS_UPGRADES_MODEL_HTTPS_UPGRADE_SERVICE_FACTORY_H_
 #define IOS_CHROME_BROWSER_HTTPS_UPGRADES_MODEL_HTTPS_UPGRADE_SERVICE_FACTORY_H_
 
-#include <memory>
-
 #include "base/no_destructor.h"
-#include "components/keyed_service/ios/browser_state_keyed_service_factory.h"
 #include "ios/chrome/browser/https_upgrades/model/https_upgrade_service_impl.h"
+#include "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
 class ProfileIOS;
 
 // Singleton that owns all HttpsUpgradeService and associates them with
 // ProfileIOS.
-class HttpsUpgradeServiceFactory : public BrowserStateKeyedServiceFactory {
+class HttpsUpgradeServiceFactory : public ProfileKeyedServiceFactoryIOS {
  public:
   static HttpsUpgradeService* GetForProfile(ProfileIOS* profile);
   static HttpsUpgradeServiceFactory* GetInstance();
 
-  HttpsUpgradeServiceFactory(const HttpsUpgradeServiceFactory&) = delete;
-  HttpsUpgradeServiceFactory& operator=(const HttpsUpgradeServiceFactory&) =
-      delete;
-
  private:
   friend class base::NoDestructor<HttpsUpgradeServiceFactory>;
 
@@ -33,10 +27,6 @@
   // BrowserStateKeyedServiceFactory implementation.
   std::unique_ptr<KeyedService> BuildServiceInstanceFor(
       web::BrowserState* context) const override;
-  web::BrowserState* GetBrowserStateToUse(
-      web::BrowserState* context) const override;
-
-  bool ServiceIsNULLWhileTesting() const override;
 };
 
 #endif  // IOS_CHROME_BROWSER_HTTPS_UPGRADES_MODEL_HTTPS_UPGRADE_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/https_upgrades/model/https_upgrade_service_factory.mm b/ios/chrome/browser/https_upgrades/model/https_upgrade_service_factory.mm
index 4bf81fd7..1fb84d1 100644
--- a/ios/chrome/browser/https_upgrades/model/https_upgrade_service_factory.mm
+++ b/ios/chrome/browser/https_upgrades/model/https_upgrade_service_factory.mm
@@ -4,18 +4,15 @@
 
 #import "ios/chrome/browser/https_upgrades/model/https_upgrade_service_factory.h"
 
-#import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "ios/chrome/browser/content_settings/model/host_content_settings_map_factory.h"
-#import "ios/chrome/browser/shared/model/browser_state/browser_state_otr_helper.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/web/public/browser_state.h"
 
 // static
 HttpsUpgradeService* HttpsUpgradeServiceFactory::GetForProfile(
     ProfileIOS* profile) {
-  return static_cast<HttpsUpgradeService*>(
-      GetInstance()->GetServiceForBrowserState(profile, true));
+  return GetInstance()->GetServiceForProfileAs<HttpsUpgradeService>(
+      profile, /*create=*/true);
 }
 
 // static
@@ -25,13 +22,12 @@
 }
 
 HttpsUpgradeServiceFactory::HttpsUpgradeServiceFactory()
-    : BrowserStateKeyedServiceFactory(
-          "HttpsUpgradeService",
-          BrowserStateDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactoryIOS("HttpsUpgradeService",
+                                    ProfileSelection::kOwnInstanceInIncognito) {
   DependsOn(ios::HostContentSettingsMapFactory::GetInstance());
 }
 
-HttpsUpgradeServiceFactory::~HttpsUpgradeServiceFactory() {}
+HttpsUpgradeServiceFactory::~HttpsUpgradeServiceFactory() = default;
 
 std::unique_ptr<KeyedService>
 HttpsUpgradeServiceFactory::BuildServiceInstanceFor(
@@ -39,12 +35,3 @@
   return std::make_unique<HttpsUpgradeServiceImpl>(
       ProfileIOS::FromBrowserState(context));
 }
-
-web::BrowserState* HttpsUpgradeServiceFactory::GetBrowserStateToUse(
-    web::BrowserState* context) const {
-  return GetBrowserStateOwnInstanceInIncognito(context);
-}
-
-bool HttpsUpgradeServiceFactory::ServiceIsNULLWhileTesting() const {
-  return false;
-}
diff --git a/ios/chrome/browser/incognito_reauth/ui_bundled/incognito_reauth_scene_agent.mm b/ios/chrome/browser/incognito_reauth/ui_bundled/incognito_reauth_scene_agent.mm
index 399dd3f6..3b46374 100644
--- a/ios/chrome/browser/incognito_reauth/ui_bundled/incognito_reauth_scene_agent.mm
+++ b/ios/chrome/browser/incognito_reauth/ui_bundled/incognito_reauth_scene_agent.mm
@@ -243,6 +243,7 @@
   if (IsIOSSoftLockEnabled()) {
     [self setUpPrefObservers];
     [self logIncognitoLockStateHistogramOnce];
+    [self recordIncognitoLockImpressionForSceneState:sceneState];
   }
 }
 
@@ -491,7 +492,9 @@
 
 // Records impressions of the Incognito lock for reauth and soft lock states.
 - (void)recordIncognitoLockImpressionForSceneState:(SceneState*)sceneState {
-  if (sceneState.incognitoContentVisible &&
+  // sceneState.UIEnabled guarantees that sceneState.controller has been
+  // initialized.
+  if (sceneState.UIEnabled && sceneState.incognitoContentVisible &&
       sceneState.activationLevel == SceneActivationLevelForegroundActive) {
     switch ([self incognitoLockState]) {
       case IncognitoLockState::kNone:
diff --git a/ios/chrome/browser/language/model/BUILD.gn b/ios/chrome/browser/language/model/BUILD.gn
index 71e8f62202..4f07d6c 100644
--- a/ios/chrome/browser/language/model/BUILD.gn
+++ b/ios/chrome/browser/language/model/BUILD.gn
@@ -14,14 +14,12 @@
   deps = [
     "//base",
     "//components/keyed_service/core",
-    "//components/keyed_service/ios",
     "//components/language/core/browser",
     "//components/language/core/common",
     "//components/language/core/language_model",
     "//components/pref_registry",
     "//components/prefs",
     "//ios/chrome/browser/shared/model/application_context",
-    "//ios/chrome/browser/shared/model/browser_state",
     "//ios/chrome/browser/shared/model/profile",
     "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
   ]
diff --git a/ios/chrome/browser/language/model/language_model_manager_factory.h b/ios/chrome/browser/language/model/language_model_manager_factory.h
index a0d5091..7192b7b 100644
--- a/ios/chrome/browser/language/model/language_model_manager_factory.h
+++ b/ios/chrome/browser/language/model/language_model_manager_factory.h
@@ -8,10 +8,7 @@
 #import <memory>
 
 #import "base/no_destructor.h"
-#import "components/keyed_service/core/keyed_service.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
-
-class ProfileIOS;
+#import "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
 namespace language {
 class LanguageModelManager;
@@ -19,15 +16,11 @@
 
 // Manages the language model for each profile. The particular language model
 // provided depends on feature flags.
-class LanguageModelManagerFactory : public BrowserStateKeyedServiceFactory {
+class LanguageModelManagerFactory : public ProfileKeyedServiceFactoryIOS {
  public:
   static language::LanguageModelManager* GetForProfile(ProfileIOS* profile);
   static LanguageModelManagerFactory* GetInstance();
 
-  LanguageModelManagerFactory(const LanguageModelManagerFactory&) = delete;
-  LanguageModelManagerFactory& operator=(const LanguageModelManagerFactory&) =
-      delete;
-
  private:
   friend class base::NoDestructor<LanguageModelManagerFactory>;
 
@@ -37,8 +30,6 @@
   // BrowserStateKeyedServiceFactory implementation.
   std::unique_ptr<KeyedService> BuildServiceInstanceFor(
       web::BrowserState* context) const override;
-  web::BrowserState* GetBrowserStateToUse(
-      web::BrowserState* state) const override;
 };
 
 #endif  // IOS_CHROME_BROWSER_LANGUAGE_MODEL_LANGUAGE_MODEL_MANAGER_FACTORY_H_
diff --git a/ios/chrome/browser/language/model/language_model_manager_factory.mm b/ios/chrome/browser/language/model/language_model_manager_factory.mm
index f862d4b7..003787a 100644
--- a/ios/chrome/browser/language/model/language_model_manager_factory.mm
+++ b/ios/chrome/browser/language/model/language_model_manager_factory.mm
@@ -6,8 +6,6 @@
 
 #import "base/feature_list.h"
 #import "base/no_destructor.h"
-#import "components/keyed_service/core/keyed_service.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "components/language/core/browser/language_model.h"
 #import "components/language/core/browser/language_model_manager.h"
 #import "components/language/core/browser/pref_names.h"
@@ -16,7 +14,6 @@
 #import "components/pref_registry/pref_registry_syncable.h"
 #import "components/prefs/pref_service.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
-#import "ios/chrome/browser/shared/model/browser_state/browser_state_otr_helper.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 
 namespace {
@@ -42,14 +39,14 @@
 // static
 language::LanguageModelManager* LanguageModelManagerFactory::GetForProfile(
     ProfileIOS* profile) {
-  return static_cast<language::LanguageModelManager*>(
-      GetInstance()->GetServiceForBrowserState(profile, true));
+  return GetInstance()->GetServiceForProfileAs<language::LanguageModelManager>(
+      profile, /*create=*/true);
 }
 
+// Use the original profile's language model even in Incognito mode.
 LanguageModelManagerFactory::LanguageModelManagerFactory()
-    : BrowserStateKeyedServiceFactory(
-          "LanguageModelManager",
-          BrowserStateDependencyManager::GetInstance()) {}
+    : ProfileKeyedServiceFactoryIOS("LanguageModelManager",
+                                    ProfileSelection::kRedirectedInIncognito) {}
 
 LanguageModelManagerFactory::~LanguageModelManagerFactory() {}
 
@@ -63,9 +60,3 @@
   PrepareLanguageModels(profile, manager.get());
   return manager;
 }
-
-web::BrowserState* LanguageModelManagerFactory::GetBrowserStateToUse(
-    web::BrowserState* const state) const {
-  // Use the original profile's language model even in Incognito mode.
-  return GetBrowserStateRedirectedInIncognito(state);
-}
diff --git a/ios/chrome/browser/page_image/model/BUILD.gn b/ios/chrome/browser/page_image/model/BUILD.gn
index a358c48..3e269784 100644
--- a/ios/chrome/browser/page_image/model/BUILD.gn
+++ b/ios/chrome/browser/page_image/model/BUILD.gn
@@ -9,14 +9,12 @@
   ]
   deps = [
     "//base",
-    "//components/keyed_service/core",
-    "//components/keyed_service/ios",
     "//components/page_image_service",
     "//ios/chrome/browser/autocomplete/model",
     "//ios/chrome/browser/optimization_guide/model",
     "//ios/chrome/browser/search_engines/model",
-    "//ios/chrome/browser/shared/model/browser_state",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
     "//ios/chrome/browser/sync/model",
   ]
 }
diff --git a/ios/chrome/browser/page_image/model/page_image_service_factory.h b/ios/chrome/browser/page_image/model/page_image_service_factory.h
index f6d14b7..718e5db 100644
--- a/ios/chrome/browser/page_image/model/page_image_service_factory.h
+++ b/ios/chrome/browser/page_image/model/page_image_service_factory.h
@@ -8,23 +8,18 @@
 #import <memory>
 
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
-
-class ProfileIOS;
+#import "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
 namespace page_image_service {
 class ImageService;
 }  // namespace page_image_service
 
 // Factory for the components ImageService service which fetches salient images.
-class PageImageServiceFactory : public BrowserStateKeyedServiceFactory {
+class PageImageServiceFactory : public ProfileKeyedServiceFactoryIOS {
  public:
   static page_image_service::ImageService* GetForProfile(ProfileIOS* profile);
   static PageImageServiceFactory* GetInstance();
 
-  PageImageServiceFactory(const PageImageServiceFactory&) = delete;
-  PageImageServiceFactory& operator=(const PageImageServiceFactory&) = delete;
-
  private:
   friend class base::NoDestructor<PageImageServiceFactory>;
 
diff --git a/ios/chrome/browser/page_image/model/page_image_service_factory.mm b/ios/chrome/browser/page_image/model/page_image_service_factory.mm
index 3d54cec..0e7f3160 100644
--- a/ios/chrome/browser/page_image/model/page_image_service_factory.mm
+++ b/ios/chrome/browser/page_image/model/page_image_service_factory.mm
@@ -4,8 +4,6 @@
 
 #import "ios/chrome/browser/page_image/model/page_image_service_factory.h"
 
-#import "components/keyed_service/core/service_access_type.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "components/page_image_service/image_service.h"
 #import "components/page_image_service/image_service_impl.h"
 #import "ios/chrome/browser/autocomplete/model/autocomplete_scheme_classifier_impl.h"
@@ -13,21 +11,19 @@
 #import "ios/chrome/browser/optimization_guide/model/optimization_guide_service.h"
 #import "ios/chrome/browser/optimization_guide/model/optimization_guide_service_factory.h"
 #import "ios/chrome/browser/search_engines/model/template_url_service_factory.h"
-#import "ios/chrome/browser/shared/model/browser_state/browser_state_otr_helper.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/sync/model/sync_service_factory.h"
 
 // static
 page_image_service::ImageService* PageImageServiceFactory::GetForProfile(
     ProfileIOS* profile) {
-  return static_cast<page_image_service::ImageService*>(
-      GetInstance()->GetServiceForBrowserState(profile, true));
+  return GetInstance()
+      ->GetServiceForProfileAs<page_image_service::ImageService>(
+          profile, /*create=*/true);
 }
 
 PageImageServiceFactory::PageImageServiceFactory()
-    : BrowserStateKeyedServiceFactory(
-          "PageImageService",
-          BrowserStateDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactoryIOS("PageImageService") {
   DependsOn(ios::TemplateURLServiceFactory::GetInstance());
   DependsOn(RemoteSuggestionsServiceFactory::GetInstance());
   DependsOn(OptimizationGuideServiceFactory::GetInstance());
diff --git a/ios/chrome/browser/passwords/model/BUILD.gn b/ios/chrome/browser/passwords/model/BUILD.gn
index 6fed80a..caab063 100644
--- a/ios/chrome/browser/passwords/model/BUILD.gn
+++ b/ios/chrome/browser/passwords/model/BUILD.gn
@@ -57,7 +57,6 @@
     "//components/browser_sync",
     "//components/image_fetcher/core",
     "//components/image_fetcher/ios",
-    "//components/keyed_service/ios",
     "//components/password_manager/core/browser",
     "//components/password_manager/core/browser/affiliation:affiliation_fetching",
     "//components/password_manager/core/browser/features:password_features",
@@ -90,7 +89,6 @@
     "//ios/chrome/browser/safe_browsing/model:features",
     "//ios/chrome/browser/shared/model/application_context",
     "//ios/chrome/browser/shared/model/browser",
-    "//ios/chrome/browser/shared/model/browser_state",
     "//ios/chrome/browser/shared/model/profile",
     "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
     "//ios/chrome/browser/shared/public/commands",
@@ -161,7 +159,6 @@
     "//components/sync",
     "//ios/chrome/browser/affiliations/model",
     "//ios/chrome/browser/shared/model/application_context",
-    "//ios/chrome/browser/shared/model/browser_state",
     "//ios/chrome/browser/shared/model/profile",
     "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
     "//ios/chrome/browser/signin/model:signin_util",
@@ -231,7 +228,6 @@
   ]
   deps = [
     ":store_factory",
-    "//components/keyed_service/ios",
     "//components/password_manager/core/browser",
     "//components/password_manager/core/browser/features:password_features",
     "//components/password_manager/core/browser/sharing",
@@ -358,7 +354,6 @@
     "//base",
     "//base/test:test_support",
     "//components/autofill/core/common",
-    "//components/keyed_service/core",
     "//components/password_manager/core/browser",
     "//components/password_manager/core/common",
     "//components/prefs",
diff --git a/ios/chrome/browser/passwords/model/ios_chrome_password_check_manager_factory.h b/ios/chrome/browser/passwords/model/ios_chrome_password_check_manager_factory.h
index 52fb70d..b051091 100644
--- a/ios/chrome/browser/passwords/model/ios_chrome_password_check_manager_factory.h
+++ b/ios/chrome/browser/passwords/model/ios_chrome_password_check_manager_factory.h
@@ -7,14 +7,13 @@
 
 #import "base/memory/weak_ptr.h"
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.h"
+#import "ios/chrome/browser/shared/model/profile/refcounted_profile_keyed_service_factory_ios.h"
 
 class IOSChromePasswordCheckManager;
-class ProfileIOS;
 
 // Singleton that owns weak pointer to IOSChromePasswordCheckManager.
 class IOSChromePasswordCheckManagerFactory
-    : public RefcountedBrowserStateKeyedServiceFactory {
+    : public RefcountedProfileKeyedServiceFactoryIOS {
  public:
   static scoped_refptr<IOSChromePasswordCheckManager> GetForProfile(
       ProfileIOS* profile);
diff --git a/ios/chrome/browser/passwords/model/ios_chrome_password_check_manager_factory.mm b/ios/chrome/browser/passwords/model/ios_chrome_password_check_manager_factory.mm
index 86614db..5f66cad7 100644
--- a/ios/chrome/browser/passwords/model/ios_chrome_password_check_manager_factory.mm
+++ b/ios/chrome/browser/passwords/model/ios_chrome_password_check_manager_factory.mm
@@ -8,7 +8,6 @@
 #import "base/memory/scoped_refptr.h"
 #import "base/no_destructor.h"
 #import "components/keyed_service/core/service_access_type.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
 #import "ios/chrome/browser/affiliations/model/ios_chrome_affiliation_service_factory.h"
 #import "ios/chrome/browser/passwords/model/ios_chrome_account_password_store_factory.h"
@@ -28,14 +27,12 @@
 // static
 scoped_refptr<IOSChromePasswordCheckManager>
 IOSChromePasswordCheckManagerFactory::GetForProfile(ProfileIOS* profile) {
-  return base::WrapRefCounted(static_cast<IOSChromePasswordCheckManager*>(
-      GetInstance()->GetServiceForBrowserState(profile, true).get()));
+  return GetInstance()->GetServiceForProfileAs<IOSChromePasswordCheckManager>(
+      profile, /*create=*/true);
 }
 
 IOSChromePasswordCheckManagerFactory::IOSChromePasswordCheckManagerFactory()
-    : RefcountedBrowserStateKeyedServiceFactory(
-          "PasswordCheckManager",
-          BrowserStateDependencyManager::GetInstance()) {
+    : RefcountedProfileKeyedServiceFactoryIOS("PasswordCheckManager") {
   DependsOn(IOSChromeAccountPasswordStoreFactory::GetInstance());
   DependsOn(IOSChromeAffiliationServiceFactory::GetInstance());
   DependsOn(IOSChromeBulkLeakCheckServiceFactory::GetInstance());
diff --git a/ios/chrome/browser/passwords/model/ios_chrome_password_manager_client.mm b/ios/chrome/browser/passwords/model/ios_chrome_password_manager_client.mm
index 364a45d8..06386f51 100644
--- a/ios/chrome/browser/passwords/model/ios_chrome_password_manager_client.mm
+++ b/ios/chrome/browser/passwords/model/ios_chrome_password_manager_client.mm
@@ -294,8 +294,7 @@
 
 password_manager::PasswordRequirementsService*
 IOSChromePasswordManagerClient::GetPasswordRequirementsService() {
-  return IOSPasswordRequirementsServiceFactory::GetForProfile(
-      bridge_.profile, ServiceAccessType::EXPLICIT_ACCESS);
+  return IOSPasswordRequirementsServiceFactory::GetForProfile(bridge_.profile);
 }
 
 void IOSChromePasswordManagerClient::UpdateFormManagers() {
diff --git a/ios/chrome/browser/passwords/model/ios_chrome_profile_password_store_factory.h b/ios/chrome/browser/passwords/model/ios_chrome_profile_password_store_factory.h
index f6c0634f..afab87f 100644
--- a/ios/chrome/browser/passwords/model/ios_chrome_profile_password_store_factory.h
+++ b/ios/chrome/browser/passwords/model/ios_chrome_profile_password_store_factory.h
@@ -7,9 +7,8 @@
 
 #import "base/memory/ref_counted.h"
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.h"
+#import "ios/chrome/browser/shared/model/profile/refcounted_profile_keyed_service_factory_ios.h"
 
-class ProfileIOS;
 enum class ServiceAccessType;
 
 namespace password_manager {
@@ -19,18 +18,13 @@
 // Singleton that owns all PasswordStores and associates them with
 // ProfileIOS.
 class IOSChromeProfilePasswordStoreFactory
-    : public RefcountedBrowserStateKeyedServiceFactory {
+    : public RefcountedProfileKeyedServiceFactoryIOS {
  public:
   static scoped_refptr<password_manager::PasswordStoreInterface> GetForProfile(
       ProfileIOS* profile,
       ServiceAccessType access_type);
   static IOSChromeProfilePasswordStoreFactory* GetInstance();
 
-  IOSChromeProfilePasswordStoreFactory(
-      const IOSChromeProfilePasswordStoreFactory&) = delete;
-  IOSChromeProfilePasswordStoreFactory& operator=(
-      const IOSChromeProfilePasswordStoreFactory&) = delete;
-
  private:
   friend class base::NoDestructor<IOSChromeProfilePasswordStoreFactory>;
 
@@ -40,9 +34,6 @@
   // BrowserStateKeyedServiceFactory:
   scoped_refptr<RefcountedKeyedService> BuildServiceInstanceFor(
       web::BrowserState* context) const override;
-  web::BrowserState* GetBrowserStateToUse(
-      web::BrowserState* context) const override;
-  bool ServiceIsNULLWhileTesting() const override;
 };
 
 #endif  // IOS_CHROME_BROWSER_PASSWORDS_MODEL_IOS_CHROME_PROFILE_PASSWORD_STORE_FACTORY_H_
diff --git a/ios/chrome/browser/passwords/model/ios_chrome_profile_password_store_factory.mm b/ios/chrome/browser/passwords/model/ios_chrome_profile_password_store_factory.mm
index b9bb250..62011e5 100644
--- a/ios/chrome/browser/passwords/model/ios_chrome_profile_password_store_factory.mm
+++ b/ios/chrome/browser/passwords/model/ios_chrome_profile_password_store_factory.mm
@@ -12,7 +12,6 @@
 #import "base/no_destructor.h"
 #import "components/affiliations/core/browser/affiliation_service.h"
 #import "components/keyed_service/core/service_access_type.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "components/password_manager/core/browser/affiliation/password_affiliation_source_adapter.h"
 #import "components/password_manager/core/browser/features/password_features.h"
 #import "components/password_manager/core/browser/password_store/login_database.h"
@@ -26,7 +25,6 @@
 #import "ios/chrome/browser/passwords/model/credentials_cleaner_runner_factory.h"
 #import "ios/chrome/browser/passwords/model/ios_password_store_utils.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
-#import "ios/chrome/browser/shared/model/browser_state/browser_state_otr_helper.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/signin/model/signin_util.h"
 #import "ios/chrome/browser/sync/model/sync_service_factory.h"
@@ -62,9 +60,9 @@
       profile->IsOffTheRecord()) {
     return nullptr;
   }
-  return base::WrapRefCounted(
-      static_cast<password_manager::PasswordStoreInterface*>(
-          GetInstance()->GetServiceForBrowserState(profile, true).get()));
+  return GetInstance()
+      ->GetServiceForProfileAs<password_manager::PasswordStoreInterface>(
+          profile, /*create=*/true);
 }
 
 // static
@@ -75,9 +73,10 @@
 }
 
 IOSChromeProfilePasswordStoreFactory::IOSChromeProfilePasswordStoreFactory()
-    : RefcountedBrowserStateKeyedServiceFactory(
+    : RefcountedProfileKeyedServiceFactoryIOS(
           "PasswordStore",
-          BrowserStateDependencyManager::GetInstance()) {
+          ProfileSelection::kRedirectedInIncognito,
+          TestingCreation::kNoServiceForTests) {
   DependsOn(CredentialsCleanerRunnerFactory::GetInstance());
   DependsOn(IOSChromeAffiliationServiceFactory::GetInstance());
 }
@@ -128,12 +127,3 @@
   affiliation_service->RegisterSource(std::move(password_affiliation_adapter));
   return store;
 }
-
-web::BrowserState* IOSChromeProfilePasswordStoreFactory::GetBrowserStateToUse(
-    web::BrowserState* context) const {
-  return GetBrowserStateRedirectedInIncognito(context);
-}
-
-bool IOSChromeProfilePasswordStoreFactory::ServiceIsNULLWhileTesting() const {
-  return true;
-}
diff --git a/ios/chrome/browser/passwords/model/ios_password_requirements_service_factory.cc b/ios/chrome/browser/passwords/model/ios_password_requirements_service_factory.cc
index a9cf794..117492f7 100644
--- a/ios/chrome/browser/passwords/model/ios_password_requirements_service_factory.cc
+++ b/ios/chrome/browser/passwords/model/ios_password_requirements_service_factory.cc
@@ -5,19 +5,16 @@
 #include "ios/chrome/browser/passwords/model/ios_password_requirements_service_factory.h"
 
 #include "base/no_destructor.h"
-#include "components/keyed_service/core/service_access_type.h"
-#include "components/keyed_service/ios/browser_state_dependency_manager.h"
 #include "components/password_manager/core/browser/password_requirements_service.h"
 #include "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
 // static
 password_manager::PasswordRequirementsService*
-IOSPasswordRequirementsServiceFactory::GetForProfile(
-    ProfileIOS* profile,
-    ServiceAccessType access_type) {
-  return static_cast<password_manager::PasswordRequirementsService*>(
-      GetInstance()->GetServiceForBrowserState(profile, true));
+IOSPasswordRequirementsServiceFactory::GetForProfile(ProfileIOS* profile) {
+  return GetInstance()
+      ->GetServiceForProfileAs<password_manager::PasswordRequirementsService>(
+          profile, /*create=*/true);
 }
 
 // static
@@ -28,9 +25,8 @@
 }
 
 IOSPasswordRequirementsServiceFactory::IOSPasswordRequirementsServiceFactory()
-    : BrowserStateKeyedServiceFactory(
-          "PasswordRequirementsServiceFactory",
-          BrowserStateDependencyManager::GetInstance()) {}
+    : ProfileKeyedServiceFactoryIOS("PasswordRequirementsServiceFactory",
+                                    TestingCreation::kNoServiceForTests) {}
 
 IOSPasswordRequirementsServiceFactory::
     ~IOSPasswordRequirementsServiceFactory() {}
@@ -41,7 +37,3 @@
   return password_manager::CreatePasswordRequirementsService(
       context->GetSharedURLLoaderFactory());
 }
-
-bool IOSPasswordRequirementsServiceFactory::ServiceIsNULLWhileTesting() const {
-  return true;
-}
diff --git a/ios/chrome/browser/passwords/model/ios_password_requirements_service_factory.h b/ios/chrome/browser/passwords/model/ios_password_requirements_service_factory.h
index c14bce5..5bd8d33 100644
--- a/ios/chrome/browser/passwords/model/ios_password_requirements_service_factory.h
+++ b/ios/chrome/browser/passwords/model/ios_password_requirements_service_factory.h
@@ -6,11 +6,7 @@
 #define IOS_CHROME_BROWSER_PASSWORDS_MODEL_IOS_PASSWORD_REQUIREMENTS_SERVICE_FACTORY_H_
 
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
-#import "ios/chrome/browser/shared/model/browser_state/browser_state_otr_helper.h"
-
-class ProfileIOS;
-enum class ServiceAccessType;
+#import "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
 namespace password_manager {
 class PasswordRequirementsService;
@@ -19,19 +15,12 @@
 // Singleton that owns all PasswordRequirementsService and associates them with
 // ProfileIOS.
 class IOSPasswordRequirementsServiceFactory
-    : public BrowserStateKeyedServiceFactory {
+    : public ProfileKeyedServiceFactoryIOS {
  public:
   static password_manager::PasswordRequirementsService* GetForProfile(
-      ProfileIOS* profile,
-      ServiceAccessType access_type);
-
+      ProfileIOS* profile);
   static IOSPasswordRequirementsServiceFactory* GetInstance();
 
-  IOSPasswordRequirementsServiceFactory(
-      const IOSPasswordRequirementsServiceFactory&) = delete;
-  IOSPasswordRequirementsServiceFactory& operator=(
-      const IOSPasswordRequirementsServiceFactory&) = delete;
-
  private:
   friend class base::NoDestructor<IOSPasswordRequirementsServiceFactory>;
 
@@ -41,7 +30,6 @@
   // BrowserStateKeyedServiceFactory:
   std::unique_ptr<KeyedService> BuildServiceInstanceFor(
       web::BrowserState* context) const override;
-  bool ServiceIsNULLWhileTesting() const override;
 };
 
 #endif  // IOS_CHROME_BROWSER_PASSWORDS_MODEL_IOS_PASSWORD_REQUIREMENTS_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/passwords/model/password_controller_unittest.mm b/ios/chrome/browser/passwords/model/password_controller_unittest.mm
index 361c96b7..3bda16c 100644
--- a/ios/chrome/browser/passwords/model/password_controller_unittest.mm
+++ b/ios/chrome/browser/passwords/model/password_controller_unittest.mm
@@ -570,7 +570,7 @@
       processPasswordFormFillData:form_data
                        forFrameId:frame->GetFrameId()
                       isMainFrame:frame->IsMainFrame()
-                forSecurityOrigin:frame->GetSecurityOriginDeprecated()];
+                forSecurityOrigin:frame->GetSecurityOrigin()];
 
   __block BOOL block_was_called = NO;
 
@@ -1106,8 +1106,7 @@
       processPasswordFormFillData:form_data
                        forFrameId:expected_frame->GetFrameId()
                       isMainFrame:expected_frame->IsMainFrame()
-                forSecurityOrigin:expected_frame
-                                      ->GetSecurityOriginDeprecated()];
+                forSecurityOrigin:expected_frame->GetSecurityOrigin()];
 
   // clang-format off
   SuggestionTestData test_data[] = {
@@ -1620,8 +1619,7 @@
       processPasswordFormFillData:form_data
                        forFrameId:expected_frame->GetFrameId()
                       isMainFrame:expected_frame->IsMainFrame()
-                forSecurityOrigin:expected_frame
-                                      ->GetSecurityOriginDeprecated()];
+                forSecurityOrigin:expected_frame->GetSecurityOrigin()];
 
   // clang-format off
   SuggestionTestData test_data[] = {
diff --git a/ios/chrome/browser/price_insights/model/BUILD.gn b/ios/chrome/browser/price_insights/model/BUILD.gn
index fdffb24..23bc0f6 100644
--- a/ios/chrome/browser/price_insights/model/BUILD.gn
+++ b/ios/chrome/browser/price_insights/model/BUILD.gn
@@ -17,12 +17,12 @@
     "//components/commerce/core/subscriptions",
     "//components/feature_engagement/public",
     "//components/keyed_service/core",
-    "//components/keyed_service/ios",
     "//components/strings",
     "//ios/chrome/browser/commerce/model:shopping_service",
     "//ios/chrome/browser/contextual_panel/model:public",
     "//ios/chrome/browser/price_insights/resources",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
     "//ios/chrome/browser/shared/ui/symbols",
     "//ios/web/public",
     "//ui/base",
diff --git a/ios/chrome/browser/price_insights/model/price_insights_model_factory.h b/ios/chrome/browser/price_insights/model/price_insights_model_factory.h
index ffa730d7..1b0cd2d 100644
--- a/ios/chrome/browser/price_insights/model/price_insights_model_factory.h
+++ b/ios/chrome/browser/price_insights/model/price_insights_model_factory.h
@@ -6,22 +6,17 @@
 #define IOS_CHROME_BROWSER_PRICE_INSIGHTS_MODEL_PRICE_INSIGHTS_MODEL_FACTORY_H_
 
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
+#import "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
 class PriceInsightsModel;
-class ProfileIOS;
 
 // Singleton that owns all PriceInsightsModels and associates them with
 // profile.
-class PriceInsightsModelFactory : public BrowserStateKeyedServiceFactory {
+class PriceInsightsModelFactory : public ProfileKeyedServiceFactoryIOS {
  public:
   static PriceInsightsModel* GetForProfile(ProfileIOS* profile);
   static PriceInsightsModelFactory* GetInstance();
 
-  PriceInsightsModelFactory(const PriceInsightsModelFactory&) = delete;
-  PriceInsightsModelFactory& operator=(const PriceInsightsModelFactory&) =
-      delete;
-
  private:
   friend class base::NoDestructor<PriceInsightsModelFactory>;
 
diff --git a/ios/chrome/browser/price_insights/model/price_insights_model_factory.mm b/ios/chrome/browser/price_insights/model/price_insights_model_factory.mm
index 831dffb..7f9bc43 100644
--- a/ios/chrome/browser/price_insights/model/price_insights_model_factory.mm
+++ b/ios/chrome/browser/price_insights/model/price_insights_model_factory.mm
@@ -5,15 +5,14 @@
 #import "ios/chrome/browser/price_insights/model/price_insights_model_factory.h"
 
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "ios/chrome/browser/price_insights/model/price_insights_model.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 
 // static
 PriceInsightsModel* PriceInsightsModelFactory::GetForProfile(
     ProfileIOS* profile) {
-  return static_cast<PriceInsightsModel*>(
-      GetInstance()->GetServiceForBrowserState(profile, true));
+  return GetInstance()->GetServiceForProfileAs<PriceInsightsModel>(
+      profile, /*create=*/true);
 }
 
 // static
@@ -23,9 +22,7 @@
 }
 
 PriceInsightsModelFactory::PriceInsightsModelFactory()
-    : BrowserStateKeyedServiceFactory(
-          "PriceInsightsModel",
-          BrowserStateDependencyManager::GetInstance()) {}
+    : ProfileKeyedServiceFactoryIOS("PriceInsightsModel") {}
 
 PriceInsightsModelFactory::~PriceInsightsModelFactory() {}
 
diff --git a/ios/chrome/browser/safe_browsing/model/hash_realtime_service_factory.h b/ios/chrome/browser/safe_browsing/model/hash_realtime_service_factory.h
index e89948d..a1e1d15 100644
--- a/ios/chrome/browser/safe_browsing/model/hash_realtime_service_factory.h
+++ b/ios/chrome/browser/safe_browsing/model/hash_realtime_service_factory.h
@@ -6,11 +6,10 @@
 #define IOS_CHROME_BROWSER_SAFE_BROWSING_MODEL_HASH_REALTIME_SERVICE_FACTORY_H_
 
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
+#import "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 #import "services/network/public/mojom/network_context.mojom.h"
 
 class KeyedService;
-class ProfileIOS;
 
 namespace safe_browsing {
 class HashRealTimeService;
@@ -18,16 +17,12 @@
 
 // Singleton that owns HashRealTimeService objects, one for each active profile.
 // It returns nullptr for incognito profiles.
-class HashRealTimeServiceFactory : public BrowserStateKeyedServiceFactory {
+class HashRealTimeServiceFactory : public ProfileKeyedServiceFactoryIOS {
  public:
   static safe_browsing::HashRealTimeService* GetForProfile(ProfileIOS* profile);
   // Returns the singleton instance of HashRealTimeServiceFactory.
   static HashRealTimeServiceFactory* GetInstance();
 
-  HashRealTimeServiceFactory(const HashRealTimeServiceFactory&) = delete;
-  HashRealTimeServiceFactory& operator=(const HashRealTimeServiceFactory&) =
-      delete;
-
  private:
   friend class base::NoDestructor<HashRealTimeServiceFactory>;
 
diff --git a/ios/chrome/browser/safe_browsing/model/hash_realtime_service_factory.mm b/ios/chrome/browser/safe_browsing/model/hash_realtime_service_factory.mm
index 7cdb632..4b4e3e6 100644
--- a/ios/chrome/browser/safe_browsing/model/hash_realtime_service_factory.mm
+++ b/ios/chrome/browser/safe_browsing/model/hash_realtime_service_factory.mm
@@ -5,7 +5,6 @@
 #import "ios/chrome/browser/safe_browsing/model/hash_realtime_service_factory.h"
 
 #import "base/feature_list.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service.h"
 #import "components/safe_browsing/core/browser/verdict_cache_manager.h"
 #import "ios/chrome/browser/safe_browsing/model/ohttp_key_service_factory.h"
@@ -25,8 +24,9 @@
 // static
 safe_browsing::HashRealTimeService* HashRealTimeServiceFactory::GetForProfile(
     ProfileIOS* profile) {
-  return static_cast<safe_browsing::HashRealTimeService*>(
-      GetInstance()->GetServiceForBrowserState(profile, true));
+  return GetInstance()
+      ->GetServiceForProfileAs<safe_browsing::HashRealTimeService>(
+          profile, /*create=*/true);
 }
 
 // static
@@ -36,9 +36,7 @@
 }
 
 HashRealTimeServiceFactory::HashRealTimeServiceFactory()
-    : BrowserStateKeyedServiceFactory(
-          "HashRealTimeService",
-          BrowserStateDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactoryIOS("HashRealTimeService") {
   DependsOn(VerdictCacheManagerFactory::GetInstance());
   DependsOn(OhttpKeyServiceFactory::GetInstance());
 }
diff --git a/ios/chrome/browser/scanner/ui_bundled/BUILD.gn b/ios/chrome/browser/scanner/ui_bundled/BUILD.gn
index e03f136..24bdae0 100644
--- a/ios/chrome/browser/scanner/ui_bundled/BUILD.gn
+++ b/ios/chrome/browser/scanner/ui_bundled/BUILD.gn
@@ -35,6 +35,7 @@
     "//ui/base",
   ]
   frameworks = [
+    "Accessibility.framework",
     "AVFoundation.framework",
     "UIKit.framework",
   ]
diff --git a/ios/chrome/browser/scanner/ui_bundled/scanner_alerts.mm b/ios/chrome/browser/scanner/ui_bundled/scanner_alerts.mm
index 250b463..6b00214 100644
--- a/ios/chrome/browser/scanner/ui_bundled/scanner_alerts.mm
+++ b/ios/chrome/browser/scanner/ui_bundled/scanner_alerts.mm
@@ -4,6 +4,8 @@
 
 #import "ios/chrome/browser/scanner/ui_bundled/scanner_alerts.h"
 
+#import <Accessibility/Accessibility.h>
+
 #import "base/notreached.h"
 #import "components/version_info/version_info.h"
 #import "ios/chrome/grit/ios_branded_strings.h"
@@ -51,7 +53,15 @@
     scanner::CancelAlertAction cancelBlock) {
   NSURL* settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
 
-  if (![[UIApplication sharedApplication] canOpenURL:settingsURL]) {
+  BOOL canGoToSettings =
+      [[UIApplication sharedApplication] canOpenURL:settingsURL];
+  // In Assistive Access, it's not possible to go to Settings, but
+  // `-[UIApplication canOpenURL:]` still returns YES. Detect Assistive Access
+  // (only available starting in iOS 18), and avoid sending to Settings.
+  if (@available(iOS 18, *)) {
+    canGoToSettings = canGoToSettings && !AXAssistiveAccessEnabled();
+  }
+  if (!canGoToSettings) {
     // Display a dialog instructing the user how to change the settings.
     NSString* dialogTitle =
         l10n_util::GetNSString(IDS_IOS_SCANNER_CAMERA_PERMISSIONS_HELP_TITLE);
diff --git a/ios/chrome/browser/sessions/model/BUILD.gn b/ios/chrome/browser/sessions/model/BUILD.gn
index 9fd0b56..78174572 100644
--- a/ios/chrome/browser/sessions/model/BUILD.gn
+++ b/ios/chrome/browser/sessions/model/BUILD.gn
@@ -365,11 +365,10 @@
     ":session_constants",
     "//build:branding_buildflags",
     "//components/keyed_service/core",
-    "//components/keyed_service/ios",
     "//components/strings",
     "//ios/chrome/browser/shared/model/browser",
-    "//ios/chrome/browser/shared/model/browser_state",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
     "//ios/chrome/browser/shared/model/url:constants",
     "//ios/chrome/browser/shared/model/web_state_list",
     "//ios/web/navigation:wk_navigation_util",
diff --git a/ios/chrome/browser/sessions/model/web_session_state_cache.h b/ios/chrome/browser/sessions/model/web_session_state_cache.h
index 8d34e540..1bac6d7 100644
--- a/ios/chrome/browser/sessions/model/web_session_state_cache.h
+++ b/ios/chrome/browser/sessions/model/web_session_state_cache.h
@@ -9,7 +9,6 @@
 
 #import "base/files/file_path.h"
 #import "base/functional/callback_forward.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
 
 class ProfileIOS;
 
diff --git a/ios/chrome/browser/sessions/model/web_session_state_cache_factory.h b/ios/chrome/browser/sessions/model/web_session_state_cache_factory.h
index 3fd4132c..9331299 100644
--- a/ios/chrome/browser/sessions/model/web_session_state_cache_factory.h
+++ b/ios/chrome/browser/sessions/model/web_session_state_cache_factory.h
@@ -8,22 +8,18 @@
 #import <memory>
 
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
+#import "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
 class ProfileIOS;
 @class WebSessionStateCache;
 
 // Singleton that owns all WebSessionStateCaches and associates them with
 // ProfileIOS.
-class WebSessionStateCacheFactory : public BrowserStateKeyedServiceFactory {
+class WebSessionStateCacheFactory : public ProfileKeyedServiceFactoryIOS {
  public:
   static WebSessionStateCache* GetForProfile(ProfileIOS* profile);
   static WebSessionStateCacheFactory* GetInstance();
 
-  WebSessionStateCacheFactory(const WebSessionStateCacheFactory&) = delete;
-  WebSessionStateCacheFactory& operator=(const WebSessionStateCacheFactory&) =
-      delete;
-
  private:
   friend class base::NoDestructor<WebSessionStateCacheFactory>;
 
@@ -33,8 +29,6 @@
   // BrowserStateKeyedServiceFactory implementation.
   std::unique_ptr<KeyedService> BuildServiceInstanceFor(
       web::BrowserState* context) const override;
-  web::BrowserState* GetBrowserStateToUse(
-      web::BrowserState* context) const override;
 };
 
 #endif  // IOS_CHROME_BROWSER_SESSIONS_MODEL_WEB_SESSION_STATE_CACHE_FACTORY_H_
diff --git a/ios/chrome/browser/sessions/model/web_session_state_cache_factory.mm b/ios/chrome/browser/sessions/model/web_session_state_cache_factory.mm
index 6fc25df..74c40c0 100644
--- a/ios/chrome/browser/sessions/model/web_session_state_cache_factory.mm
+++ b/ios/chrome/browser/sessions/model/web_session_state_cache_factory.mm
@@ -7,14 +7,11 @@
 #import "base/functional/bind.h"
 #import "base/logging.h"
 #import "base/memory/ptr_util.h"
-#import "base/no_destructor.h"
 #import "components/keyed_service/core/keyed_service.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "ios/chrome/browser/sessions/model/web_session_state_cache.h"
 #import "ios/chrome/browser/sessions/model/web_session_state_cache_web_state_list_observer.h"
 #import "ios/chrome/browser/shared/model/browser/all_web_state_list_observation_registrar.h"
 #import "ios/chrome/browser/shared/model/browser/browser_list_factory.h"
-#import "ios/chrome/browser/shared/model/browser_state/browser_state_otr_helper.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 
 namespace {
@@ -76,8 +73,8 @@
 WebSessionStateCache* WebSessionStateCacheFactory::GetForProfile(
     ProfileIOS* profile) {
   WebSessionStateCacheWrapper* wrapper =
-      static_cast<WebSessionStateCacheWrapper*>(
-          GetInstance()->GetServiceForBrowserState(profile, true));
+      GetInstance()->GetServiceForProfileAs<WebSessionStateCacheWrapper>(
+          profile, /*create=*/true);
   return wrapper ? wrapper->web_session_state_cache() : nil;
 }
 
@@ -88,9 +85,8 @@
 }
 
 WebSessionStateCacheFactory::WebSessionStateCacheFactory()
-    : BrowserStateKeyedServiceFactory(
-          "WebSessionStateCache",
-          BrowserStateDependencyManager::GetInstance()) {}
+    : ProfileKeyedServiceFactoryIOS("WebSessionStateCache",
+                                    ProfileSelection::kRedirectedInIncognito) {}
 
 WebSessionStateCacheFactory::~WebSessionStateCacheFactory() = default;
 
@@ -99,8 +95,3 @@
     web::BrowserState* context) const {
   return BuildWebSessionStateCacheWrapper(context);
 }
-
-web::BrowserState* WebSessionStateCacheFactory::GetBrowserStateToUse(
-    web::BrowserState* context) const {
-  return GetBrowserStateRedirectedInIncognito(context);
-}
diff --git a/ios/chrome/browser/settings/ui_bundled/autofill/autofill_credit_card_edit_table_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/autofill/autofill_credit_card_edit_table_view_controller.mm
index 786ed8a..81a24e8 100644
--- a/ios/chrome/browser/settings/ui_bundled/autofill/autofill_credit_card_edit_table_view_controller.mm
+++ b/ios/chrome/browser/settings/ui_bundled/autofill/autofill_credit_card_edit_table_view_controller.mm
@@ -10,8 +10,8 @@
 #import "base/ios/block_types.h"
 #import "base/memory/raw_ptr.h"
 #import "base/strings/sys_string_conversions.h"
-#import "components/autofill/core/browser/autofill_data_util.h"
 #import "components/autofill/core/browser/data_model/credit_card.h"
+#import "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #import "components/autofill/core/browser/field_types.h"
 #import "components/autofill/core/browser/payments/payments_service_url.h"
 #import "components/autofill/core/browser/payments_data_manager.h"
diff --git a/ios/chrome/browser/settings/ui_bundled/autofill/autofill_profile_edit_coordinator.mm b/ios/chrome/browser/settings/ui_bundled/autofill/autofill_profile_edit_coordinator.mm
index f36323c..65d3f3f 100644
--- a/ios/chrome/browser/settings/ui_bundled/autofill/autofill_profile_edit_coordinator.mm
+++ b/ios/chrome/browser/settings/ui_bundled/autofill/autofill_profile_edit_coordinator.mm
@@ -6,8 +6,8 @@
 
 #import "base/apple/foundation_util.h"
 #import "base/strings/sys_string_conversions.h"
-#import "components/autofill/core/browser/autofill_data_util.h"
 #import "components/autofill/core/browser/data_model/autofill_profile.h"
+#import "components/autofill/core/browser/data_quality/autofill_data_util.h"
 #import "components/autofill/core/browser/personal_data_manager.h"
 #import "components/autofill/ios/browser/personal_data_manager_observer_bridge.h"
 #import "ios/chrome/browser/autofill/model/personal_data_manager_factory.h"
diff --git a/ios/chrome/browser/settings/ui_bundled/autofill/autofill_profile_table_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/autofill/autofill_profile_table_view_controller.mm
index 1eb980a..3543332 100644
--- a/ios/chrome/browser/settings/ui_bundled/autofill/autofill_profile_table_view_controller.mm
+++ b/ios/chrome/browser/settings/ui_bundled/autofill/autofill_profile_table_view_controller.mm
@@ -13,8 +13,8 @@
 #import "base/strings/sys_string_conversions.h"
 #import "base/strings/utf_string_conversions.h"
 #import "components/autofill/core/browser/address_data_manager.h"
+#import "components/autofill/core/browser/data_quality/addresses/profile_requirement_utils.h"
 #import "components/autofill/core/browser/personal_data_manager.h"
-#import "components/autofill/core/browser/profile_requirement_utils.h"
 #import "components/autofill/core/common/autofill_features.h"
 #import "components/autofill/core/common/autofill_prefs.h"
 #import "components/autofill/ios/browser/personal_data_manager_observer_bridge.h"
diff --git a/ios/chrome/browser/shared/coordinator/alert/alert_coordinator.h b/ios/chrome/browser/shared/coordinator/alert/alert_coordinator.h
index d5676836..6a12d2d 100644
--- a/ios/chrome/browser/shared/coordinator/alert/alert_coordinator.h
+++ b/ios/chrome/browser/shared/coordinator/alert/alert_coordinator.h
@@ -27,8 +27,8 @@
 // Whether the alert is visible. This will be true after `-start` is called
 // until a subsequent `-stop`.
 @property(nonatomic, readonly, getter=isVisible) BOOL visible;
-// Block called when the alert is stopped with `stop` or during dealloc. It is
-// called only if no interaction with the alert has occurred.
+// Block called synchronously when the alert is stopped with `stop` or during
+// dealloc. It is called only if no interaction with the alert has occurred.
 @property(nonatomic, copy) ProceduralBlock noInteractionAction;
 
 // Init a coordinator for displaying a alert on this view controller.
diff --git a/ios/chrome/browser/shared/ui/util/omnibox_util.h b/ios/chrome/browser/shared/ui/util/omnibox_util.h
index 03225fb..e6d4594 100644
--- a/ios/chrome/browser/shared/ui/util/omnibox_util.h
+++ b/ios/chrome/browser/shared/ui/util/omnibox_util.h
@@ -8,10 +8,8 @@
 #import <UIKit/UIKit.h>
 
 class Browser;
-@class LayoutGuideCenter;
 
 /// Returns true if the omnibox is at the bottom in the current layout.
-bool IsCurrentLayoutBottomOmnibox(LayoutGuideCenter* layout_guide_center);
 bool IsCurrentLayoutBottomOmnibox(Browser* browser);
 
 #endif  // IOS_CHROME_BROWSER_SHARED_UI_UTIL_OMNIBOX_UTIL_H_
diff --git a/ios/chrome/browser/signin/model/authentication_service.mm b/ios/chrome/browser/signin/model/authentication_service.mm
index 9c24f13..8a14da4 100644
--- a/ios/chrome/browser/signin/model/authentication_service.mm
+++ b/ios/chrome/browser/signin/model/authentication_service.mm
@@ -510,6 +510,10 @@
   crash_keys::SetCurrentlySignedIn(false);
   cached_mdm_errors_.clear();
 
+  // ClearPrimaryAccount() removed all the accounts from IdentityManager.
+  // Populate them again.
+  ReloadCredentialsFromIdentities();
+
   base::OnceClosure callback_closure =
       completion ? base::BindOnce(completion) : base::DoNothing();
 
diff --git a/ios/chrome/browser/signin/model/authentication_service_unittest.mm b/ios/chrome/browser/signin/model/authentication_service_unittest.mm
index a01250b..309064b 100644
--- a/ios/chrome/browser/signin/model/authentication_service_unittest.mm
+++ b/ios/chrome/browser/signin/model/authentication_service_unittest.mm
@@ -12,6 +12,7 @@
 #import "base/memory/raw_ptr.h"
 #import "base/run_loop.h"
 #import "base/strings/sys_string_conversions.h"
+#import "base/task/sequenced_task_runner.h"
 #import "base/test/bind.h"
 #import "base/test/gtest_util.h"
 #import "base/test/metrics/histogram_tester.h"
@@ -143,6 +144,13 @@
     return prefs;
   }
 
+  void FlushTaskRunner() {
+    base::RunLoop loop;
+    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
+        FROM_HERE, loop.QuitClosure());
+    loop.Run();
+  }
+
   void VerifyLastSigninTimestamp() {
     EXPECT_EQ(profile_.get()->GetPrefs()->GetTime(prefs::kLastSigninTimestamp),
               base::Time::Now());
@@ -500,7 +508,7 @@
 TEST_P(AuthenticationServiceTest, MDMErrorsClearedOnSignout) {
   authentication_service()->SignIn(
       identity(0), signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN);
-  EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 2UL);
+  ASSERT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 2UL);
   VerifyLastSigninTimestamp();
 
   SetCachedMDMInfo(identity(0), CreateRefreshAccessTokenError(identity(0)));
@@ -508,7 +516,7 @@
       signin_metrics::ProfileSignout::kAbortSignin,
       /*force_clear_browsing_data=*/false, nil);
   EXPECT_FALSE(HasCachedMDMInfo(identity(0)));
-  EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 0UL);
+  EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 2UL);
   EXPECT_EQ(ClearBrowsingDataCount(), 0);
 }
 
@@ -518,7 +526,7 @@
        MDMErrorsClearedOnSignoutAndClearBrowsingData) {
   authentication_service()->SignIn(
       identity(0), signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN);
-  EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 2UL);
+  ASSERT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 2UL);
   VerifyLastSigninTimestamp();
 
   SetCachedMDMInfo(identity(0), CreateRefreshAccessTokenError(identity(0)));
@@ -526,7 +534,7 @@
       signin_metrics::ProfileSignout::kAbortSignin,
       /*force_clear_browsing_data=*/true, nil);
   EXPECT_FALSE(HasCachedMDMInfo(identity(0)));
-  EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 0UL);
+  EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 2UL);
   EXPECT_EQ(ClearBrowsingDataCount(), 1);
 }
 
@@ -540,6 +548,10 @@
   FakeSystemIdentity* fake_system_identity =
       [FakeSystemIdentity fakeManagedIdentity];
   fake_system_identity_manager()->AddIdentity(fake_system_identity);
+  ASSERT_EQ([account_manager_->GetAllIdentities() count], 3UL);
+  // IdentityManager is updated via a posted task; wait for that to happen.
+  FlushTaskRunner();
+  ASSERT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 3UL);
 
   authentication_service()->SignIn(
       identity(2), signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN);
@@ -553,7 +565,7 @@
       signin_metrics::ProfileSignout::kAbortSignin,
       /*force_clear_browsing_data=*/false, nil);
   EXPECT_FALSE(HasCachedMDMInfo(identity(2)));
-  EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 0UL);
+  EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 3UL);
   EXPECT_EQ(ClearBrowsingDataCount(), 0);
 }
 
@@ -566,11 +578,15 @@
   FakeSystemIdentity* fake_system_identity =
       [FakeSystemIdentity fakeManagedIdentity];
   fake_system_identity_manager()->AddIdentity(fake_system_identity);
+  ASSERT_EQ([account_manager_->GetAllIdentities() count], 3UL);
+  // IdentityManager is updated via a posted task; wait for that to happen.
+  FlushTaskRunner();
+  ASSERT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 3UL);
 
   authentication_service()->SignIn(
       identity(2), signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN);
-  EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 3UL);
-  EXPECT_TRUE(authentication_service()->HasPrimaryIdentityManaged(
+  ASSERT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 3UL);
+  ASSERT_TRUE(authentication_service()->HasPrimaryIdentityManaged(
       signin::ConsentLevel::kSignin));
   VerifyLastSigninTimestamp();
 
@@ -582,7 +598,7 @@
       signin_metrics::ProfileSignout::kUserClickedSignoutSettings,
       /*force_clear_browsing_data=*/false, nil);
   EXPECT_FALSE(HasCachedMDMInfo(identity(2)));
-  EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 0UL);
+  EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 3UL);
   EXPECT_EQ(ClearBrowsingDataFromSigninCount(), 1);
 }
 
@@ -601,6 +617,10 @@
   FakeSystemIdentity* fake_system_identity =
       [FakeSystemIdentity fakeManagedIdentity];
   fake_system_identity_manager()->AddIdentity(fake_system_identity);
+  ASSERT_EQ([account_manager_->GetAllIdentities() count], 3UL);
+  // IdentityManager is updated via a posted task; wait for that to happen.
+  FlushTaskRunner();
+  ASSERT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 3UL);
 
   authentication_service()->SignIn(
       identity(2), signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN);
@@ -615,7 +635,7 @@
       signin_metrics::ProfileSignout::kAbortSignin,
       /*force_clear_browsing_data=*/false, nil);
   ASSERT_FALSE(HasCachedMDMInfo(identity(2)));
-  ASSERT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 0UL);
+  ASSERT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 3UL);
   EXPECT_EQ(ClearBrowsingDataCount(), 0);
   EXPECT_EQ(ClearBrowsingDataFromSigninCount(), 0);
   [userDefaults removeObjectForKey:kPolicyLoaderIOSConfigurationKey];
@@ -633,6 +653,10 @@
   FakeSystemIdentity* fake_system_identity =
       [FakeSystemIdentity fakeManagedIdentity];
   fake_system_identity_manager()->AddIdentity(fake_system_identity);
+  ASSERT_EQ([account_manager_->GetAllIdentities() count], 3UL);
+  // IdentityManager is updated via a posted task; wait for that to happen.
+  FlushTaskRunner();
+  ASSERT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 3UL);
 
   authentication_service()->SignIn(
       identity(2), signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN);
@@ -660,7 +684,7 @@
       signin_metrics::ProfileSignout::kAbortSignin,
       /*force_clear_browsing_data=*/false, nil);
   ASSERT_FALSE(HasCachedMDMInfo(identity(2)));
-  ASSERT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 0UL);
+  ASSERT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 3UL);
   EXPECT_EQ(ClearBrowsingDataCount(), 1);
   EXPECT_EQ(ClearBrowsingDataFromSigninCount(), 0);
 }
@@ -671,7 +695,7 @@
 TEST_P(AuthenticationServiceTest, MDMErrorsDontSeedEmptyAccountIds) {
   authentication_service()->SignIn(
       identity(0), signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN);
-  EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 2UL);
+  ASSERT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 2UL);
   VerifyLastSigninTimestamp();
 
   SetCachedMDMInfo(identity(0), CreateRefreshAccessTokenError(identity(0)));
@@ -705,6 +729,10 @@
   FakeSystemIdentity* fake_system_identity =
       [FakeSystemIdentity fakeManagedIdentity];
   fake_system_identity_manager()->AddIdentity(fake_system_identity);
+  ASSERT_EQ([account_manager_->GetAllIdentities() count], 3UL);
+  // IdentityManager is updated via a posted task; wait for that to happen.
+  FlushTaskRunner();
+  ASSERT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 3UL);
 
   authentication_service()->SignIn(
       identity(2), signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN);
@@ -720,7 +748,7 @@
       signin_metrics::ProfileSignout::kAbortSignin,
       /*force_clear_browsing_data=*/false, nil);
   EXPECT_FALSE(HasCachedMDMInfo(identity(2)));
-  EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 0UL);
+  EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 3UL);
   EXPECT_EQ(ClearBrowsingDataCount(), 1);
 }
 
@@ -734,6 +762,10 @@
   FakeSystemIdentity* fake_system_identity =
       [FakeSystemIdentity fakeManagedIdentity];
   fake_system_identity_manager()->AddIdentity(fake_system_identity);
+  ASSERT_EQ([account_manager_->GetAllIdentities() count], 3UL);
+  // IdentityManager is updated via a posted task; wait for that to happen.
+  FlushTaskRunner();
+  ASSERT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 3UL);
 
   authentication_service()->SignIn(
       identity(2), signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN);
@@ -748,7 +780,7 @@
       signin_metrics::ProfileSignout::kAbortSignin,
       /*force_clear_browsing_data=*/true, nil);
   EXPECT_FALSE(HasCachedMDMInfo(identity(2)));
-  EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 0UL);
+  EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 3UL);
   EXPECT_EQ(ClearBrowsingDataCount(), 1);
 }
 
diff --git a/ios/chrome/browser/supervised_user/model/BUILD.gn b/ios/chrome/browser/supervised_user/model/BUILD.gn
index 2f11423..e5af6a7 100644
--- a/ios/chrome/browser/supervised_user/model/BUILD.gn
+++ b/ios/chrome/browser/supervised_user/model/BUILD.gn
@@ -29,7 +29,6 @@
   deps = [
     ":capabilities",
     ":sync_settings_factory",
-    "//components/keyed_service/core",
     "//components/keyed_service/ios",
     "//components/prefs",
     "//components/security_interstitials/core",
@@ -85,10 +84,9 @@
     "supervised_user_settings_service_factory.mm",
   ]
   deps = [
-    "//components/keyed_service/ios",
     "//components/supervised_user/core/browser",
-    "//ios/chrome/browser/shared/model/browser_state",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
   ]
 }
 
diff --git a/ios/chrome/browser/supervised_user/model/supervised_user_settings_service_factory.h b/ios/chrome/browser/supervised_user/model/supervised_user_settings_service_factory.h
index 0abdfa9..0f8f137 100644
--- a/ios/chrome/browser/supervised_user/model/supervised_user_settings_service_factory.h
+++ b/ios/chrome/browser/supervised_user/model/supervised_user_settings_service_factory.h
@@ -6,9 +6,7 @@
 #define IOS_CHROME_BROWSER_SUPERVISED_USER_MODEL_SUPERVISED_USER_SETTINGS_SERVICE_FACTORY_H_
 
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
-
-class ProfileIOS;
+#import "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
 namespace supervised_user {
 class SupervisedUserSettingsService;
@@ -17,17 +15,12 @@
 // Singleton that owns SupervisedUserSettingsService object and associates
 // them with ProfileIOS.
 class SupervisedUserSettingsServiceFactory
-    : public BrowserStateKeyedServiceFactory {
+    : public ProfileKeyedServiceFactoryIOS {
  public:
   static supervised_user::SupervisedUserSettingsService* GetForProfile(
       ProfileIOS* profile);
   static SupervisedUserSettingsServiceFactory* GetInstance();
 
-  SupervisedUserSettingsServiceFactory(
-      const SupervisedUserSettingsServiceFactory&) = delete;
-  SupervisedUserSettingsServiceFactory& operator=(
-      const SupervisedUserSettingsServiceFactory&) = delete;
-
  private:
   friend class base::NoDestructor<SupervisedUserSettingsServiceFactory>;
 
@@ -38,8 +31,6 @@
   bool ServiceIsRequiredForContextInitialization() const override;
   std::unique_ptr<KeyedService> BuildServiceInstanceFor(
       web::BrowserState* context) const override;
-  web::BrowserState* GetBrowserStateToUse(
-      web::BrowserState* context) const override;
 };
 
 #endif  // IOS_CHROME_BROWSER_SUPERVISED_USER_MODEL_SUPERVISED_USER_SETTINGS_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/supervised_user/model/supervised_user_settings_service_factory.mm b/ios/chrome/browser/supervised_user/model/supervised_user_settings_service_factory.mm
index 8c09604..d31346b9 100644
--- a/ios/chrome/browser/supervised_user/model/supervised_user_settings_service_factory.mm
+++ b/ios/chrome/browser/supervised_user/model/supervised_user_settings_service_factory.mm
@@ -5,16 +5,15 @@
 #import "ios/chrome/browser/supervised_user/model/supervised_user_settings_service_factory.h"
 
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "components/supervised_user/core/browser/supervised_user_settings_service.h"
-#import "ios/chrome/browser/shared/model/browser_state/browser_state_otr_helper.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 
 // static
 supervised_user::SupervisedUserSettingsService*
 SupervisedUserSettingsServiceFactory::GetForProfile(ProfileIOS* profile) {
-  return static_cast<supervised_user::SupervisedUserSettingsService*>(
-      GetInstance()->GetServiceForBrowserState(profile, true));
+  return GetInstance()
+      ->GetServiceForProfileAs<supervised_user::SupervisedUserSettingsService>(
+          profile, /*create=*/true);
 }
 
 // static
@@ -25,9 +24,9 @@
 }
 
 SupervisedUserSettingsServiceFactory::SupervisedUserSettingsServiceFactory()
-    : BrowserStateKeyedServiceFactory(
-          "SupervisedUserSettingsService",
-          BrowserStateDependencyManager::GetInstance()) {}
+    : ProfileKeyedServiceFactoryIOS("SupervisedUserSettingsService",
+                                    ProfileSelection::kOwnInstanceInIncognito) {
+}
 
 bool SupervisedUserSettingsServiceFactory::
     ServiceIsRequiredForContextInitialization() const {
@@ -42,8 +41,3 @@
     web::BrowserState* context) const {
   return std::make_unique<supervised_user::SupervisedUserSettingsService>();
 }
-
-web::BrowserState* SupervisedUserSettingsServiceFactory::GetBrowserStateToUse(
-    web::BrowserState* context) const {
-  return GetBrowserStateOwnInstanceInIncognito(context);
-}
diff --git a/ios/chrome/browser/sync/model/BUILD.gn b/ios/chrome/browser/sync/model/BUILD.gn
index 6a7ea2d..64c4de7 100644
--- a/ios/chrome/browser/sync/model/BUILD.gn
+++ b/ios/chrome/browser/sync/model/BUILD.gn
@@ -198,8 +198,6 @@
     ":model",
     "//base",
     "//components/consent_auditor:test_support",
-    "//components/keyed_service/core",
-    "//components/keyed_service/ios",
     "//components/sync",
     "//components/sync:test_support",
     "//ios/chrome/common",
diff --git a/ios/chrome/browser/sync/model/session_sync_service_factory.h b/ios/chrome/browser/sync/model/session_sync_service_factory.h
index 4b03220e..633cd9d 100644
--- a/ios/chrome/browser/sync/model/session_sync_service_factory.h
+++ b/ios/chrome/browser/sync/model/session_sync_service_factory.h
@@ -8,10 +8,9 @@
 #import <memory>
 
 #import "base/no_destructor.h"
-#import "components/keyed_service/ios/browser_state_keyed_service_factory.h"
+#import "ios/chrome/browser/shared/model/profile/profile_keyed_service_factory_ios.h"
 
 class GURL;
-class ProfileIOS;
 
 namespace sync_sessions {
 class SessionSyncService;
@@ -19,15 +18,11 @@
 
 // Singleton that owns all SessionSyncService and associates them with
 // ProfileIOS.
-class SessionSyncServiceFactory : public BrowserStateKeyedServiceFactory {
+class SessionSyncServiceFactory : public ProfileKeyedServiceFactoryIOS {
  public:
   static sync_sessions::SessionSyncService* GetForProfile(ProfileIOS* profile);
   static SessionSyncServiceFactory* GetInstance();
 
-  SessionSyncServiceFactory(const SessionSyncServiceFactory&) = delete;
-  SessionSyncServiceFactory& operator=(const SessionSyncServiceFactory&) =
-      delete;
-
   static bool ShouldSyncURLForTesting(const GURL& url);
 
  private:
diff --git a/ios/chrome/browser/sync/model/session_sync_service_factory.mm b/ios/chrome/browser/sync/model/session_sync_service_factory.mm
index 969aa6df..09cf93d0 100644
--- a/ios/chrome/browser/sync/model/session_sync_service_factory.mm
+++ b/ios/chrome/browser/sync/model/session_sync_service_factory.mm
@@ -13,7 +13,6 @@
 #import "components/dom_distiller/core/url_constants.h"
 #import "components/history/core/browser/history_service.h"
 #import "components/keyed_service/core/service_access_type.h"
-#import "components/keyed_service/ios/browser_state_dependency_manager.h"
 #import "components/sync/model/data_type_store_service.h"
 #import "components/sync/service/sync_service.h"
 #import "components/sync_device_info/device_info_sync_service.h"
@@ -142,20 +141,18 @@
 // static
 SessionSyncService* SessionSyncServiceFactory::GetForProfile(
     ProfileIOS* profile) {
-  return static_cast<SessionSyncService*>(
-      GetInstance()->GetServiceForBrowserState(profile, true));
+  return GetInstance()->GetServiceForProfileAs<SessionSyncService>(
+      profile, /*create=*/true);
 }
 
 SessionSyncServiceFactory::SessionSyncServiceFactory()
-    : BrowserStateKeyedServiceFactory(
-          "SessionSyncService",
-          BrowserStateDependencyManager::GetInstance()) {
+    : ProfileKeyedServiceFactoryIOS("SessionSyncService") {
   DependsOn(ios::HistoryServiceFactory::GetInstance());
   DependsOn(DataTypeStoreServiceFactory::GetInstance());
   DependsOn(DeviceInfoSyncServiceFactory::GetInstance());
 }
 
-SessionSyncServiceFactory::~SessionSyncServiceFactory() {}
+SessionSyncServiceFactory::~SessionSyncServiceFactory() = default;
 
 std::unique_ptr<KeyedService>
 SessionSyncServiceFactory::BuildServiceInstanceFor(
diff --git a/ios/chrome/browser/ui/authentication/account_menu/BUILD.gn b/ios/chrome/browser/ui/authentication/account_menu/BUILD.gn
index aff3eb9..b4d09a8 100644
--- a/ios/chrome/browser/ui/authentication/account_menu/BUILD.gn
+++ b/ios/chrome/browser/ui/authentication/account_menu/BUILD.gn
@@ -124,6 +124,7 @@
     "//ios/chrome/browser/shared/model/browser/test:test_support",
     "//ios/chrome/browser/shared/model/profile/test",
     "//ios/chrome/browser/shared/public/commands",
+    "//ios/chrome/browser/shared/public/features",
     "//ios/chrome/browser/shared/ui/table_view:utils",
     "//ios/chrome/browser/shared/ui/util/identity_snackbar",
     "//ios/chrome/browser/signin/model",
diff --git a/ios/chrome/browser/ui/authentication/account_menu/account_menu_coordinator.mm b/ios/chrome/browser/ui/authentication/account_menu/account_menu_coordinator.mm
index f37c5ac..fd4ce6df 100644
--- a/ios/chrome/browser/ui/authentication/account_menu/account_menu_coordinator.mm
+++ b/ios/chrome/browser/ui/authentication/account_menu/account_menu_coordinator.mm
@@ -54,6 +54,7 @@
 #import "ios/chrome/browser/ui/authentication/account_menu/account_menu_view_controller.h"
 #import "ios/chrome/browser/ui/authentication/authentication_flow.h"
 #import "ios/chrome/browser/ui/authentication/signin/add_account_signin/add_account_signin_coordinator.h"
+#import "ios/chrome/browser/ui/authentication/signin/interruptible_chrome_coordinator.h"
 #import "ios/chrome/browser/ui/authentication/signin/signin_constants.h"
 #import "ios/chrome/browser/ui/authentication/signin/signin_coordinator+protected.h"
 #import "ios/chrome/browser/ui/authentication/signin/signin_coordinator.h"
@@ -442,8 +443,14 @@
       completion();
     }
   };
-  [self stopChildrenAndViewControllerWithAction:action
-                                     completion:childrenCompletion];
+  if (base::FeatureList::IsEnabled(
+          kIOSInterruptibleChromeStoppedSynchronously)) {
+    [self stopChildrenAndViewControllerWithAction:action completion:nil];
+    childrenCompletion();
+  } else {
+    [self stopChildrenAndViewControllerWithAction:action
+                                       completion:childrenCompletion];
+  }
 }
 
 #pragma mark - ManageAccountsCoordinatorDelegate
@@ -539,9 +546,8 @@
   _signoutActionSheetCoordinator = nil;
 }
 
-// Stops all children, then dismiss the view controller, then execute
-// `completion`. If `dismiss` is YES, dismiss the add account coordinator if it
-// is present.
+// Stops all children, then dismiss the view controller. Executes
+// `completion` synchronously.
 - (void)stopChildrenAndViewControllerWithAction:
             (SigninCoordinatorInterrupt)action
                                      completion:(ProceduralBlock)completion {
diff --git a/ios/chrome/browser/ui/authentication/account_menu/account_menu_coordinator_unittests.mm b/ios/chrome/browser/ui/authentication/account_menu/account_menu_coordinator_unittests.mm
index 087a3f9..af9aa9b 100644
--- a/ios/chrome/browser/ui/authentication/account_menu/account_menu_coordinator_unittests.mm
+++ b/ios/chrome/browser/ui/authentication/account_menu/account_menu_coordinator_unittests.mm
@@ -7,6 +7,7 @@
 #import <MaterialComponents/MaterialSnackbar.h>
 
 #import "base/memory/raw_ptr.h"
+#import "base/test/scoped_feature_list.h"
 #import "components/sync/service/sync_service_utils.h"
 #import "components/trusted_vault/trusted_vault_server_constants.h"
 #import "ios/chrome/browser/settings/ui_bundled/sync/sync_encryption_passphrase_table_view_controller.h"
@@ -22,6 +23,7 @@
 #import "ios/chrome/browser/shared/public/commands/settings_commands.h"
 #import "ios/chrome/browser/shared/public/commands/show_signin_command.h"
 #import "ios/chrome/browser/shared/public/commands/snackbar_commands.h"
+#import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/shared/ui/util/identity_snackbar/identity_snackbar_message.h"
 #import "ios/chrome/browser/signin/model/authentication_service.h"
 #import "ios/chrome/browser/signin/model/authentication_service_factory.h"
@@ -63,8 +65,16 @@
 
 @end
 
-class AccountMenuCoordinatorTest : public PlatformTest {
+// The test param determines whether `kSeparateProfilesForManagedAccounts` is
+// enabled.
+class AccountMenuCoordinatorTest : public PlatformTest,
+                                   public testing::WithParamInterface<bool> {
  public:
+  AccountMenuCoordinatorTest() {
+    feature_list_.InitWithFeatureState(kSeparateProfilesForManagedAccounts,
+                                       GetParam());
+  }
+
   void SetUp() override {
     PlatformTest::SetUp();
     scene_state_ = [[SceneState alloc] initWithAppState:nil];
@@ -165,6 +175,8 @@
                  completion:nil];
   }
 
+  base::test::ScopedFeatureList feature_list_;
+
   AccountMenuCoordinator<UIAdaptivePresentationControllerDelegate>*
       coordinator_;
   id<ApplicationCommands> mock_application_commands_handler_;
@@ -229,7 +241,7 @@
 
 // Tests that `didTapManageYourGoogleAccount` requests the view controller to
 // present a view.
-TEST_F(AccountMenuCoordinatorNonManagedTest, testManageYourGoogleAccount) {
+TEST_P(AccountMenuCoordinatorNonManagedTest, testManageYourGoogleAccount) {
   OCMExpect([view_controller_ presentViewController:[OCMArg any]
                                            animated:YES
                                          completion:nil]);
@@ -239,14 +251,14 @@
 
 // Tests that `didTapManageAccounts` has no impact on the view controller and
 // mediator.
-TEST_F(AccountMenuCoordinatorNonManagedTest, testEditAccountList) {
+TEST_P(AccountMenuCoordinatorNonManagedTest, testEditAccountList) {
   [coordinator_ didTapManageAccounts];
   assertOpenAndInterrupt();
 }
 
 // Tests that `signOutFromTargetRect` requests the delegate to be stopped and
 // shows a snackbar and calls its completion.
-TEST_F(AccountMenuCoordinatorNonManagedTest, testSignOut) {
+TEST_P(AccountMenuCoordinatorNonManagedTest, testSignOut) {
   base::RunLoop run_loop;
   base::RepeatingClosure closure = run_loop.QuitClosure();
   CGRect rect = CGRect();
@@ -267,13 +279,13 @@
 
 // Tests that `mediatorWantsToBeDismissed` requests to the delegate to stop the
 // coordinator.
-TEST_F(AccountMenuCoordinatorNonManagedTest, testMediatorWantsToBeDismissed) {
+TEST_P(AccountMenuCoordinatorNonManagedTest, testMediatorWantsToBeDismissed) {
   assertOpenAndInterrupt();
 }
 
 // Tests that `triggerSignoutWithTargetRect` calls its
 // callback.
-TEST_F(AccountMenuCoordinatorNonManagedTest, testTriggerSignout) {
+TEST_P(AccountMenuCoordinatorNonManagedTest, testTriggerSignout) {
   OCMExpect([mock_snackbar_commands_handler_
       showSnackbarMessageOverBrowserToolbar:[OCMArg any]]);
 
@@ -291,7 +303,7 @@
 }
 
 // Tests that `triggerSigninWithSystemIdentity` call its completion.
-TEST_F(AccountMenuCoordinatorNonManagedTest, testSignin) {
+TEST_P(AccountMenuCoordinatorNonManagedTest, testSignin) {
   base::RunLoop run_loop;
   base::RepeatingClosure closure = run_loop.QuitClosure();
   AuthenticationFlow* authentication_flow = [coordinator_
@@ -309,7 +321,7 @@
 }
 
 // Tests that `triggerAccountSwitchSnackbarWithIdentity` shows a snackbar.
-TEST_F(AccountMenuCoordinatorNonManagedTest, testSnackbar) {
+TEST_P(AccountMenuCoordinatorNonManagedTest, testSnackbar) {
   OCMExpect([mock_snackbar_commands_handler_
       showSnackbarMessageOverBrowserToolbar:[OCMArg checkWithBlock:^BOOL(
                                                         IdentitySnackbarMessage*
@@ -323,7 +335,7 @@
 
 // Tests that `triggerAccountSwitchSnackbarWithIdentity` shows a snackbar with
 // `managed` set to true.
-TEST_F(AccountMenuCoordinatorManagedTest, testSnackbarManaged) {
+TEST_P(AccountMenuCoordinatorManagedTest, testSnackbarManaged) {
   OCMExpect([mock_snackbar_commands_handler_
       showSnackbarMessageOverBrowserToolbar:[OCMArg checkWithBlock:^BOOL(
                                                         IdentitySnackbarMessage*
@@ -341,7 +353,7 @@
 // view controller and mediator. Tests also that the
 // `SyncEncryptionPassphraseTableViewController` is allocated, and the view is
 // correctly closed when the coordinator is stopped.
-TEST_F(AccountMenuCoordinatorNonManagedTest, testPassphrase) {
+TEST_P(AccountMenuCoordinatorNonManagedTest, testPassphrase) {
   SyncEncryptionPassphraseTableViewController* passphraseViewController =
       [SyncEncryptionPassphraseTableViewController alloc];
   id classMock =
@@ -353,21 +365,37 @@
 
 // Tests that `openTrustedVaultReauthForFetchKeys` calls
 // `showTrustedVaultReauthForFetchKeysFromViewController`.
-TEST_F(AccountMenuCoordinatorNonManagedTest, testFetchKeys) {
+TEST_P(AccountMenuCoordinatorNonManagedTest, testFetchKeys) {
   [coordinator_ openTrustedVaultReauthForFetchKeys];
   assertOpenAndInterrupt();
 }
 
 // Tests that `openTrustedVaultReauthForDegradedRecoverability` calls
 // `showTrustedVaultReauthForDegradedRecoverabilityFromViewController`.
-TEST_F(AccountMenuCoordinatorNonManagedTest, testDegradedRecoverability) {
+TEST_P(AccountMenuCoordinatorNonManagedTest, testDegradedRecoverability) {
   [coordinator_ openTrustedVaultReauthForDegradedRecoverability];
   assertOpenAndInterrupt();
 }
 
 // Tests that `openMDMErrodDialogWithSystemIdentity` has no effects on the
 // mediator and view controller.
-TEST_F(AccountMenuCoordinatorNonManagedTest, testMDMError) {
+TEST_P(AccountMenuCoordinatorNonManagedTest, testMDMError) {
   [coordinator_ openMDMErrodDialogWithSystemIdentity:kPrimaryIdentity];
   assertOpenAndInterrupt();
 }
+
+INSTANTIATE_TEST_SUITE_P(,
+                         AccountMenuCoordinatorNonManagedTest,
+                         testing::Bool(),
+                         [](const testing::TestParamInfo<bool>& info) {
+                           return info.param ? "WithSeparateProfiles"
+                                             : "WithoutSeparateProfiles";
+                         });
+
+INSTANTIATE_TEST_SUITE_P(,
+                         AccountMenuCoordinatorManagedTest,
+                         testing::Bool(),
+                         [](const testing::TestParamInfo<bool>& info) {
+                           return info.param ? "WithSeparateProfiles"
+                                             : "WithoutSeparateProfiles";
+                         });
diff --git a/ios/chrome/browser/ui/authentication/account_menu/account_menu_mediator_unittests.mm b/ios/chrome/browser/ui/authentication/account_menu/account_menu_mediator_unittests.mm
index 0cf1f7c..f651aaa0 100644
--- a/ios/chrome/browser/ui/authentication/account_menu/account_menu_mediator_unittests.mm
+++ b/ios/chrome/browser/ui/authentication/account_menu/account_menu_mediator_unittests.mm
@@ -6,6 +6,7 @@
 
 #import "base/memory/raw_ptr.h"
 #import "base/test/metrics/user_action_tester.h"
+#import "base/test/scoped_feature_list.h"
 #import "base/test/task_environment.h"
 #import "components/sync/test/test_sync_service.h"
 #import "ios/chrome/browser/settings/model/sync/utils/account_error_ui_info.h"
@@ -13,6 +14,7 @@
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
 #import "ios/chrome/browser/shared/public/commands/show_signin_command.h"
+#import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/signin/model/authentication_service.h"
 #import "ios/chrome/browser/signin/model/authentication_service_factory.h"
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service.h"
@@ -46,8 +48,16 @@
     [FakeSystemIdentity fakeIdentity3];
 }  // namespace
 
-class AccountMenuMediatorTest : public PlatformTest {
+// The test param determines whether `kSeparateProfilesForManagedAccounts` is
+// enabled.
+class AccountMenuMediatorTest : public PlatformTest,
+                                public testing::WithParamInterface<bool> {
  public:
+  AccountMenuMediatorTest() {
+    feature_list_.InitWithFeatureState(kSeparateProfilesForManagedAccounts,
+                                       GetParam());
+  }
+
   void SetUp() override {
     PlatformTest::SetUp();
 
@@ -134,6 +144,8 @@
     run_loop.Run();
   }
 
+  base::test::ScopedFeatureList feature_list_;
+
   id<AccountMenuMediatorDelegate> delegate_;
   id<AccountMenuConsumer> consumer_;
   AccountMenuMediator* mediator_;
@@ -167,7 +179,7 @@
 
 // Checks that adding a secondary identity lead to updating the
 // consumer.
-TEST_F(AccountMenuMediatorTest, TestAddSecondaryIdentity) {
+TEST_P(AccountMenuMediatorTest, TestAddSecondaryIdentity) {
   const FakeSystemIdentity* thirdIdentity = [FakeSystemIdentity fakeIdentity3];
   OCMExpect([consumer_
       updateAccountListWithGaiaIDsToAdd:@[ thirdIdentity.gaiaID ]
@@ -178,17 +190,23 @@
 
 // Checks that removing a secondary identity lead to updating the
 // consumer.
-TEST_F(AccountMenuMediatorTest, TestRemoveSecondaryIdentity) {
+TEST_P(AccountMenuMediatorTest, TestRemoveSecondaryIdentity) {
   // Expectations due to ChromeAccountManagerServiceObserver updates.
-  OCMExpect([consumer_
-      updateAccountListWithGaiaIDsToAdd:@[]
-                        gaiaIDsToRemove:@[]
-                          gaiaIDsToKeep:@[ kSecondaryIdentity.gaiaID ]]);
+  // If AreSeparateProfilesForManagedAccountsEnabled() is true, the updates come
+  // from IdentityManager instead, which doesn't send no-op updates.
+  if (!AreSeparateProfilesForManagedAccountsEnabled()) {
+    OCMExpect([consumer_
+        updateAccountListWithGaiaIDsToAdd:@[]
+                          gaiaIDsToRemove:@[]
+                            gaiaIDsToKeep:@[ kSecondaryIdentity.gaiaID ]]);
+  }
   OCMExpect([consumer_ updatePrimaryAccount]);
-  OCMExpect([consumer_
-      updateAccountListWithGaiaIDsToAdd:@[]
-                        gaiaIDsToRemove:@[]
-                          gaiaIDsToKeep:@[ kSecondaryIdentity.gaiaID ]]);
+  if (!AreSeparateProfilesForManagedAccountsEnabled()) {
+    OCMExpect([consumer_
+        updateAccountListWithGaiaIDsToAdd:@[]
+                          gaiaIDsToRemove:@[]
+                            gaiaIDsToKeep:@[ kSecondaryIdentity.gaiaID ]]);
+  }
 
   OCMExpect([consumer_
       updateAccountListWithGaiaIDsToAdd:@[]
@@ -210,7 +228,7 @@
 
 // Checks that removing the primary identity lead to updating the
 // consumer.
-TEST_F(AccountMenuMediatorTest, TestRemovePrimaryIdentity) {
+TEST_P(AccountMenuMediatorTest, TestRemovePrimaryIdentity) {
   OCMExpect([delegate_ mediatorWantsToBeDismissed:mediator_]);
   OCMExpect([consumer_ setUserInteractionsEnabled:NO]);
   authentication_service_->SignOut(signin_metrics::ProfileSignout::kTest,
@@ -222,7 +240,7 @@
 #pragma mark - AccountMenuDataSource
 
 // Tests the result of secondaryAccountsGaiaIDs.
-TEST_F(AccountMenuMediatorTest, TestSecondaryAccountsGaiaID) {
+TEST_P(AccountMenuMediatorTest, TestSecondaryAccountsGaiaID) {
   EXPECT_NSEQ([mediator_ secondaryAccountsGaiaIDs],
               @[ kSecondaryIdentity.gaiaID ]);
 }
@@ -230,19 +248,19 @@
 #pragma mark - AccountMenuDataSource and SyncObserverModelBridge
 
 // Tests the result of nameForGaiaID.
-TEST_F(AccountMenuMediatorTest, nameForGaiaID) {
+TEST_P(AccountMenuMediatorTest, nameForGaiaID) {
   EXPECT_NSEQ([mediator_ nameForGaiaID:kSecondaryIdentity.gaiaID],
               kSecondaryIdentity.userFullName);
 }
 
 // Tests the result of emailForGaiaID.
-TEST_F(AccountMenuMediatorTest, emailForGaiaID) {
+TEST_P(AccountMenuMediatorTest, emailForGaiaID) {
   EXPECT_NSEQ([mediator_ emailForGaiaID:kSecondaryIdentity.gaiaID],
               kSecondaryIdentity.userEmail);
 }
 
 // Tests the result of imageForGaiaID.
-TEST_F(AccountMenuMediatorTest, imageForGaiaID) {
+TEST_P(AccountMenuMediatorTest, imageForGaiaID) {
   EXPECT_NSEQ([mediator_ imageForGaiaID:kSecondaryIdentity.gaiaID],
               account_manager_service_ -> GetIdentityAvatarWithIdentity(
                                            kSecondaryIdentity,
@@ -250,18 +268,18 @@
 }
 
 // Tests the result of primaryAccountEmail.
-TEST_F(AccountMenuMediatorTest, TestPrimaryAccountEmail) {
+TEST_P(AccountMenuMediatorTest, TestPrimaryAccountEmail) {
   EXPECT_NSEQ([mediator_ primaryAccountEmail], kPrimaryIdentity.userEmail);
 }
 
 // Tests the result of primaryAccountUserFullName.
-TEST_F(AccountMenuMediatorTest, TestPrimaryAccountUserFullName) {
+TEST_P(AccountMenuMediatorTest, TestPrimaryAccountUserFullName) {
   EXPECT_NSEQ([mediator_ primaryAccountUserFullName],
               kPrimaryIdentity.userFullName);
 }
 
 // Tests the result of primaryAccountAvatar.
-TEST_F(AccountMenuMediatorTest, TestPrimaryAccountAvatar) {
+TEST_P(AccountMenuMediatorTest, TestPrimaryAccountAvatar) {
   EXPECT_NSEQ([mediator_ primaryAccountAvatar],
               account_manager_service_ -> GetIdentityAvatarWithIdentity(
                                            kPrimaryIdentity,
@@ -269,12 +287,12 @@
 }
 
 // Tests the result of TestError when there is no error.
-TEST_F(AccountMenuMediatorTest, TestNoError) {
+TEST_P(AccountMenuMediatorTest, TestNoError) {
   EXPECT_THAT([mediator_ accountErrorUIInfo], testing::IsNull());
 }
 
 // Tests the result of TestError when passphrase is required.
-TEST_F(AccountMenuMediatorTest, TestError) {
+TEST_P(AccountMenuMediatorTest, TestError) {
   // In order to simulate requiring a passphrase, test sync service requires
   // us to explicitly set that the setup is not complete, and fire the state
   // change to its observer.
@@ -296,7 +314,7 @@
 
 // Tests the result of accountTappedWithGaiaID:targetRect:
 // when sign-out fail.
-TEST_F(AccountMenuMediatorTest, TestAccountTapedSignoutFailed) {
+TEST_P(AccountMenuMediatorTest, TestAccountTapedSignoutFailed) {
   // Given that the method  `triggerSignoutWithTargetRect:completion` creates a
   // callback in a callback, this tests has three parts.  One part by callback,
   // and one part for the initial part of the run.
@@ -333,7 +351,7 @@
 
 // Tests the result of accountTappedWithGaiaID:targetRect:
 // when sign-in fail.
-TEST_F(AccountMenuMediatorTest, TestAccountTapedSignInFailed) {
+TEST_P(AccountMenuMediatorTest, TestAccountTapedSignInFailed) {
   // Given that the method  `signOutFromTargetRect:forSwitch:completion` create
   // a callback in a callback, this tests has three parts.  One part by
   // callback, and one part for the initial part of the run.
@@ -393,7 +411,7 @@
 
 // Tests the result of accountTappedWithGaiaID:targetRect:
 // when switch is succesful.
-TEST_F(AccountMenuMediatorTest, TestAccountTapedWithSuccesfulSwitch) {
+TEST_P(AccountMenuMediatorTest, TestAccountTapedWithSuccesfulSwitch) {
   // Given that the method  `signOutFromTargetRect:forSwitch:callback` create a
   // callback in a callback, this tests has three parts.  One part by callback,
   // and one part for the initial part of the run.
@@ -446,7 +464,7 @@
 }
 
 // Tests the result of didTapErrorButton when a passphrase is required.
-TEST_F(AccountMenuMediatorTest, TestTapErrorButtonPassphrase) {
+TEST_P(AccountMenuMediatorTest, TestTapErrorButtonPassphrase) {
   // While many errors can be displayed by the account menu, this test suite
   // only consider the error where the passphrase is needed. This is because,
   // when the suite was written, `TestSyncService::GetUserActionableError` could
@@ -461,19 +479,19 @@
 }
 
 // Tests the effect of didTapManageYourGoogleAccount.
-TEST_F(AccountMenuMediatorTest, TestDidTapManageYourGoogleAccount) {
+TEST_P(AccountMenuMediatorTest, TestDidTapManageYourGoogleAccount) {
   OCMExpect([delegate_ didTapManageYourGoogleAccount]);
   [mediator_ didTapManageYourGoogleAccount];
 }
 
 // Tests the effect of didTapManageAccounts.
-TEST_F(AccountMenuMediatorTest, TestDidTapEditAccountList) {
+TEST_P(AccountMenuMediatorTest, TestDidTapEditAccountList) {
   OCMExpect([delegate_ didTapManageAccounts]);
   [mediator_ didTapManageAccounts];
 }
 
 // Tests the effect of didTapAddAccount.
-TEST_F(AccountMenuMediatorTest, TestDidTapAddAccount) {
+TEST_P(AccountMenuMediatorTest, TestDidTapAddAccount) {
   __block SigninCoordinatorCompletionCallback completion = nil;
   OCMExpect([delegate_
       didTapAddAccountWithCompletion:[OCMArg checkWithBlock:^BOOL(id value) {
@@ -492,7 +510,7 @@
 }
 
 // Tests the effect of signOutFromTargetRect.
-TEST_F(AccountMenuMediatorTest, TestSignoutFromTargetRect) {
+TEST_P(AccountMenuMediatorTest, TestSignoutFromTargetRect) {
   CGRect rect = CGRectMake(0, 0, 40, 24);
 
   __block void (^completion)(BOOL) = nil;
@@ -513,7 +531,7 @@
 
 // Tests tapping on the close button just after the sign-out button.
 // This is a regression test for crbug.com/371046656.
-TEST_F(AccountMenuMediatorTest, TestSignoutAndClose) {
+TEST_P(AccountMenuMediatorTest, TestSignoutAndClose) {
   CGRect rect = CGRectMake(0, 0, 40, 24);
   __block void (^completion)(BOOL) = nil;
   OCMExpect([delegate_
@@ -534,9 +552,17 @@
 
 // Tests tapping on the close button just after the sign-out button.
 // This is a regression test for crbug.com/371046656.
-TEST_F(AccountMenuMediatorTest, TestViewControllerWantToBeClosed) {
+TEST_P(AccountMenuMediatorTest, TestViewControllerWantToBeClosed) {
   OCMExpect([delegate_ mediatorWantsToBeDismissed:mediator_]);
   OCMExpect([consumer_ setUserInteractionsEnabled:NO]);
   [mediator_
       viewControllerWantsToBeClosed:(AccountMenuViewController*)consumer_];
 }
+
+INSTANTIATE_TEST_SUITE_P(,
+                         AccountMenuMediatorTest,
+                         testing::Bool(),
+                         [](const testing::TestParamInfo<bool>& info) {
+                           return info.param ? "WithSeparateProfiles"
+                                             : "WithoutSeparateProfiles";
+                         });
diff --git a/ios/chrome/browser/ui/authentication/account_menu/account_menu_view_controller_unittests.mm b/ios/chrome/browser/ui/authentication/account_menu/account_menu_view_controller_unittests.mm
index 880ac63..0e3183d 100644
--- a/ios/chrome/browser/ui/authentication/account_menu/account_menu_view_controller_unittests.mm
+++ b/ios/chrome/browser/ui/authentication/account_menu/account_menu_view_controller_unittests.mm
@@ -7,12 +7,14 @@
 #import "base/check_op.h"
 #import "base/memory/raw_ptr.h"
 #import "base/test/metrics/user_action_tester.h"
+#import "base/test/scoped_feature_list.h"
 #import "ios/chrome/browser/policy/model/management_state.h"
 #import "ios/chrome/browser/settings/model/sync/utils/account_error_ui_info.h"
 #import "ios/chrome/browser/settings/ui_bundled/cells/settings_image_detail_text_cell.h"
 #import "ios/chrome/browser/settings/ui_bundled/settings_table_view_controller_constants.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
+#import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_text_item.h"
 #import "ios/chrome/browser/shared/ui/table_view/table_view_utils.h"
 #import "ios/chrome/browser/signin/model/authentication_service.h"
@@ -99,8 +101,16 @@
 
 @end
 
-class AccountMenuViewControllerTest : public PlatformTest {
+// The test param determines whether `kSeparateProfilesForManagedAccounts` is
+// enabled.
+class AccountMenuViewControllerTest : public PlatformTest,
+                                      public testing::WithParamInterface<bool> {
  public:
+  AccountMenuViewControllerTest() {
+    feature_list_.InitWithFeatureState(kSeparateProfilesForManagedAccounts,
+                                       GetParam());
+  }
+
   void SetUp() override {
     PlatformTest::SetUp();
     TestProfileIOS::Builder builder;
@@ -136,6 +146,8 @@
   }
 
  protected:
+  base::test::ScopedFeatureList feature_list_;
+
   // The navigation controller that displays the view_controller_.
   // It is not used in test. However, it’s accessed by the view controller, so
   // we must not let it be deallocated until tests are done.
@@ -204,7 +216,7 @@
 };
 
 // Test the view controller when it starts.
-TEST_F(AccountMenuViewControllerTest, TestDefaultSetting) {
+TEST_P(AccountMenuViewControllerTest, TestDefaultSetting) {
   EXPECT_EQ(2, TableView().numberOfSections);
   // The secondary account and Add Account...
   EXPECT_EQ(2, [TableView() numberOfRowsInSection:0]);
@@ -233,7 +245,7 @@
 #pragma mark - Test tapping on the views.
 
 // Tests tapping on the secondary account cell.
-TEST_F(AccountMenuViewControllerTest, TestTapSecondaryAccount) {
+TEST_P(AccountMenuViewControllerTest, TestTapSecondaryAccount) {
   OCMExpect([mutator_ accountTappedWithGaiaID:kSecondaryIdentity.gaiaID
                                    targetRect:CGRect()])
       .ignoringNonObjectArgs();
@@ -243,14 +255,14 @@
 }
 
 // Tests tapping on the add account cell.
-TEST_F(AccountMenuViewControllerTest, TestTapAddAccount) {
+TEST_P(AccountMenuViewControllerTest, TestTapAddAccount) {
   OCMExpect([mutator_ didTapAddAccount]);
   SelectCell(path_for_add_account_);
   EXPECT_EQ(1, user_actions_.GetActionCount("Signin_AccountMenu_AddAccount"));
 }
 
 // Tests tapping on the sign-out cell.
-TEST_F(AccountMenuViewControllerTest, TestTapSignOut) {
+TEST_P(AccountMenuViewControllerTest, TestTapSignOut) {
   OCMExpect([mutator_ signOutFromTargetRect:CGRect()]).ignoringNonObjectArgs();
   SelectCell(path_for_sign_out_);
   EXPECT_EQ(1, user_actions_.GetActionCount("Signin_AccountMenu_Signout"));
@@ -259,7 +271,7 @@
 #pragma mark - AccountMenuConsumer
 
 // Tests tapping on error action button.
-TEST_F(AccountMenuViewControllerTest, TestSetError) {
+TEST_P(AccountMenuViewControllerTest, TestSetError) {
   AccountErrorUIInfo* errorInfo = [[AccountErrorUIInfo alloc]
        initWithErrorType:syncer::SyncService::UserActionableError::
                              kNeedsPassphrase
@@ -298,7 +310,7 @@
 
 // Tests that adding an account adds an extra row in the secondary account
 // section.
-TEST_F(AccountMenuViewControllerTest, TestAddAccount) {
+TEST_P(AccountMenuViewControllerTest, TestAddAccount) {
   fake_system_identity_manager_->AddIdentity(kSecondaryIdentity2);
   [view_controller_
       updateAccountListWithGaiaIDsToAdd:@[ kSecondaryIdentity2.gaiaID ]
@@ -313,7 +325,7 @@
 
 // Test that removing a secondary account remove a row in the secondary account
 // section.
-TEST_F(AccountMenuViewControllerTest, TestRemoveAccount) {
+TEST_P(AccountMenuViewControllerTest, TestRemoveAccount) {
   [view_controller_
       updateAccountListWithGaiaIDsToAdd:@[]
                         gaiaIDsToRemove:@[ kSecondaryIdentity.gaiaID ]
@@ -327,7 +339,7 @@
 
 // Test that updating the primary account has no discernable impact on the view
 // controller.
-TEST_F(AccountMenuViewControllerTest, TestUpdatePrimaryAccount) {
+TEST_P(AccountMenuViewControllerTest, TestUpdatePrimaryAccount) {
   [view_controller_ updatePrimaryAccount];
   EXPECT_EQ(2, TableView().numberOfSections);
   // The secondary account and Add Account...
@@ -336,3 +348,10 @@
   EXPECT_EQ(1, [TableView() numberOfRowsInSection:1]);
 }
 
+INSTANTIATE_TEST_SUITE_P(,
+                         AccountMenuViewControllerTest,
+                         testing::Bool(),
+                         [](const testing::TestParamInfo<bool>& info) {
+                           return info.param ? "WithSeparateProfiles"
+                                             : "WithoutSeparateProfiles";
+                         });
diff --git a/ios/chrome/browser/ui/authentication/authentication_flow_performer.h b/ios/chrome/browser/ui/authentication/authentication_flow_performer.h
index 0e8e06e..9b9f4d97 100644
--- a/ios/chrome/browser/ui/authentication/authentication_flow_performer.h
+++ b/ios/chrome/browser/ui/authentication/authentication_flow_performer.h
@@ -33,7 +33,7 @@
 - (instancetype)init NS_UNAVAILABLE;
 
 // Cancels any outstanding work and dismisses an alert view (if shown) using
-// animation if `animated` is true.
+// animation if `animated` is true. Calls `completion` synchronously.
 - (void)interruptWithAction:(SigninCoordinatorInterrupt)action
                  completion:(ProceduralBlock)completion;
 
diff --git a/ios/chrome/browser/ui/authentication/history_sync/history_sync_popup_coordinator.mm b/ios/chrome/browser/ui/authentication/history_sync/history_sync_popup_coordinator.mm
index cddcdbe..00ae9ea7 100644
--- a/ios/chrome/browser/ui/authentication/history_sync/history_sync_popup_coordinator.mm
+++ b/ios/chrome/browser/ui/authentication/history_sync/history_sync_popup_coordinator.mm
@@ -18,6 +18,7 @@
 #import "ios/chrome/browser/ui/authentication/authentication_ui_util.h"
 #import "ios/chrome/browser/ui/authentication/history_sync/history_sync_coordinator.h"
 #import "ios/chrome/browser/ui/authentication/history_sync/history_sync_utils.h"
+#import "ios/chrome/browser/ui/authentication/signin/interruptible_chrome_coordinator.h"
 
 @interface HistorySyncPopupCoordinator () <
     HistorySyncCoordinatorDelegate,
@@ -120,13 +121,20 @@
   };
   switch (action) {
     case SigninCoordinatorInterrupt::DismissWithAnimation:
-      [_navigationController dismissViewControllerAnimated:YES
-                                                completion:dismissCompletion];
+    case SigninCoordinatorInterrupt::DismissWithoutAnimation: {
+      BOOL animated =
+          SigninCoordinatorInterrupt::DismissWithAnimation == action;
+      if (base::FeatureList::IsEnabled(
+              kIOSInterruptibleChromeStoppedSynchronously)) {
+        [_navigationController dismissViewControllerAnimated:animated
+                                                  completion:nil];
+        dismissCompletion();
+      } else {
+        [_navigationController dismissViewControllerAnimated:animated
+                                                  completion:dismissCompletion];
+      }
       break;
-    case SigninCoordinatorInterrupt::DismissWithoutAnimation:
-      [_navigationController dismissViewControllerAnimated:NO
-                                                completion:dismissCompletion];
-      break;
+    }
     case SigninCoordinatorInterrupt::UIShutdownNoDismiss:
       // The view should be ignored and leave it being presented.
       _navigationController.presentationController.delegate = nil;
diff --git a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_promo_signin_coordinator.mm b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_promo_signin_coordinator.mm
index 60a8529..4304b12 100644
--- a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_promo_signin_coordinator.mm
+++ b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_promo_signin_coordinator.mm
@@ -30,6 +30,7 @@
 #import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_sheet/consistency_sheet_navigation_controller.h"
 #import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_sheet/consistency_sheet_presentation_controller.h"
 #import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_sheet/consistency_sheet_slide_transition_animator.h"
+#import "ios/chrome/browser/ui/authentication/signin/interruptible_chrome_coordinator.h"
 #import "ios/chrome/browser/ui/authentication/signin/signin_constants.h"
 #import "ios/chrome/browser/ui/authentication/signin/signin_coordinator+protected.h"
 #import "ios/chrome/browser/ui/authentication/signin/signin_utils.h"
@@ -209,9 +210,19 @@
     case SigninCoordinatorInterrupt::DismissWithAnimation: {
       BOOL animated =
           action == SigninCoordinatorInterrupt::DismissWithAnimation;
-      [self.navigationController.presentingViewController
-          dismissViewControllerAnimated:animated
-                             completion:finishCompletionBlock];
+      if (base::FeatureList::IsEnabled(
+              kIOSInterruptibleChromeStoppedSynchronously)) {
+        [self.navigationController.presentingViewController
+            dismissViewControllerAnimated:animated
+                               completion:nil];
+        finishCompletionBlock();
+      } else {
+        {
+          [self.navigationController.presentingViewController
+              dismissViewControllerAnimated:animated
+                                 completion:finishCompletionBlock];
+        }
+      }
     }
   }
 }
diff --git a/ios/chrome/browser/ui/authentication/signin/forced_signin/forced_signin_coordinator.mm b/ios/chrome/browser/ui/authentication/signin/forced_signin/forced_signin_coordinator.mm
index b7f8a5f..477ab98 100644
--- a/ios/chrome/browser/ui/authentication/signin/forced_signin/forced_signin_coordinator.mm
+++ b/ios/chrome/browser/ui/authentication/signin/forced_signin/forced_signin_coordinator.mm
@@ -17,6 +17,7 @@
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/signin/model/authentication_service.h"
 #import "ios/chrome/browser/signin/model/authentication_service_factory.h"
+#import "ios/chrome/browser/ui/authentication/signin/interruptible_chrome_coordinator.h"
 #import "ios/chrome/browser/ui/authentication/signin/signin_coordinator+protected.h"
 
 @interface ForcedSigninCoordinator () <FirstRunScreenDelegate>
@@ -180,15 +181,26 @@
     }
   }
 
+  ProceduralBlock childCompletion = ^{
+    if (base::FeatureList::IsEnabled(
+            kIOSInterruptibleChromeStoppedSynchronously)) {
+      [weakSelf.navigationController.presentingViewController
+          dismissViewControllerAnimated:animated
+                             completion:nil];
+      finishCompletion();
+
+    } else {
+      [weakSelf.navigationController.presentingViewController
+          dismissViewControllerAnimated:animated
+                             completion:finishCompletion];
+    }
+  };
+
   // Interrupt the child coordinator UI first before dismissing the forced
   // sign-in navigation controller.
   [self.childCoordinator
       interruptWithAction:SigninCoordinatorInterrupt::DismissWithoutAnimation
-               completion:^{
-                 [weakSelf.navigationController.presentingViewController
-                     dismissViewControllerAnimated:animated
-                                        completion:finishCompletion];
-               }];
+               completion:childCompletion];
 }
 
 #pragma mark - NSObject
diff --git a/ios/chrome/browser/ui/authentication/signin/instant_signin/instant_signin_coordinator.mm b/ios/chrome/browser/ui/authentication/signin/instant_signin/instant_signin_coordinator.mm
index be0cd5a..842ba044 100644
--- a/ios/chrome/browser/ui/authentication/signin/instant_signin/instant_signin_coordinator.mm
+++ b/ios/chrome/browser/ui/authentication/signin/instant_signin/instant_signin_coordinator.mm
@@ -20,6 +20,7 @@
 #import "ios/chrome/browser/ui/authentication/identity_chooser/identity_chooser_coordinator.h"
 #import "ios/chrome/browser/ui/authentication/identity_chooser/identity_chooser_coordinator_delegate.h"
 #import "ios/chrome/browser/ui/authentication/signin/instant_signin/instant_signin_mediator.h"
+#import "ios/chrome/browser/ui/authentication/signin/interruptible_chrome_coordinator.h"
 #import "ios/chrome/browser/ui/authentication/signin/signin_constants.h"
 #import "ios/chrome/browser/ui/authentication/signin/signin_coordinator+protected.h"
 
@@ -171,7 +172,15 @@
       completion();
     }
   } else {
-    [_mediator interruptWithAction:action completion:completion];
+    if (base::FeatureList::IsEnabled(
+            kIOSInterruptibleChromeStoppedSynchronously)) {
+      [_mediator interruptWithAction:action completion:nil];
+      if (completion) {
+        completion();
+      }
+    } else {
+      [_mediator interruptWithAction:action completion:completion];
+    }
   }
 }
 
diff --git a/ios/chrome/browser/ui/authentication/signin/instant_signin/instant_signin_mediator.h b/ios/chrome/browser/ui/authentication/signin/instant_signin/instant_signin_mediator.h
index 1fb91ef..0645a54 100644
--- a/ios/chrome/browser/ui/authentication/signin/instant_signin/instant_signin_mediator.h
+++ b/ios/chrome/browser/ui/authentication/signin/instant_signin/instant_signin_mediator.h
@@ -42,7 +42,8 @@
 - (void)disconnect;
 
 // Stops the sign-in flow. This method can only be called once, and only after
-// `startSignInOnlyFlowWithAuthenticationFlow:` has ben called.
+// `startSignInOnlyFlowWithAuthenticationFlow:` has ben called. `completion` is
+// run synchronously iff kIOSInterruptibleChromeStoppedSynchronously is enabled.
 - (void)interruptWithAction:(SigninCoordinatorInterrupt)action
                  completion:(ProceduralBlock)completion;
 
diff --git a/ios/chrome/browser/ui/authentication/signin/interruptible_chrome_coordinator.h b/ios/chrome/browser/ui/authentication/signin/interruptible_chrome_coordinator.h
index 4829b2e..341dd8a 100644
--- a/ios/chrome/browser/ui/authentication/signin/interruptible_chrome_coordinator.h
+++ b/ios/chrome/browser/ui/authentication/signin/interruptible_chrome_coordinator.h
@@ -21,8 +21,10 @@
 // Dependending on `action`, the interruption may be done asynchronously
 // with/without an animation, or without dismissing the views when the
 // interruption is for shutdown (e.g., tearing down the scene). `completion` is
-// called when the interruption is done. Simply calls `completion` if the
+// called synchronously. Simply calls `completion` if the
 // method is not overridden.
+// TODO(crbug.com/381444097): Remove the completion parameter when the flag
+// IOSInterruptibleChromeStoppedSynchronously is removed.
 - (void)interruptWithAction:(SigninCoordinatorInterrupt)action
                  completion:(ProceduralBlock)completion;
 
diff --git a/ios/chrome/browser/ui/authentication/signin/signin_coordinator.h b/ios/chrome/browser/ui/authentication/signin/signin_coordinator.h
index eb4ee799..7da1cf40 100644
--- a/ios/chrome/browser/ui/authentication/signin/signin_coordinator.h
+++ b/ios/chrome/browser/ui/authentication/signin/signin_coordinator.h
@@ -192,8 +192,9 @@
 // `signinCompletion()` and `completion()` are called synchronously in this
 // order.
 // When the coordinator is interrupted with `DismissWithoutAnimation` or
-// `DismissWithAnimation`, the view is dismissed first. After being dismissed,
-// `signinCompletion()` is called, and then `completion()` is called.
+// `DismissWithAnimation`, the view is dismissed first.
+// `signinCompletion()` and then `completion()` are called synchronously
+// kIOSInterruptibleChromeStoppedSynchronously is enabled.
 //
 // It is still mandatory to call `-[SigninCoordinator stop]` once
 // `signinCompletion()` is called.
diff --git a/ios/chrome/browser/ui/authentication/signin/trusted_vault_reauthentication/trusted_vault_reauthentication_coordinator.mm b/ios/chrome/browser/ui/authentication/signin/trusted_vault_reauthentication/trusted_vault_reauthentication_coordinator.mm
index b1186c5..996bb48 100644
--- a/ios/chrome/browser/ui/authentication/signin/trusted_vault_reauthentication/trusted_vault_reauthentication_coordinator.mm
+++ b/ios/chrome/browser/ui/authentication/signin/trusted_vault_reauthentication/trusted_vault_reauthentication_coordinator.mm
@@ -15,6 +15,7 @@
 #import "ios/chrome/browser/signin/model/authentication_service_factory.h"
 #import "ios/chrome/browser/signin/model/trusted_vault_client_backend.h"
 #import "ios/chrome/browser/signin/model/trusted_vault_client_backend_factory.h"
+#import "ios/chrome/browser/ui/authentication/signin/interruptible_chrome_coordinator.h"
 #import "ios/chrome/browser/ui/authentication/signin/signin_coordinator+protected.h"
 #import "ios/chrome/grit/ios_strings.h"
 #import "ui/base/l10n/l10n_util.h"
@@ -100,6 +101,12 @@
     CHECK(!self.errorAlertCoordinator.noInteractionAction);
     self.errorAlertCoordinator.noInteractionAction = cancelCompletion;
     [self stopErrorAlertCoordinator];
+    // Checks that `cancelCompletion` is executed synchronously.
+    CHECK(!self.signinCompletion, base::NotFatalUntil::M126);
+  } else if (base::FeatureList::IsEnabled(
+                 kIOSInterruptibleChromeStoppedSynchronously)) {
+    std::move(_dialogCancelCallback).Run(animated, nil);
+    cancelCompletion();
   } else {
     std::move(_dialogCancelCallback).Run(animated, cancelCompletion);
   }
diff --git a/ios/chrome/browser/ui/authentication/signin/trusted_vault_reauthentication/trusted_vault_reauthentication_coordinator_unittest.mm b/ios/chrome/browser/ui/authentication/signin/trusted_vault_reauthentication/trusted_vault_reauthentication_coordinator_unittest.mm
index 0d75bf6..b2dda9d 100644
--- a/ios/chrome/browser/ui/authentication/signin/trusted_vault_reauthentication/trusted_vault_reauthentication_coordinator_unittest.mm
+++ b/ios/chrome/browser/ui/authentication/signin/trusted_vault_reauthentication/trusted_vault_reauthentication_coordinator_unittest.mm
@@ -14,6 +14,7 @@
 #import "ios/chrome/browser/signin/model/fake_system_identity.h"
 #import "ios/chrome/browser/signin/model/fake_system_identity_manager.h"
 #import "ios/chrome/browser/signin/model/trusted_vault_client_backend_factory.h"
+#import "ios/chrome/browser/ui/authentication/signin/interruptible_chrome_coordinator.h"
 #import "ios/chrome/browser/ui/authentication/signin/signin_constants.h"
 #import "ios/chrome/browser/ui/authentication/signin/signin_coordinator.h"
 #import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h"
@@ -175,10 +176,17 @@
                  EXPECT_TRUE(signin_completion_called);
                  interrupt_completion_called = true;
                }];
-  // The sign-in and interrupt completion blocks should be called
-  // asynchronously, after the UI is dismissed.
-  EXPECT_FALSE(signin_completion_called);
-  EXPECT_FALSE(interrupt_completion_called);
+  if (base::FeatureList::IsEnabled(
+          kIOSInterruptibleChromeStoppedSynchronously)) {
+    // Sign-in and interrupt completion blocks should be called synchronously.
+    EXPECT_TRUE(signin_completion_called);
+    EXPECT_TRUE(interrupt_completion_called);
+  } else {
+    // The sign-in and interrupt completion blocks should be called
+    // asynchronously, after the UI is dismissed.
+    EXPECT_FALSE(signin_completion_called);
+    EXPECT_FALSE(interrupt_completion_called);
+  };
   // Test the completion block.
   EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
       base::test::ios::kWaitForUIElementTimeout, ^bool() {
diff --git a/ios/chrome/browser/ui/authentication/signin/two_screens_signin/two_screens_signin_coordinator.mm b/ios/chrome/browser/ui/authentication/signin/two_screens_signin/two_screens_signin_coordinator.mm
index f7c98098..08502a2 100644
--- a/ios/chrome/browser/ui/authentication/signin/two_screens_signin/two_screens_signin_coordinator.mm
+++ b/ios/chrome/browser/ui/authentication/signin/two_screens_signin/two_screens_signin_coordinator.mm
@@ -21,6 +21,7 @@
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service_factory.h"
 #import "ios/chrome/browser/signin/model/identity_manager_factory.h"
 #import "ios/chrome/browser/ui/authentication/history_sync/history_sync_coordinator.h"
+#import "ios/chrome/browser/ui/authentication/signin/interruptible_chrome_coordinator.h"
 #import "ios/chrome/browser/ui/authentication/signin/logging/upgrade_signin_logger.h"
 #import "ios/chrome/browser/ui/authentication/signin/signin_coordinator+protected.h"
 #import "ios/chrome/browser/ui/authentication/signin/uno_signin_screen_provider.h"
@@ -242,21 +243,30 @@
     }
   }
 
+  ProceduralBlock signinCompletion = ^{
+    UIViewController* presentingViewController =
+        weakNavigationController.presentingViewController;
+    if (presentingViewController) {
+      if (base::FeatureList::IsEnabled(
+              kIOSInterruptibleChromeStoppedSynchronously)) {
+        [presentingViewController dismissViewControllerAnimated:animated
+                                                     completion:nil];
+        finishCompletion();
+      } else {
+        [presentingViewController
+            dismissViewControllerAnimated:animated
+                               completion:finishCompletion];
+      }
+    } else {
+      finishCompletion();
+    }
+  };
+
   // Interrupt the child coordinator UI first before dismissing the new
   // sign-in navigation controller.
   [_childCoordinator
       interruptWithAction:SigninCoordinatorInterrupt::DismissWithoutAnimation
-               completion:^{
-                 UIViewController* presentingViewController =
-                     weakNavigationController.presentingViewController;
-                 if (presentingViewController) {
-                   [presentingViewController
-                       dismissViewControllerAnimated:animated
-                                          completion:finishCompletion];
-                 } else {
-                   finishCompletion();
-                 }
-               }];
+               completion:signinCompletion];
 }
 
 #pragma mark - HistorySyncCoordinatorDelegate
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
index 3ac1012..7752fb9 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
@@ -143,11 +143,6 @@
   [[EarlGrey selectElementWithMatcher:WebStateScrollViewMatcher()]
       performAction:grey_swipeSlowInDirection(kGREYDirectionDown)];
   [ChromeEarlGreyUI waitForToolbarVisible:YES];
-
-  // Test that the toolbar is still visible even after attempting to hide it
-  // on swipe up.
-  HideToolbarUsingUI();
-  [ChromeEarlGreyUI waitForToolbarVisible:YES];
 }
 
 // Verifies that the toolbar properly appears/disappears when scrolling up/down
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_mediator.h b/ios/chrome/browser/ui/fullscreen/fullscreen_mediator.h
index c633bbc3..38d77bb 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_mediator.h
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_mediator.h
@@ -15,6 +15,7 @@
 
 class FullscreenController;
 class FullscreenControllerObserver;
+enum class FullscreenModelScrollDirection;
 @class FullscreenResetAnimator;
 @class FullscreenScrollEndAnimator;
 @class FullscreenScrollToTopAnimator;
@@ -88,6 +89,10 @@
   // animator's current progress value.
   void StopAnimating(bool update_model);
 
+  // Returns the animator style given a scroll direction.
+  FullscreenAnimatorStyle AnimatorStyleFromScrollDirection(
+      FullscreenModelScrollDirection direction);
+
   // Progress value when scroll event started.
   float start_progress_;
   // True if metrics as not been recorded and should be.
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_mediator.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_mediator.mm
index 3706d6f..4d69e184 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_mediator.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_mediator.mm
@@ -161,29 +161,21 @@
     FullscreenModel* model) {
   DCHECK_EQ(model_, model);
   should_record_metrics_ = true;
-  FullscreenAnimatorStyle animatorStyle;
   if (base::FeatureList::IsEnabled(web::features::kSmoothScrollingDefault)) {
     AnimateWithStyle(model_->progress() >= 0.5
                          ? FullscreenAnimatorStyle::EXIT_FULLSCREEN
                          : FullscreenAnimatorStyle::ENTER_FULLSCREEN);
   } else {
-    // Compute the direction to ensure to not enter fullscreen when the website
-    // is not long enough to have more than 0.5 progress and do not enter
-    // fullscreen when we scroll up.
-    float direction = model_->progress() - start_progress_;
-    animatorStyle = animator_.style;
     if (model_->enabled() && model_->is_scrolled_to_bottom() &&
         AreCGFloatsEqual(model_->progress(), 0.0) &&
         model_->can_collapse_toolbar()) {
-      animatorStyle = FullscreenAnimatorStyle::EXIT_FULLSCREEN;
+      AnimateWithStyle(FullscreenAnimatorStyle::EXIT_FULLSCREEN);
       base::RecordAction(
           base::UserMetricsAction("MobileFullscreenExitedBottomReached"));
-    } else if (model_->progress() >= 0.5) {
-      animatorStyle = FullscreenAnimatorStyle::EXIT_FULLSCREEN;
-    } else if (direction < 0) {
-      animatorStyle = FullscreenAnimatorStyle::ENTER_FULLSCREEN;
+    } else {
+      AnimateWithStyle(
+          AnimatorStyleFromScrollDirection(model->LastDirection()));
     }
-    AnimateWithStyle(animatorStyle);
   }
 }
 
@@ -268,3 +260,13 @@
     observer.ResizeHorizontalInsets(controller_);
   }
 }
+
+FullscreenAnimatorStyle FullscreenMediator::AnimatorStyleFromScrollDirection(
+    FullscreenModelScrollDirection direction) {
+  switch (direction) {
+    case FullscreenModelScrollDirection::kUp:
+      return FullscreenAnimatorStyle::EXIT_FULLSCREEN;
+    case FullscreenModelScrollDirection::kDown:
+      return FullscreenAnimatorStyle::ENTER_FULLSCREEN;
+  }
+}
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_model.h b/ios/chrome/browser/ui/fullscreen/fullscreen_model.h
index 59cc0ad..18d281ac 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_model.h
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_model.h
@@ -17,6 +17,9 @@
 
 class FullscreenModelObserver;
 
+// Represents the direction the user is scrolling.
+enum class FullscreenModelScrollDirection { kUp, kDown };
+
 // Model object used to calculate fullscreen state.
 class FullscreenModel : public ChromeBroadcastObserverInterface {
  public:
@@ -199,6 +202,13 @@
   void SetInsetsUpdateEnabled(bool enabled);
   bool IsInsetsUpdateEnabled() const;
 
+  // Returns the direction of the last scroll event.
+  FullscreenModelScrollDirection LastDirection() const {
+    return initial_y_offset_ - y_content_offset_ > 0
+               ? FullscreenModelScrollDirection::kUp
+               : FullscreenModelScrollDirection::kDown;
+  }
+
  private:
   // Returns how a scroll to the current `y_content_offset_` from `from_offset`
   // should be handled.
@@ -254,6 +264,8 @@
   CGFloat collapsed_bottom_toolbar_height_ = 0.0;
   // The current vertical content offset of the main content.
   CGFloat y_content_offset_ = 0.0;
+  // The vertical content offset at the start of a scroll event.
+  CGFloat initial_y_offset_ = 0.0;
   // The height of the scroll view displaying the current page.
   CGFloat scroll_view_height_ = 0.0;
   // The height of the current page's rendered content.
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm
index 81a9560..8234414 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm
@@ -197,6 +197,7 @@
 
 void FullscreenModel::SetYContentOffset(CGFloat y_content_offset) {
   CGFloat from_offset = y_content_offset_;
+  initial_y_offset_ = y_content_offset_;
   y_content_offset_ = y_content_offset;
   switch (ActionForScrollFromOffset(from_offset)) {
     case ScrollAction::kUpdateBaseOffset:
@@ -231,6 +232,7 @@
     for (auto& observer : observers_) {
       observer.FullscreenModelScrollEventStarted(this);
     }
+    initial_y_offset_ = y_content_offset_;
   } else {
     // Stop ignoring the current scroll.
     ignoring_current_scroll_ = false;
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_proxy_observer.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_proxy_observer.mm
index 0214d72..1c8ad68 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_proxy_observer.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_proxy_observer.mm
@@ -71,6 +71,7 @@
 - (void)webViewScrollViewWillBeginDragging:
     (CRWWebViewScrollViewProxy*)webViewScrollViewProxy {
   if (!base::FeatureList::IsEnabled(web::features::kSmoothScrollingDefault)) {
+    self.model->SetYContentOffset(webViewScrollViewProxy.contentOffset.y);
     self.model->SetScrollViewIsScrolling(true);
     self.model->SetScrollViewIsDragging(true);
   }
diff --git a/ios/chrome/browser/web/model/error_page_util_unittest.mm b/ios/chrome/browser/web/model/error_page_util_unittest.mm
index ffcd5d78..dd40b87 100644
--- a/ios/chrome/browser/web/model/error_page_util_unittest.mm
+++ b/ios/chrome/browser/web/model/error_page_util_unittest.mm
@@ -61,10 +61,10 @@
 
 // Tests error page for POST and non-OTR error. Error pages for POST requests do
 // not have Reload button. The expected strings are: error code and failing
-// url.
+// url's host.
 TEST_F(ErrorPageUtilTest, PostNonOtrError) {
-  NSString* html = GetErrorPage(GURL(base::SysNSStringToUTF8(kTestUrl)),
-                                CreateTestError(NSURLErrorTimedOut),
+  GURL test_url = GURL(base::SysNSStringToUTF8(kTestUrl));
+  NSString* html = GetErrorPage(test_url, CreateTestError(NSURLErrorTimedOut),
                                 /*is_post=*/true,
                                 /*is_off_the_record=*/false);
 
@@ -72,7 +72,7 @@
   EXPECT_TRUE([html containsString:@"<head>"]);
 
   EXPECT_TRUE([html containsString:ErrorAsString(ERR_CONNECTION_TIMED_OUT)]);
-  EXPECT_TRUE([html containsString:kTestUrl]);
+  EXPECT_TRUE([html containsString:base::SysUTF8ToNSString(test_url.host())]);
   EXPECT_FALSE([html containsString:GetNSString(IDS_ERRORPAGES_BUTTON_RELOAD)]);
 }
 
@@ -95,10 +95,10 @@
 
 // Tests error page for OST and OTR error. On iOS OTR error pages are the same
 // as non-OTR. Error pages for POST requests do not have Reload button. The
-// expected strings are: error code and failing url.
+// expected strings are: error code and failing url's host.
 TEST_F(ErrorPageUtilTest, PostOtrError) {
-  NSString* html = GetErrorPage(GURL(base::SysNSStringToUTF8(kTestUrl)),
-                                CreateTestError(NSURLErrorTimedOut),
+  GURL test_url = GURL(base::SysNSStringToUTF8(kTestUrl));
+  NSString* html = GetErrorPage(test_url, CreateTestError(NSURLErrorTimedOut),
                                 /*is_post=*/true,
                                 /*is_off_the_record=*/true);
 
@@ -106,7 +106,7 @@
   EXPECT_TRUE([html containsString:@"<head>"]);
 
   EXPECT_TRUE([html containsString:ErrorAsString(ERR_CONNECTION_TIMED_OUT)]);
-  EXPECT_TRUE([html containsString:kTestUrl]);
+  EXPECT_TRUE([html containsString:base::SysUTF8ToNSString(test_url.host())]);
   EXPECT_FALSE([html containsString:GetNSString(IDS_ERRORPAGES_BUTTON_RELOAD)]);
 }
 
diff --git a/ios/web/content/js_messaging/content_web_frame.h b/ios/web/content/js_messaging/content_web_frame.h
index 2354399..a268c06 100644
--- a/ios/web/content/js_messaging/content_web_frame.h
+++ b/ios/web/content/js_messaging/content_web_frame.h
@@ -15,6 +15,7 @@
 #import "ios/web/public/js_messaging/web_frame.h"
 #import "ios/web/public/web_state_observer.h"
 #import "url/gurl.h"
+#import "url/origin.h"
 
 namespace content {
 class RenderFrameHost;
@@ -43,6 +44,7 @@
   std::string GetFrameId() const override;
   bool IsMainFrame() const override;
   GURL GetSecurityOriginDeprecated() const override;
+  url::Origin GetSecurityOrigin() const override;
   BrowserState* GetBrowserState() override;
   base::WeakPtr<WebFrame> AsWeakPtr() override;
 
diff --git a/ios/web/content/js_messaging/content_web_frame.mm b/ios/web/content/js_messaging/content_web_frame.mm
index 5724a75..7a1ecf53 100644
--- a/ios/web/content/js_messaging/content_web_frame.mm
+++ b/ios/web/content/js_messaging/content_web_frame.mm
@@ -73,6 +73,10 @@
   return render_frame_host_->GetLastCommittedURL().DeprecatedGetOriginAsURL();
 }
 
+url::Origin ContentWebFrame::GetSecurityOrigin() const {
+  return render_frame_host_->GetLastCommittedOrigin();
+}
+
 BrowserState* ContentWebFrame::GetBrowserState() {
   return content_web_state_->GetBrowserState();
   ;
diff --git a/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm b/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
index a9251bd..628f7d3 100644
--- a/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
+++ b/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
@@ -118,8 +118,8 @@
 WebViewAutofillClientIOS::GetCrowdsourcingManager() {
   if (!crowdsourcing_manager_) {
     // Lazy initialization to avoid virtual function calls in the constructor.
-    crowdsourcing_manager_ = std::make_unique<AutofillCrowdsourcingManager>(
-        this, GetChannel(), GetLogManager());
+    crowdsourcing_manager_ =
+        std::make_unique<AutofillCrowdsourcingManager>(this, GetChannel());
   }
   return *crowdsourcing_manager_;
 }
diff --git a/ios_internal b/ios_internal
index 6291d21..0ab8b51 160000
--- a/ios_internal
+++ b/ios_internal
@@ -1 +1 @@
-Subproject commit 6291d21f3b65625b40e468f413e4d4671a264163
+Subproject commit 0ab8b51d63a6a0a658d209f18df69058aa201007
diff --git a/media/capture/video/video_capture_device_client.cc b/media/capture/video/video_capture_device_client.cc
index 56ab8db..ccce265 100644
--- a/media/capture/video/video_capture_device_client.cc
+++ b/media/capture/video/video_capture_device_client.cc
@@ -376,6 +376,46 @@
 }
 
 #if BUILDFLAG(ENABLE_VIDEO_EFFECTS)
+std::optional<VideoCaptureDevice::Client::Buffer>
+VideoCaptureDeviceClient::ReserveEffectsOutputBuffer(
+    const VideoCaptureFormat& format,
+    const int frame_feedback_id) {
+  CHECK(base::FeatureList::IsEnabled(media::kCameraMicEffects));
+  // We need to allocate the output buffer since the post-processor cannot
+  // operate in-place. This new `out_buffer`, along with original `buffer`,
+  // will be considered as held for producer until the post-processor has
+  // finished processing their contents, after which the `buffer` should be
+  // marked as unused (`RelinquishProducerReservation()`) and `out_buffer`
+  // will be marked as held for consumer.
+  // Note that this means we're allocating 2x as many buffers as we'd have
+  // allocated without the video effects. It may be possible to hold on to
+  // the input buffer for less time than what is needed to post-process it
+  // - it could be released once the processor has imported it into the
+  // graphical API it uses to run the post-processing logic.
+  // TODO(https://crbug.com/339141106): Consider having an additional pool
+  // for post-processing output buffers, separate from the pool used to
+  // allocate the original buffers.
+  Buffer out_buffer;
+  const VideoCaptureDevice::Client::ReserveResult reserve_result =
+      ReserveOutputBuffer(format.frame_size, format.pixel_format,
+                          frame_feedback_id, &out_buffer,
+                          /*require_new_buffer_id=*/nullptr,
+                          /*retire_old_buffer_id=*/nullptr);
+
+  if (reserve_result == VideoCaptureDevice::Client::ReserveResult::kSucceeded) {
+    return std::move(out_buffer);
+  } else {
+    // We weren't able to reserve the buffer for the post-processor's
+    // result. We could either drop the frame or deliver the unprocessed
+    // buffer to the consumer, but since post-processing can apply
+    // privacy-preserving effects, we should not deliver unprocessed frames
+    // without user intervention, hence we report failure.
+    receiver_->OnFrameDropped(
+        ConvertReservationFailureToFrameDropReason(reserve_result));
+    return std::nullopt;
+  }
+}
+
 void VideoCaptureDeviceClient::OnPostProcessDone(
     base::expected<PostProcessDoneInfo, video_effects::mojom::PostProcessError>
         post_process_info_or_error) {
@@ -694,60 +734,37 @@
         reference_time, timestamp, capture_begin_timestamp, buffer.format,
         metadata, visible_rect, /*is_premapped=*/false, buffer.color_space);
 
-    // We need to allocate the output buffer since the post-processor cannot
-    // operate in-place. This new `out_buffer`, along with original `buffer`,
-    // will be considered as held for producer until the post-processor has
-    // finished processing their contents, after which the `buffer` should be
-    // marked as unused (`RelinquishProducerReservation()`) and `out_buffer`
-    // will be marked as held for consumer.
-    // Note that this means we're allocating 2x as many buffers as we'd have
-    // allocated without the video effects. It may be possible to hold on to
-    // the input buffer for less time than what is needed to post-process it
-    // - it could be released once the processor has imported it into the
-    // graphical API it uses to run the post-processing logic.
-    // TODO(https://crbug.com/339141106): Consider having an additional pool
-    // for post-processing output buffers, separate from the pool used to
-    // allocate the original buffers.
-    Buffer out_buffer;
-    const VideoCaptureDevice::Client::ReserveResult reserve_result =
-        ReserveOutputBuffer(
-            buffer.format.frame_size, buffer.format.pixel_format,
-            /*frame_feedback_id=*/0, &out_buffer, nullptr, nullptr);
+    const auto format = buffer.format;
+    auto out_buffer_optional =
+        ReserveEffectsOutputBuffer(format, /*frame_feedback_id=*/0);
+    if (!out_buffer_optional) {
+      return;
+    }
+    Buffer out_buffer = std::move(out_buffer_optional).value();
 
-    if (reserve_result ==
-        VideoCaptureDevice::Client::ReserveResult::kSucceeded) {
-      // Must happen here since we move out of `out_buffer` in the call to
-      // post-processor:
-      const VideoCaptureBufferType out_buffer_type =
-          buffer_pool_->GetBufferType(out_buffer.id);
-      const auto format = buffer.format;
+    // Must happen here since we move out of `out_buffer` in the call to
+    // post-processor:
+    const VideoCaptureBufferType out_buffer_type =
+        buffer_pool_->GetBufferType(out_buffer.id);
 
-      // The buffers were reserved but has not yet been reported as ready to the
-      // `receiver_`. Once the post-processor has completed, we will call
-      // `OnPostProcessDone()` & thus notify the receiver from there.
-      // TODO(https://crbug.com/345688428): drop the frame if we're already
-      // waiting for processing to finish for too many. Maybe if pool
-      // utilization is approaching 70%?
-      auto post_process_data = base::BindOnce(
-          &VideoCaptureEffectsProcessor::PostProcessExternalBuffer,
-          effects_processor_->GetWeakPtr(), std::move(buffer), std::move(info),
-          std::move(out_buffer), format, out_buffer_type,
-          base::BindOnce(&VideoCaptureDeviceClient::OnPostProcessDone,
-                         weak_ptr_factory_.GetWeakPtr()));
-      if (!effects_processor_task_runner_->RunsTasksInCurrentSequence()) {
-        effects_processor_task_runner_->PostTask(FROM_HERE,
-                                                 std::move(post_process_data));
-        return;
-      }
+    // The buffers were reserved but has not yet been reported as ready to the
+    // `receiver_`. Once the post-processor has completed, we will call
+    // `OnPostProcessDone()` & thus notify the receiver from there.
+
+    // TODO(https://crbug.com/345688428): drop the frame if we're already
+    // waiting for processing to finish for too many. Maybe if pool
+    // utilization is approaching 70%?
+    auto post_process_data = base::BindOnce(
+        &VideoCaptureEffectsProcessor::PostProcessExternalBuffer,
+        effects_processor_->GetWeakPtr(), std::move(buffer), std::move(info),
+        std::move(out_buffer), format, out_buffer_type,
+        base::BindOnce(&VideoCaptureDeviceClient::OnPostProcessDone,
+                       weak_ptr_factory_.GetWeakPtr()));
+    if (effects_processor_task_runner_->RunsTasksInCurrentSequence()) {
       std::move(post_process_data).Run();
     } else {
-      // We weren't able to reserve the buffer for the post-processor's
-      // result. We could either drop the frame or deliver the unprocessed
-      // buffer to the consumer, but since post-processing can apply
-      // privacy-preserving effects, we should not deliver unprocessed frames
-      // without user intervention, hence we report failure.
-      receiver_->OnFrameDropped(
-          ConvertReservationFailureToFrameDropReason(reserve_result));
+      effects_processor_task_runner_->PostTask(FROM_HERE,
+                                               std::move(post_process_data));
     }
     return;
   }
@@ -950,63 +967,34 @@
 #if BUILDFLAG(ENABLE_VIDEO_EFFECTS)
   if (base::FeatureList::IsEnabled(media::kCameraMicEffects) &&
       effects_processor_) {
-    // We need to allocate the output buffer since the post-processor cannot
-    // operate in-place. This new `out_buffer`, along with original `buffer`,
-    // will be considered as held for producer until the post-processor has
-    // finished processing their contents, after which the `buffer` should be
-    // marked as unused (`RelinquishProducerReservation()`) and `out_buffer`
-    // will be marked as held for consumer.
-    // Note that this means we're allocating 2x as many buffers as we'd have
-    // allocated without the video effects. It may be possible to hold on to
-    // the input buffer for less time than what is needed to post-process it
-    // - it could be released once the processor has imported it into the
-    // graphical API it uses to run the post-processing logic.
-    // TODO(https://crbug.com/339141106): Consider having an additional pool
-    // for post-processing output buffers, separate from the pool used to
-    // allocate the original buffers.
-
-    Buffer out_buffer;
-    const VideoCaptureDevice::Client::ReserveResult reserve_result =
-        ReserveOutputBuffer(format.frame_size, format.pixel_format,
-                            buffer.frame_feedback_id, &out_buffer, nullptr,
-                            nullptr);
-
-    const bool reserve_succeeded =
-        reserve_result == VideoCaptureDevice::Client::ReserveResult::kSucceeded;
-
-    if (reserve_succeeded) {
-      // Must happen here since we move out of `buffer` & `out_buffer` in the
-      // call to post-processor:
-      const VideoCaptureBufferType in_buffer_type =
-          buffer_pool_->GetBufferType(buffer.id);
-
-      const VideoCaptureBufferType out_buffer_type =
-          buffer_pool_->GetBufferType(out_buffer.id);
-
-      // The buffers were reserved but has not yet been reported as ready to the
-      // `receiver_`. Once the post-processor has completed, we will call
-      // `OnPostProcessDone()` & thus notify the receiver from there.
-
-      // TODO(https://crbug.com/345688428): drop the frame if we're already
-      // waiting for processing to finish for too many. Maybe if pool
-      // utilization is approaching 70%?
-      effects_processor_->PostProcessBuffer(
-          std::move(buffer), std::move(info), in_buffer_type,
-          std::move(out_buffer), format, out_buffer_type,
-          base::BindOnce(&VideoCaptureDeviceClient::OnPostProcessDone,
-                         weak_ptr_factory_.GetWeakPtr()));
-      return;
-    } else {
-      // We weren't able to reserve the buffer for the post-processor's
-      // result. We could either drop the frame or deliver the unprocessed
-      // buffer to the consumer, but since post-processing can apply
-      // privacy-preserving effects, we should not deliver unprocessed frames
-      // without user intervention, hence we report failure.
-
-      receiver_->OnFrameDropped(
-          ConvertReservationFailureToFrameDropReason(reserve_result));
+    auto out_buffer_optional =
+        ReserveEffectsOutputBuffer(format, /*frame_feedback_id=*/0);
+    if (!out_buffer_optional) {
       return;
     }
+    Buffer out_buffer = std::move(out_buffer_optional).value();
+
+    // Must happen here since we move out of `buffer` & `out_buffer` in the
+    // call to post-processor:
+    const VideoCaptureBufferType in_buffer_type =
+        buffer_pool_->GetBufferType(buffer.id);
+
+    const VideoCaptureBufferType out_buffer_type =
+        buffer_pool_->GetBufferType(out_buffer.id);
+
+    // The buffers were reserved but has not yet been reported as ready to the
+    // `receiver_`. Once the post-processor has completed, we will call
+    // `OnPostProcessDone()` & thus notify the receiver from there.
+
+    // TODO(https://crbug.com/345688428): drop the frame if we're already
+    // waiting for processing to finish for too many. Maybe if pool
+    // utilization is approaching 70%?
+    effects_processor_->PostProcessBuffer(
+        std::move(buffer), std::move(info), in_buffer_type,
+        std::move(out_buffer), format, out_buffer_type,
+        base::BindOnce(&VideoCaptureDeviceClient::OnPostProcessDone,
+                       weak_ptr_factory_.GetWeakPtr()));
+    return;
   }
 #endif
 
diff --git a/media/capture/video/video_capture_device_client.h b/media/capture/video/video_capture_device_client.h
index 47e126b8..755f12e 100644
--- a/media/capture/video/video_capture_device_client.h
+++ b/media/capture/video/video_capture_device_client.h
@@ -185,6 +185,10 @@
       int frame_feedback_id);
 
 #if BUILDFLAG(ENABLE_VIDEO_EFFECTS)
+  std::optional<VideoCaptureDevice::Client::Buffer> ReserveEffectsOutputBuffer(
+      const VideoCaptureFormat& format,
+      const int frame_feedback_id);
+
   void OnPostProcessDone(base::expected<PostProcessDoneInfo,
                                         video_effects::mojom::PostProcessError>
                              post_process_info_or_error);
diff --git a/media/filters/stream_parser_factory.cc b/media/filters/stream_parser_factory.cc
index c21529a..9df07868 100644
--- a/media/filters/stream_parser_factory.cc
+++ b/media/filters/stream_parser_factory.cc
@@ -94,8 +94,9 @@
 struct SupportedTypeInfo {
   const char* type;
   const ParserFactoryFunction factory_function;
-  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
-  // #global-scope
+  // This field is not a raw_ptr<> because both levels of pointer only ever
+  // point to statically-allocated data which is never freed, and hence cannot
+  // dangle.
   RAW_PTR_EXCLUSION const CodecInfo* const* codecs;
 };
 
diff --git a/media/gpu/chromeos/registered_frame_converter.cc b/media/gpu/chromeos/registered_frame_converter.cc
index dc079a1..18b71c205 100644
--- a/media/gpu/chromeos/registered_frame_converter.cc
+++ b/media/gpu/chromeos/registered_frame_converter.cc
@@ -40,9 +40,11 @@
     return OnError(FROM_HERE, "Failed to create VideoFrame.");
   }
 
-  // Merges the metadata from the frame. Use of MergeMetadataFrom() avoids
-  // overwriting |video_frame->metadata()->tracking_token|.
-  video_frame->metadata().MergeMetadataFrom(frame->metadata());
+  // It is fine to use set_metadata() to replace `video_frame`'s metadata with
+  // that of `frame`. The `tracking_token` field of each are the same.
+  video_frame->set_metadata(frame->metadata());
+  video_frame->set_color_space(frame->ColorSpace());
+  video_frame->set_hdr_metadata(frame->hdr_metadata());
 
   // A reference to |frame| is stored in |registry_|. Next, a reference to
   // |registry_| is stored in the destruction observer of the generated
diff --git a/media/gpu/vaapi/test/fake_libva_driver/BUILD.gn b/media/gpu/vaapi/test/fake_libva_driver/BUILD.gn
index e4cd64f..aca2987 100644
--- a/media/gpu/vaapi/test/fake_libva_driver/BUILD.gn
+++ b/media/gpu/vaapi/test/fake_libva_driver/BUILD.gn
@@ -5,15 +5,10 @@
 import("//media/gpu/args.gni")
 import("//testing/test.gni")
 
-if (is_linux) {
-  shared_library("fake_gbm") {
-    sources = [
-      "fake_gbm.cc",
-      "fake_gbm.h",
-    ]
+shared_library("fake_gbm") {
+  sources = [ "fake_gbm.cc" ]
 
-    deps = [ "//base" ]
-  }
+  deps = [ "//base" ]
 }
 
 shared_library("fake_drv_video") {
@@ -58,6 +53,7 @@
   ]
 
   deps = [
+    ":fake_gbm",
     "//base",
     "//build/config/linux/libdrm",
     "//third_party/dav1d",
@@ -70,10 +66,6 @@
   if (is_chromeos) {
     public_deps = [ "//third_party/minigbm" ]
   }
-
-  if (is_linux) {
-    public_deps = [ ":fake_gbm" ]
-  }
 }
 
 test("fake_libva_driver_unittest") {
diff --git a/media/gpu/vaapi/test/fake_libva_driver/DEPS b/media/gpu/vaapi/test/fake_libva_driver/DEPS
new file mode 100644
index 0000000..7e7e464
--- /dev/null
+++ b/media/gpu/vaapi/test/fake_libva_driver/DEPS
@@ -0,0 +1,8 @@
+specific_include_rules = {
+  'fake_gbm\.cc': [
+    '+third_party/minigbm/src/gbm.h',
+  ],
+  'scoped_bo_mapping_factory\.h': [
+    '+third_party/minigbm/src/gbm.h',
+  ],
+}
diff --git a/media/gpu/vaapi/test/fake_libva_driver/fake_gbm.cc b/media/gpu/vaapi/test/fake_libva_driver/fake_gbm.cc
index 780b8d5..1f01b56 100644
--- a/media/gpu/vaapi/test/fake_libva_driver/fake_gbm.cc
+++ b/media/gpu/vaapi/test/fake_libva_driver/fake_gbm.cc
@@ -2,14 +2,25 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Fake GBM is a GBM "implementation" designed to run in a completely headless
+// environment. This means that fake GBM does not need an actual GEM driver to
+// operate, and instead uses simple tmpfiles to back its memory allocation.
+//
+// The motivation behind Fake GBM is that it was discovered that not all system
+// GBM implementations behave the same, and this can sometimes cause problems
+// when testing hardware accelerated video decoders on different systems, even
+// when using the fake VA-API backend.
+//
+// Fake GBM should be ABI compatible with Minigbm. So usually the shared library
+// built for Fake GBM will simply be DLL injected (using LD_PRELOAD generally)
+// into the test process.
+
 #ifdef UNSAFE_BUFFERS_BUILD
 // We need to conform to the GBM API, which unfortunately involves a lot of
 // unsafe buffer access to maintain C99 compatibility.
 #pragma allow_unsafe_buffers
 #endif
 
-#include "media/gpu/vaapi/test/fake_libva_driver/fake_gbm.h"
-
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -19,13 +30,23 @@
 
 #include "base/memory/raw_ptr.h"
 #include "base/notreached.h"
+#include "third_party/minigbm/src/gbm.h"
 
 #define PAGE_SIZE 4096
 #define ALIGN(x, y) (((x + y - 1) / y) * y)
 
 #define DRM_NODE_RENDER 2
 
-int drmGetNodeTypeFromFd(int fd) {
+#define GBM_EXPORT __attribute__((visibility("default")))
+
+// This is an opaque type in GBM, so its definition does not really matter.
+struct gbm_device {
+  uint8_t pad;
+};
+
+// This is technically not GBM, it's DRM, but it's necessary for some GBM and
+// libva clients to be happy with our fake drivers.
+extern "C" GBM_EXPORT int drmGetNodeTypeFromFd(int fd) {
   return DRM_NODE_RENDER;
 }
 
@@ -207,8 +228,9 @@
 }
 
 extern "C" GBM_EXPORT int gbm_bo_get_fd_for_plane(struct gbm_bo* bo,
-                                                  size_t plane) {
+                                                  int plane) {
   CHECK(bo);
+  CHECK(plane >= 0);
   CHECK(static_cast<int>(plane) < gbm_bo_get_plane_count(bo));
 
   return gbm_bo_get_fd(bo);
diff --git a/media/gpu/vaapi/test/fake_libva_driver/fake_gbm.h b/media/gpu/vaapi/test/fake_libva_driver/fake_gbm.h
deleted file mode 100644
index d1d50f0f4c..0000000
--- a/media/gpu/vaapi/test/fake_libva_driver/fake_gbm.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MEDIA_GPU_VAAPI_TEST_FAKE_LIBVA_DRIVER_FAKE_GBM_H_
-#define MEDIA_GPU_VAAPI_TEST_FAKE_LIBVA_DRIVER_FAKE_GBM_H_
-
-#include <stdint.h>
-
-#include <memory>
-
-#define GBM_EXPORT __attribute__((visibility("default")))
-
-#define FAKE_GBM_FOURCC(a, b, c, d)                                       \
-  ((((uint32_t)d) << 24) | (((uint32_t)c) << 16) | (((uint32_t)b) << 8) | \
-   ((uint32_t)a))
-
-#define GBM_FORMAT_NV12 FAKE_GBM_FOURCC('N', 'V', '1', '2')
-#define GBM_FORMAT_P010 FAKE_GBM_FOURCC('P', '0', '1', '0')
-#define GBM_FORMAT_YUV420 FAKE_GBM_FOURCC('Y', 'U', '1', '2')
-
-#define GBM_BO_IMPORT_FD_PLANAR 0x5504
-#define GBM_BO_IMPORT_FD_MODIFIER 0x5505
-
-#define GBM_MAX_PLANES 3
-
-struct gbm_bo;
-
-struct gbm_device {
-  uint8_t pad;
-};
-
-struct gbm_import_fd_modifier_data {
-  uint32_t width;
-  uint32_t height;
-  uint32_t format;
-  uint32_t num_fds;
-  int fds[GBM_MAX_PLANES];
-  int strides[GBM_MAX_PLANES];
-  int offsets[GBM_MAX_PLANES];
-  uint64_t modifier;
-};
-
-extern "C" GBM_EXPORT int drmGetNodeTypeFromFd(int fd);
-
-extern "C" GBM_EXPORT struct gbm_device* gbm_create_device(int fd);
-extern "C" GBM_EXPORT void gbm_device_destroy(struct gbm_device* gbm);
-extern "C" GBM_EXPORT struct gbm_bo* gbm_bo_create(struct gbm_device* gbm,
-                                                   uint32_t width,
-                                                   uint32_t height,
-                                                   uint32_t format,
-                                                   uint32_t flags);
-extern "C" GBM_EXPORT void gbm_bo_destroy(struct gbm_bo* bo);
-extern "C" GBM_EXPORT void* gbm_bo_map2(struct gbm_bo* bo,
-                                        uint32_t x,
-                                        uint32_t y,
-                                        uint32_t width,
-                                        uint32_t height,
-                                        uint32_t transfer_flags,
-                                        uint32_t* stride,
-                                        void** map_data,
-                                        int plane);
-extern "C" GBM_EXPORT void gbm_bo_unmap(struct gbm_bo* bo, void* map_data);
-extern "C" GBM_EXPORT struct gbm_bo* gbm_bo_import(struct gbm_device* gbm,
-                                                   uint32_t type,
-                                                   void* buffer,
-                                                   uint32_t usage);
-extern "C" GBM_EXPORT int gbm_bo_get_fd(struct gbm_bo* bo);
-extern "C" GBM_EXPORT int gbm_bo_get_fd_for_plane(struct gbm_bo* bo,
-                                                  size_t plane);
-extern "C" GBM_EXPORT uint64_t gbm_bo_get_modifier(struct gbm_bo* bo);
-extern "C" GBM_EXPORT uint32_t gbm_bo_get_format(struct gbm_bo* bo);
-extern "C" GBM_EXPORT int gbm_bo_get_plane_count(struct gbm_bo* bo);
-extern "C" GBM_EXPORT uint32_t gbm_bo_get_offset(struct gbm_bo* bo,
-                                                 size_t plane);
-extern "C" GBM_EXPORT uint32_t gbm_bo_get_stride_for_plane(struct gbm_bo* bo,
-                                                           size_t plane);
-extern "C" GBM_EXPORT uint32_t gbm_bo_get_bpp(struct gbm_bo* bo);
-extern "C" GBM_EXPORT uint32_t gbm_bo_get_width(struct gbm_bo* bo);
-extern "C" GBM_EXPORT uint32_t gbm_bo_get_height(struct gbm_bo* bo);
-
-#define GBM_BO_USE_SW_READ_OFTEN (1 << 9)
-#define GBM_BO_USE_SW_WRITE_OFTEN (1 << 11)
-
-#define GBM_BO_TRANSFER_READ_WRITE 0b11
-
-namespace ui {
-using ScopedGbmDevice = std::unique_ptr<gbm_device>;
-}
-
-#endif  // MEDIA_GPU_VAAPI_TEST_FAKE_LIBVA_DRIVER_FAKE_GBM_H_
diff --git a/media/gpu/vaapi/test/fake_libva_driver/scoped_bo_mapping_factory.cc b/media/gpu/vaapi/test/fake_libva_driver/scoped_bo_mapping_factory.cc
index b79b68e..70730402 100644
--- a/media/gpu/vaapi/test/fake_libva_driver/scoped_bo_mapping_factory.cc
+++ b/media/gpu/vaapi/test/fake_libva_driver/scoped_bo_mapping_factory.cc
@@ -20,15 +20,11 @@
     struct dma_buf_sync sync_start;
     memset(&sync_start, 0, sizeof(sync_start));
     sync_start.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW;
-#if defined(MINIGBM)
-    PCHECK(HANDLE_EINTR(ioctl(plane.prime_fd.get(), DMA_BUF_IOCTL_SYNC,
-                              &sync_start)) == 0);
-#else
+
     // This will fail for the fake GBM backend, so ignore the return result. We
-    // leave the IOCTL in here anyway in case a Linux user wants to try the fake
-    // VA-API driver with a real GBM that happens to not be minigbm.
+    // leave the IOCTL in here anyway in case we're running on top of a real GEM
+    // driver.
     HANDLE_EINTR(ioctl(plane.prime_fd.get(), DMA_BUF_IOCTL_SYNC, &sync_start));
-#endif
   }
 }
 
@@ -37,12 +33,7 @@
     struct dma_buf_sync sync_end;
     memset(&sync_end, 0, sizeof(sync_end));
     sync_end.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
-#if defined(MINIGBM)
-    PCHECK(HANDLE_EINTR(ioctl(plane.prime_fd.get(), DMA_BUF_IOCTL_SYNC,
-                              &sync_end)) == 0);
-#else
     HANDLE_EINTR(ioctl(plane.prime_fd.get(), DMA_BUF_IOCTL_SYNC, &sync_end));
-#endif
   }
 }
 
diff --git a/media/gpu/vaapi/test/fake_libva_driver/scoped_bo_mapping_factory.h b/media/gpu/vaapi/test/fake_libva_driver/scoped_bo_mapping_factory.h
index ff577d9..28663c9 100644
--- a/media/gpu/vaapi/test/fake_libva_driver/scoped_bo_mapping_factory.h
+++ b/media/gpu/vaapi/test/fake_libva_driver/scoped_bo_mapping_factory.h
@@ -5,21 +5,13 @@
 #ifndef MEDIA_GPU_VAAPI_TEST_FAKE_LIBVA_DRIVER_SCOPED_BO_MAPPING_FACTORY_H_
 #define MEDIA_GPU_VAAPI_TEST_FAKE_LIBVA_DRIVER_SCOPED_BO_MAPPING_FACTORY_H_
 
-#include "build/build_config.h"
-
-#if !BUILDFLAG(IS_CHROMEOS)
-#include "media/gpu/vaapi/test/fake_libva_driver/fake_gbm.h"
-#else
-#include <gbm.h>
-
-#include "ui/gfx/linux/scoped_gbm_device.h"
-#endif  // BUILDFLAG(IS_CHROMEOS)
-
 #include <memory>
 
 #include "base/files/scoped_file.h"
 #include "base/memory/raw_ref.h"
 #include "base/synchronization/lock.h"
+#include "third_party/minigbm/src/gbm.h"
+#include "ui/gfx/linux/scoped_gbm_device.h"
 
 namespace media::internal {
 
diff --git a/sandbox/win/BUILD.gn b/sandbox/win/BUILD.gn
index 8848277d..a82eaae 100644
--- a/sandbox/win/BUILD.gn
+++ b/sandbox/win/BUILD.gn
@@ -170,9 +170,9 @@
   ]
 
   deps = [
+    ":maybe_set_appcontainer_acls",
     ":service_resolver",
     "//base:base_static",
-    "//build/config/win:maybe_set_appcontainer_acls",
   ]
 
   libs = [
@@ -233,6 +233,27 @@
   configs += [ "//build/config/win:delayloads" ]
 }
 
+group("maybe_set_appcontainer_acls") {
+  # Exclude setting ACLs when build is not happening on Windows.
+  if (current_cpu == target_cpu && host_os == "win") {
+    deps = [ ":set_appcontainer_acls" ]
+  }
+}
+
+if (current_cpu == target_cpu && host_os == "win") {
+  action("set_appcontainer_acls") {
+    script = "//build/win/set_appcontainer_acls.py"
+    stamp_file = "$target_out_dir/acls.stamp"
+    inputs = [ script ]
+    outputs = [ stamp_file ]
+
+    args = [
+      "--stamp=" + rebase_path(stamp_file, root_out_dir),
+      "--dir=" + rebase_path(root_out_dir, root_out_dir),
+    ]
+  }
+}
+
 shared_library("sbox_integration_test_hooking_dll") {
   testonly = true
   sources = [ "tests/integration_tests/hooking_dll.cc" ]
diff --git a/services/device/generic_sensor/platform_sensor_provider.cc b/services/device/generic_sensor/platform_sensor_provider.cc
index df26f86..0621ffd 100644
--- a/services/device/generic_sensor/platform_sensor_provider.cc
+++ b/services/device/generic_sensor/platform_sensor_provider.cc
@@ -214,11 +214,11 @@
   }
 
   size_t offset = GetSensorReadingSharedBufferOffset(type);
-  CHECK(offset % sizeof(SensorReadingSharedBuffer) == 0u);
+  CHECK(offset % sizeof(SensorReadingSharedBuffer) == 0);
 
   SensorReadingSharedBuffer& buffer =
       buffers[offset / sizeof(SensorReadingSharedBuffer)];
-  std::ranges::fill(base::byte_span_from_ref(buffer), 0u);
+  std::ranges::fill(base::byte_span_from_ref(buffer), 0);
   return &buffer;
 }
 
diff --git a/services/device/public/cpp/test/fake_sensor_and_provider.cc b/services/device/public/cpp/test/fake_sensor_and_provider.cc
index 9c122510..562fbf8 100644
--- a/services/device/public/cpp/test/fake_sensor_and_provider.cc
+++ b/services/device/public/cpp/test/fake_sensor_and_provider.cc
@@ -371,11 +371,11 @@
   }
 
   size_t offset = GetSensorReadingSharedBufferOffset(type);
-  CHECK(offset % sizeof(SensorReadingSharedBuffer) == 0u);
+  CHECK(offset % sizeof(SensorReadingSharedBuffer) == 0);
 
   SensorReadingSharedBuffer& buffer =
       buffers[offset / sizeof(SensorReadingSharedBuffer)];
-  std::ranges::fill(base::byte_span_from_ref(buffer), 0u);
+  std::ranges::fill(base::byte_span_from_ref(buffer), 0);
   return &buffer;
 }
 
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc
index e6a18483..ce41918 100644
--- a/services/network/network_context_unittest.cc
+++ b/services/network/network_context_unittest.cc
@@ -98,6 +98,11 @@
 #include "net/cookies/cookie_store_test_callbacks.h"
 #include "net/cookies/cookie_util.h"
 #include "net/cookies/site_for_cookies.h"
+
+#if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS)
+#include "net/device_bound_sessions/session_service.h"
+#endif  // BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS)
+
 #include "net/disk_cache/cache_util.h"
 #include "net/disk_cache/disk_cache.h"
 #include "net/disk_cache/memory/mem_backend_impl.h"
@@ -1128,10 +1133,19 @@
 
   std::unique_ptr<NetworkContext> network_context =
       CreateContextWithParams(std::move(context_params));
-  EXPECT_TRUE(
-      network_context->url_request_context()->device_bound_session_service());
+  net::device_bound_sessions::SessionService* service =
+      network_context->url_request_context()->device_bound_session_service();
+  EXPECT_TRUE(service);
   EXPECT_TRUE(
       network_context->url_request_context()->device_bound_session_store());
+
+  // Wait for the service to finish initial session load from the session store
+  // file.
+  base::test::TestFuture<
+      const std::vector<net::device_bound_sessions::SessionKey>&>
+      future;
+  service->GetAllSessionsAsync(future.GetCallback());
+  ASSERT_TRUE(future.Wait());
 }
 #endif  // BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS)
 
diff --git a/services/network/prefetch_matches.cc b/services/network/prefetch_matches.cc
index c298876..e9e71be 100644
--- a/services/network/prefetch_matches.cc
+++ b/services/network/prefetch_matches.cc
@@ -12,6 +12,7 @@
 #include <ostream>
 #include <string>
 #include <string_view>
+#include <type_traits>
 #include <unordered_map>
 #include <utility>
 
@@ -20,6 +21,7 @@
 #include "base/containers/contains.h"
 #include "base/containers/fixed_flat_map.h"
 #include "base/containers/fixed_flat_set.h"
+#include "base/containers/span.h"
 #include "base/logging.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/stack_allocated.h"
diff --git a/services/webnn/webnn_graph_impl_backend_test.cc b/services/webnn/webnn_graph_impl_backend_test.cc
index 7601691..092bd03 100644
--- a/services/webnn/webnn_graph_impl_backend_test.cc
+++ b/services/webnn/webnn_graph_impl_backend_test.cc
@@ -415,8 +415,7 @@
  public:
   WebNNGraphImplBackendTest()
       : scoped_feature_list_(
-            webnn::mojom::features::kWebMachineLearningNeuralNetwork) {
-  }
+            webnn::mojom::features::kWebMachineLearningNeuralNetwork) {}
 
   void SetUp() override;
   void SetUpBase();
@@ -845,7 +844,7 @@
                              15}},
         .filter = {.type = OperandDataType::kFloat32,
                    .dimensions = {1, 1, 3, 3},
-                   .values = std::vector<float>(9, 1)},
+                   .values = {1, 1, 1, 1, 1, 1, 1, 1, 1}},
         .attributes = {.bias =
                            OperandInfo<float>{.type = OperandDataType::kFloat32,
                                               .dimensions = {1},
@@ -869,7 +868,7 @@
                              13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}},
         .filter = {.type = OperandDataType::kFloat32,
                    .dimensions = {1, 1, 3, 3},
-                   .values = std::vector<float>(9, 1)},
+                   .values = {1, 1, 1, 1, 1, 1, 1, 1, 1}},
         .attributes = {.padding = {1, 1, 1, 1},
                        .bias =
                            OperandInfo<float>{.type = OperandDataType::kFloat32,
@@ -896,7 +895,7 @@
                              13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}},
         .filter = {.type = OperandDataType::kFloat32,
                    .dimensions = {1, 1, 3, 3},
-                   .values = std::vector<float>(9, 1)},
+                   .values = {1, 1, 1, 1, 1, 1, 1, 1, 1}},
         .attributes = {.padding = {1, 1, 1, 1},
                        .bias =
                            OperandInfo<float>{.type = OperandDataType::kFloat32,
@@ -980,7 +979,7 @@
                                   .values = {-3, -2, -1, -4, 0, 2, 1, 3, 4}},
                         .filter = {.type = OperandDataType::kFloat32,
                                    .dimensions = {1, 1, 2, 2},
-                                   .values = std::vector<float>(4, 1)},
+                                   .values = {1, 1, 1, 1}},
                         .output = {.type = OperandDataType::kFloat32,
                                    .dimensions = {1, 1, 2, 2},
                                    .values = {-0.9, -0.5, 0, 0.9}}}
@@ -998,7 +997,8 @@
                              13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}},
         .filter = {.type = OperandDataType::kFloat32,
                    .dimensions = {1, 1, 3, 3},
-                   .values = std::vector<float>(9, 0.05)},
+                   .values = {0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
+                              0.05}},
         .attributes = {.padding = {1, 1, 1, 1}},
         .output = {.type = OperandDataType::kFloat32,
                    .dimensions = {1, 1, 5, 5},
@@ -1030,7 +1030,6 @@
   mojom::ElementWiseBinary::Kind kind;
   OperandInfo<O> output;
   void Test(WebNNGraphImplBackendTest& helper) {
-
     // Build the graph with mojo type.
     mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote =
         helper.BindNewGraphBuilderRemote();
@@ -1195,13 +1194,11 @@
 
   // [[1  2]
   //  [6  7]] with shape (2, 2)
-  VerifyFloatDataIsEqual(named_outputs["output1"],
-                         std::array<float, 4>{1, 2, 6, 7});
+  VerifyFloatDataIsEqual(named_outputs["output1"], {1, 2, 6, 7});
   // [[3  4]
   //  [5  8]
   //  [9  10]] with shape (3, 2)
-  VerifyFloatDataIsEqual(named_outputs["output2"],
-                         std::array<float, 6>{3, 4, 5, 8, 9, 10});
+  VerifyFloatDataIsEqual(named_outputs["output2"], {3, 4, 5, 8, 9, 10});
 }
 
 template <typename T>
@@ -1382,10 +1379,9 @@
       BuildAndCompute(context(), std::move(remote), builder.TakeGraphInfo(),
                       std::move(named_inputs));
 
-  VerifyFloatDataIsEqual(
-      named_outputs["output"],
-      std::array<float, 24>({0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-                             13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}));
+  VerifyFloatDataIsEqual(named_outputs["output"],
+                         {0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                          13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24});
 }
 
 // Test building and computing a graph with two operators (reshape as the
@@ -1516,14 +1512,12 @@
       BuildAndCompute(context(), std::move(remote), builder.TakeGraphInfo(),
                       std::move(named_inputs));
 
-  VerifyFloatDataIsEqual(
-      named_outputs["output1"],
-      std::vector<float>({-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12,
-                          13, 14, 15, 16, 17, 18, 19, 20, 21, 22,  23,  24}));
-  VerifyFloatDataIsEqual(
-      named_outputs["output2"],
-      std::vector<float>({0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-                          13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}));
+  VerifyFloatDataIsEqual(named_outputs["output1"],
+                         {-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12,
+                          13, 14, 15, 16, 17, 18, 19, 20, 21, 22,  23,  24});
+  VerifyFloatDataIsEqual(named_outputs["output2"],
+                         {0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                          13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24});
 }
 
 struct GemmAttributes {
@@ -2155,8 +2149,7 @@
       BuildAndCompute(context(), std::move(remote), builder.TakeGraphInfo(),
                       std::move(named_inputs));
 
-  VerifyFloatDataIsEqual(named_outputs["output"],
-                         std::vector<float>({30, 30, 70, 70}));
+  VerifyFloatDataIsEqual(named_outputs["output"], {30, 30, 70, 70});
 }
 
 // Test building and computing a graph with one input and one constant.
@@ -2182,8 +2175,7 @@
       BuildAndCompute(context(), std::move(remote), builder.TakeGraphInfo(),
                       std::move(named_inputs));
 
-  VerifyFloatDataIsEqual(named_outputs["output"],
-                         std::vector<float>({12, 14, 12, 14}));
+  VerifyFloatDataIsEqual(named_outputs["output"], {12, 14, 12, 14});
 }
 
 template <typename T>
@@ -2551,21 +2543,21 @@
                   .values = {-4, -3, -2, -1, 0, 1, 2, 3}},
         .weight = {.type = OperandDataType::kFloat32,
                    .dimensions = {direction_count, 4 * hidden_size, input_size},
-                   .values = std::vector<float>(8, 1)},
+                   .values = {1, 1, 1, 1, 1, 1, 1, 1}},
         .recurrent_weight = {.type = OperandDataType::kFloat32,
                              .dimensions = {direction_count, 4 * hidden_size,
                                             hidden_size},
-                             .values = std::vector<float>(4, 1)},
+                             .values = {1, 1, 1, 1}},
         .steps = steps,
         .hidden_size = hidden_size,
         .bias =
             OperandInfo<float>{.type = OperandDataType::kFloat32,
                                .dimensions = {direction_count, 4 * hidden_size},
-                               .values = std::vector<float>(4, 0.5)},
+                               .values = {0.5, 0.5, 0.5, 0.5}},
         .recurrent_bias =
             OperandInfo<float>{.type = OperandDataType::kFloat32,
                                .dimensions = {direction_count, 4 * hidden_size},
-                               .values = std::vector<float>(4, 0.5)},
+                               .values = {0.5, 0.5, 0.5, 0.5}},
         .attributes =
             {.activations = {mojom::RecurrentNetworkActivation::kRelu,
                              mojom::RecurrentNetworkActivation::kRelu,
@@ -2592,21 +2584,22 @@
                   .values = {1, 2, 3, 4}},
         .weight = {.type = OperandDataType::kFloat32,
                    .dimensions = {direction_count, 4 * hidden_size, input_size},
-                   .values = std::vector<float>(16, 1)},
+                   .values = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}},
         .recurrent_weight = {.type = OperandDataType::kFloat32,
                              .dimensions = {direction_count, 4 * hidden_size,
                                             hidden_size},
-                             .values = std::vector<float>(16, 1)},
+                             .values = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                        1, 1, 1}},
         .steps = steps,
         .hidden_size = hidden_size,
         .bias =
             OperandInfo<float>{.type = OperandDataType::kFloat32,
                                .dimensions = {direction_count, 4 * hidden_size},
-                               .values = std::vector<float>(8, 1)},
+                               .values = {1, 1, 1, 1, 1, 1, 1, 1}},
         .peephole_weight =
             OperandInfo<float>{.type = OperandDataType::kFloat32,
                                .dimensions = {direction_count, 3 * hidden_size},
-                               .values = std::vector<float>(6, 0)},
+                               .values = {0, 0, 0, 0, 0, 0}},
         .attributes =
             {.activations = {mojom::RecurrentNetworkActivation::kRelu,
                              mojom::RecurrentNetworkActivation::kRelu,
@@ -2985,8 +2978,7 @@
       BuildAndCompute(context(), std::move(remote), builder.TakeGraphInfo(),
                       std::move(named_inputs));
 
-  VerifyFloatDataIsEqual(named_outputs["output"],
-                         std::vector<float>({30, 30, 70, 70}));
+  VerifyFloatDataIsEqual(named_outputs["output"], {30, 30, 70, 70});
 }
 
 // Test building and computing a graph with two inputs and two constant in
@@ -3033,8 +3025,7 @@
       BuildAndCompute(context(), std::move(remote), builder.TakeGraphInfo(),
                       std::move(named_inputs));
 
-  VerifyFloatDataIsEqual(named_outputs["output"],
-                         std::vector<float>({30, 30, 70, 70}));
+  VerifyFloatDataIsEqual(named_outputs["output"], {30, 30, 70, 70});
 }
 
 // Test building and computing a graph whose gemm operator takes a reshaped
@@ -3078,8 +3069,7 @@
       BuildAndCompute(context(), std::move(remote), builder.TakeGraphInfo(),
                       std::move(named_inputs));
 
-  VerifyFloatDataIsEqual(named_outputs["output"],
-                         std::vector<float>({8, 11, 16, 23}));
+  VerifyFloatDataIsEqual(named_outputs["output"], {8, 11, 16, 23});
 }
 
 // Test building a graph whose add operator takes a reshaped
@@ -3115,8 +3105,7 @@
   base::flat_map<std::string, std::vector<float>> named_outputs =
       BuildAndCompute(context(), std::move(remote), builder.TakeGraphInfo(),
                       std::move(named_inputs));
-  VerifyFloatDataIsEqual(named_outputs["output"],
-                         std::vector<float>({2, 2, 2, 2}));
+  VerifyFloatDataIsEqual(named_outputs["output"], {2, 2, 2, 2});
 }
 
 // Test building and computing a graph whose relu operator only has a
@@ -3140,8 +3129,7 @@
       BuildAndCompute<float>(context(), std::move(remote),
                              builder.TakeGraphInfo(),
                              /*named_inputs=*/{});
-  VerifyFloatDataIsEqual(named_outputs["output"],
-                         std::vector<float>({0, 0, 1}));
+  VerifyFloatDataIsEqual(named_outputs["output"], {0, 0, 1});
 }
 
 // Test building and computing a graph whose add operator only has constant
@@ -3170,8 +3158,7 @@
       BuildAndCompute<float>(context(), std::move(remote),
                              builder.TakeGraphInfo(),
                              /*named_inputs=*/{});
-  VerifyFloatDataIsEqual(named_outputs["output"],
-                         std::vector<float>({3, 3, 3, 3}));
+  VerifyFloatDataIsEqual(named_outputs["output"], {3, 3, 3, 3});
 }
 
 // Test building and computing a graph whose add and mul operators only have
@@ -3211,8 +3198,7 @@
       BuildAndCompute<float>(context(), std::move(remote),
                              builder.TakeGraphInfo(),
                              /*named_inputs=*/{});
-  VerifyFloatDataIsEqual(named_outputs["output"],
-                         std::vector<float>({9, 9, 9, 9}));
+  VerifyFloatDataIsEqual(named_outputs["output"], {9, 9, 9, 9});
 }
 
 struct Pool2dAttributes {
@@ -3270,8 +3256,7 @@
   base::flat_map<std::string, std::vector<float>> named_outputs =
       BuildAndCompute(context(), std::move(remote), builder.TakeGraphInfo(),
                       std::move(named_inputs));
-  VerifyFloatDataIsEqual(named_outputs["output"],
-                         std::vector<float>({2, 2, 2, 2}));
+  VerifyFloatDataIsEqual(named_outputs["output"], {2, 2, 2, 2});
 }
 
 // Test building a graph in the following topology.
@@ -3321,8 +3306,7 @@
   base::flat_map<std::string, std::vector<float>> named_outputs =
       BuildAndCompute(context(), std::move(remote), builder.TakeGraphInfo(),
                       std::move(named_inputs));
-  VerifyFloatDataIsEqual(named_outputs["output"],
-                         std::vector<float>({2, 2, 2, 2}));
+  VerifyFloatDataIsEqual(named_outputs["output"], {2, 2, 2, 2});
 }
 
 // Test building a graph in the following topology.
@@ -3373,8 +3357,7 @@
   base::flat_map<std::string, std::vector<float>> named_outputs =
       BuildAndCompute(context(), std::move(remote), builder.TakeGraphInfo(),
                       std::move(named_inputs));
-  VerifyFloatDataIsEqual(named_outputs["output"],
-                         std::vector<float>({2, 2, 2, 2}));
+  VerifyFloatDataIsEqual(named_outputs["output"], {2, 2, 2, 2});
 }
 
 // Test building and computing a graph with float 16 data type in the
@@ -3609,10 +3592,9 @@
   //  [[[ -4  16]]
   //   [[ -8  20]]
   //   [[-12  24]]]] with shape (4, 3, 1, 2)
-  VerifyFloatDataIsEqual(
-      named_outputs["output"],
-      std::vector<float>({-1, 13, -5, 17, -9,  21, -2, 14, -6, 18, -10, 22,
-                          -3, 15, -7, 19, -11, 23, -4, 16, -8, 20, -12, 24}));
+  VerifyFloatDataIsEqual(named_outputs["output"],
+                         {-1, 13, -5, 17, -9,  21, -2, 14, -6, 18, -10, 22,
+                          -3, 15, -7, 19, -11, 23, -4, 16, -8, 20, -12, 24});
 }
 
 // Test building and computing a graph in the following topology.
@@ -3663,10 +3645,9 @@
   //  [[[ 0  16]]
   //   [[ 0  20]]
   //   [[ 0  24]]]] wit shape (4, 3, 1, 2)
-  VerifyFloatDataIsEqual(
-      named_outputs["output"],
-      std::vector<float>({0, 13, 0, 17, 0, 21, 0, 14, 0, 18, 0, 22,
-                          0, 15, 0, 19, 0, 23, 0, 16, 0, 20, 0, 24}));
+  VerifyFloatDataIsEqual(named_outputs["output"],
+                         {0, 13, 0, 17, 0, 21, 0, 14, 0, 18, 0, 22,
+                          0, 15, 0, 19, 0, 23, 0, 16, 0, 20, 0, 24});
 }
 
 // Test building and computing a graph in the following topology.
@@ -3721,10 +3702,9 @@
 
   // [[ -1  -5  -9  -2  -6 -10  -3  -7 -11  -4  -8 -12]
   //  [ 13  17  21  14  18  22  15  19  23  16  20  24]] wit shape (2, 12)
-  VerifyFloatDataIsEqual(
-      named_outputs["output"],
-      std::vector<float>({-1, -5, -9, -2, -6, -10, -3, -7, -11, -4, -8, -12,
-                          13, 17, 21, 14, 18, 22,  15, 19, 23,  16, 20, 24}));
+  VerifyFloatDataIsEqual(named_outputs["output"],
+                         {-1, -5, -9, -2, -6, -10, -3, -7, -11, -4, -8, -12,
+                          13, 17, 21, 14, 18, 22,  15, 19, 23,  16, 20, 24});
 }
 
 // Test building and computing a graph in the following topology.
@@ -3769,16 +3749,14 @@
   // [[ 0  0  0  0]
   //  [ 0  0  1  2]
   //  [ 3  6 10 20]] with shape (3, 4)
-  VerifyFloatDataIsEqual(
-      named_outputs["output1"],
-      std::vector<float>({0, 0, 0, 0, 0, 0, 1, 2, 3, 6, 10, 20}));
+  VerifyFloatDataIsEqual(named_outputs["output1"],
+                         {0, 0, 0, 0, 0, 0, 1, 2, 3, 6, 10, 20});
   // [[[[ 0  0  0]
   //    [ 1  3 10]]
   //   [[ 0  0  0]
   //    [ 2  6 20]]]] with shape (1, 2, 2, 3)
-  VerifyFloatDataIsEqual(
-      named_outputs["output2"],
-      std::vector<float>({0, 0, 0, 1, 3, 10, 0, 0, 0, 2, 6, 20}));
+  VerifyFloatDataIsEqual(named_outputs["output2"],
+                         {0, 0, 0, 1, 3, 10, 0, 0, 0, 2, 6, 20});
 }
 
 // Test building and computing a graph which can't be automatically fused
@@ -3802,7 +3780,8 @@
         builder.BuildInput("input", {1, 1, 5, 5}, OperandDataType::kFloat32);
     uint64_t filter_operand_id =
         builder.BuildConstant({1, 1, 3, 3}, OperandDataType::kFloat32,
-                              base::as_byte_span(std::vector<float>(9, 1)));
+                              base::as_byte_span({1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
+                                                  1.0f, 1.0f, 1.0f, 1.0f}));
     uint64_t conv2d_output_operand_id = builder.BuildIntermediateOperand(
         {1, 1, 5, 5}, OperandDataType::kFloat32);
 
@@ -3835,9 +3814,8 @@
     base::flat_map<std::string, base::span<const float>> named_inputs;
 
     named_inputs.insert(
-        {"input", std::array<float, 25>{0,  1,  2,  3,  4,  5,  6,  7,  8,
-                                        9,  10, 11, 12, 13, 14, 15, 16, 17,
-                                        18, 19, 20, 21, 22, 23, 24}});
+        {"input", {0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12,
+                   13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}});
     base::flat_map<std::string, std::vector<float>> named_outputs =
         BuildAndCompute(context(), std::move(remote), builder.TakeGraphInfo(),
                         std::move(named_inputs));
@@ -3865,7 +3843,8 @@
         builder.BuildInput("input", {1, 1, 5, 5}, OperandDataType::kFloat32);
     uint64_t filter_operand_id =
         builder.BuildConstant({1, 1, 3, 3}, OperandDataType::kFloat32,
-                              base::as_byte_span(std::vector<float>(9, 1)));
+                              base::as_byte_span({1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
+                                                  1.0f, 1.0f, 1.0f, 1.0f}));
     uint64_t conv2d_output_operand_id = builder.BuildIntermediateOperand(
         {1, 1, 5, 5}, OperandDataType::kFloat32);
 
@@ -3898,22 +3877,19 @@
     base::flat_map<std::string, base::span<const float>> named_inputs;
 
     named_inputs.insert(
-        {"input", std::array<float, 25>{0,  1,  2,  3,  4,  5,  6,  7,  8,
-                                        9,  10, 11, 12, 13, 14, 15, 16, 17,
-                                        18, 19, 20, 21, 22, 23, 24}});
+        {"input", {0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12,
+                   13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}});
     base::flat_map<std::string, std::vector<float>> named_outputs =
         BuildAndCompute(context(), std::move(remote), builder.TakeGraphInfo(),
                         std::move(named_inputs));
 
     VerifyFloatDataIsEqual(
         named_outputs["output1"],
-        std::array<float, 25>{-88, -79, -73, -67, -76, -67, -46, -37, -28,
-                              -49, -37, -1,  8,   17,  -19, -7,  44,  53,
-                              62,  11,  -28, 11,  17,  23,  -16});
-    VerifyFloatDataIsEqual(
-        named_outputs["output2"],
-        std::array<float, 25>{0,  0, 0, 0,  0,  0,  0,  0, 0,  0,  0,  0, 8,
-                              17, 0, 0, 44, 53, 62, 11, 0, 11, 17, 23, 0});
+        {-88, -79, -73, -67, -76, -67, -46, -37, -28, -49, -37, -1, 8,
+         17,  -19, -7,  44,  53,  62,  11,  -28, 11,  17,  23,  -16});
+    VerifyFloatDataIsEqual(named_outputs["output2"],
+                           {0,  0, 0, 0,  0,  0,  0,  0, 0,  0,  0,  0, 8,
+                            17, 0, 0, 44, 53, 62, 11, 0, 11, 17, 23, 0});
   }
   //     [input]
   //        |
@@ -3932,7 +3908,8 @@
         builder.BuildInput("input", {1, 1, 5, 5}, OperandDataType::kFloat32);
     uint64_t filter_operand_id =
         builder.BuildConstant({1, 1, 3, 3}, OperandDataType::kFloat32,
-                              base::as_byte_span(std::vector<float>(9, 1)));
+                              base::as_byte_span({1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
+                                                  1.0f, 1.0f, 1.0f, 1.0f}));
     uint64_t conv2d_output_operand_id = builder.BuildIntermediateOperand(
         {1, 1, 5, 5}, OperandDataType::kFloat32);
 
@@ -3962,22 +3939,19 @@
     base::flat_map<std::string, base::span<const float>> named_inputs;
 
     named_inputs.insert(
-        {"input", std::array<float, 25>{0,  1,  2,  3,  4,  5,  6,  7,  8,
-                                        9,  10, 11, 12, 13, 14, 15, 16, 17,
-                                        18, 19, 20, 21, 22, 23, 24}});
+        {"input", {0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12,
+                   13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}});
     base::flat_map<std::string, std::vector<float>> named_outputs =
         BuildAndCompute(context(), std::move(remote), builder.TakeGraphInfo(),
                         std::move(named_inputs));
 
-    VerifyFloatDataIsEqual(
-        named_outputs["output1"],
-        std::array<float, 25>{0,  0, 0, 0,  0,  0,  0,  0, 0,  0,  0,  0, 8,
-                              17, 0, 0, 44, 53, 62, 11, 0, 11, 17, 23, 0});
+    VerifyFloatDataIsEqual(named_outputs["output1"],
+                           {0,  0, 0, 0,  0,  0,  0,  0, 0,  0,  0,  0, 8,
+                            17, 0, 0, 44, 53, 62, 11, 0, 11, 17, 23, 0});
     VerifyFloatDataIsEqual(
         named_outputs["output2"],
-        std::array<float, 25>{-88, -79, -73, -67, -76, -67, -46, -37, -28,
-                              -49, -37, -1,  8,   17,  -19, -7,  44,  53,
-                              62,  11,  -28, 11,  17,  23,  -16});
+        {-88, -79, -73, -67, -76, -67, -46, -37, -28, -49, -37, -1, 8,
+         17,  -19, -7,  44,  53,  62,  11,  -28, 11,  17,  23,  -16});
   }
 }
 
diff --git a/testing/buildbot/filters/android.emulator_15.chrome_public_test_apk.filter b/testing/buildbot/filters/android.emulator_15.chrome_public_test_apk.filter
index fd5d7667..b4252689 100644
--- a/testing/buildbot/filters/android.emulator_15.chrome_public_test_apk.filter
+++ b/testing/buildbot/filters/android.emulator_15.chrome_public_test_apk.filter
@@ -31,3 +31,8 @@
 
 # crbug.com/356175432
 -org.chromium.chrome.browser.dom_distiller.ReaderModeTest.testReaderModeInTab
+
+# crbug.com/383144566
+-org.chromium.chrome.browser.contextualsearch.ContextualSearchManagerTest.testQuickActionCaptionAndImage
+-org.chromium.chrome.browser.contextualsearch.ContextualSearchManagerTest.testPromotesToTab
+-org.chromium.chrome.browser.contextualsearch.ContextualSearchManagerTest.testAcceptedPrivacy
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 9918dd5..b894ba1 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -1978,25 +1978,6 @@
             ]
         }
     ],
-    "AutofillForUnclassifiedFieldsAvailable": [
-        {
-            "platforms": [
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled_AutofillForUnclassifiedFieldsAndManualFallbackIPH",
-                    "enable_features": [
-                        "AutofillEnableManualFallbackIPH",
-                        "AutofillForUnclassifiedFieldsAvailable"
-                    ]
-                }
-            ]
-        }
-    ],
     "AutofillGivePrecedenceToEmailOverUsername": [
         {
             "platforms": [
@@ -10986,27 +10967,11 @@
                 {
                     "name": "Enabled",
                     "params": {
-                        "AnswersInOmniboxScoped": "true",
-                        "ContentVisibilityThreshold": "0.0",
-                        "EnableSidePanel": "true",
-                        "OmniboxScoped": "true",
-                        "SearchPassageMinimumWordCount": "5",
-                        "SearchQueryMinimumWordCount": "2",
-                        "SendQualityLog": "true",
-                        "SendQualityLogV2": "true",
-                        "TrimAfterHostInResults": "true",
-                        "UseMlAnswerer": "true",
-                        "WordMatchLimit": "5",
-                        "WordMatchMaxTermCount": "10",
-                        "WordMatchMinEmbeddingScore": "0.7",
-                        "WordMatchMinTermLength": "0",
-                        "WordMatchRequiredTermRatio": "1.0",
-                        "WordMatchScoreBoostFactor": "0.2",
-                        "WordMatchSmoothingFactor": "0",
                         "allow_unsigned_user": "true",
                         "enable_feature_when_main_toggle_on": "false"
                     },
                     "enable_features": [
+                        "FeatureManagementHistoryEmbedding",
                         "HistoryEmbeddings",
                         "HistoryEmbeddingsAnswers",
                         "HistorySearchSettingsVisibility"
@@ -21412,13 +21377,7 @@
             ],
             "experiments": [
                 {
-                    "//0": "This experiment group might not be included in the",
-                    "//1": " same finch config, but it's important for now to ",
-                    "//2": "have tests ran with all relevant flags and params ",
-                    "//3": " enabled.",
-                    "//4": "Note that SensitiveContentWhileSwitchingTabs ",
-                    "//5": "depends on SensitiveContent being enabed, too.",
-                    "name": "Enabled_WithPwmHeuristicsAndTabSwitching",
+                    "name": "Enabled_WithTabSwitchingAndPwmHeuristics",
                     "params": {
                         "sensitive_content_use_pwm_heuristics": "true"
                     },
@@ -21428,12 +21387,25 @@
                     ]
                 },
                 {
+                    "name": "Enabled_WithTabSwitching",
+                    "params": {
+                        "sensitive_content_use_pwm_heuristics": "false"
+                    },
+                    "enable_features": [
+                        "SensitiveContent",
+                        "SensitiveContentWhileSwitchingTabs"
+                    ]
+                },
+                {
                     "name": "Enabled_WithPwmHeuristics",
                     "params": {
                         "sensitive_content_use_pwm_heuristics": "true"
                     },
                     "enable_features": [
                         "SensitiveContent"
+                    ],
+                    "disable_features": [
+                        "SensitiveContentWhileSwitchingTabs"
                     ]
                 },
                 {
@@ -21443,6 +21415,9 @@
                     },
                     "enable_features": [
                         "SensitiveContent"
+                    ],
+                    "disable_features": [
+                        "SensitiveContentWhileSwitchingTabs"
                     ]
                 }
             ]
diff --git a/third_party/android_build_tools/gradle_wrapper/README.chromium b/third_party/android_build_tools/gradle_wrapper/README.chromium
index 17109fa..37ae4f9 100644
--- a/third_party/android_build_tools/gradle_wrapper/README.chromium
+++ b/third_party/android_build_tools/gradle_wrapper/README.chromium
@@ -1,7 +1,7 @@
 Name: Gradle Wrapper
 Short Name: gradlew
 URL: https://gradle.org/
-Version: 8.5
+Version: 8.10
 License: Apache Version 2.0
 Security Critical: no
 Shipped: no
@@ -22,10 +22,18 @@
 
 To upgrade:
 https://docs.gradle.org/current/userguide/gradle_wrapper.html#sec:upgrading_wrapper
-- Run: `./gradlew --version` to check the current version.
-- Run: `./gradlew wrapper --gradle-version <version>` to update to a newer version.
-  - You can find the latest version here: https://gradle.org/releases/
-- Run: `./gradlew --version` again to actually download the new version.
+https://docs.gradle.org/current/userguide/compatibility.html
+
+./gradlew init
+./gradlew --version
+./gradlew wrapper --gradle-version <version>
+./gradlew --version
+git clean -df
+
+Test it via:
+build/android/gradle/generate_gradle.py --output-directory out/Debug
+* And by running "3pp-linux-amd64-packager" trybot on the change
+
 
 Local Modifications:
 No modifications.
diff --git a/third_party/android_build_tools/gradle_wrapper/gradle/wrapper/gradle-wrapper.jar b/third_party/android_build_tools/gradle_wrapper/gradle/wrapper/gradle-wrapper.jar
index 41d9927..d64cd49 100644
--- a/third_party/android_build_tools/gradle_wrapper/gradle/wrapper/gradle-wrapper.jar
+++ b/third_party/android_build_tools/gradle_wrapper/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/third_party/android_build_tools/gradle_wrapper/gradle/wrapper/gradle-wrapper.properties b/third_party/android_build_tools/gradle_wrapper/gradle/wrapper/gradle-wrapper.properties
index a5952066..9355b41 100644
--- a/third_party/android_build_tools/gradle_wrapper/gradle/wrapper/gradle-wrapper.properties
+++ b/third_party/android_build_tools/gradle_wrapper/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,7 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/third_party/android_build_tools/gradle_wrapper/gradlew b/third_party/android_build_tools/gradle_wrapper/gradlew
index 1b6c787..1aa94a4 100755
--- a/third_party/android_build_tools/gradle_wrapper/gradlew
+++ b/third_party/android_build_tools/gradle_wrapper/gradlew
@@ -55,7 +55,7 @@
 #       Darwin, MinGW, and NonStop.
 #
 #   (3) This script is generated from the Groovy template
-#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+#       https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
 #       within the Gradle project.
 #
 #       You can find Gradle at https://github.com/gradle/gradle/.
@@ -80,13 +80,11 @@
     esac
 done
 
-APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
-
-APP_NAME="Gradle"
+# This is normally unused
+# shellcheck disable=SC2034
 APP_BASE_NAME=${0##*/}
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
 
 # Use the maximum available, or set MAX_FD != -1 to use that value.
 MAX_FD=maximum
@@ -133,22 +131,29 @@
     fi
 else
     JAVACMD=java
-    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+    if ! command -v java >/dev/null 2>&1
+    then
+        die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
 
 Please set the JAVA_HOME variable in your environment to match the
 location of your Java installation."
+    fi
 fi
 
 # Increase the maximum file descriptors if we can.
 if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
     case $MAX_FD in #(
       max*)
+        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+        # shellcheck disable=SC2039,SC3045
         MAX_FD=$( ulimit -H -n ) ||
             warn "Could not query maximum file descriptor limit"
     esac
     case $MAX_FD in  #(
       '' | soft) :;; #(
       *)
+        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+        # shellcheck disable=SC2039,SC3045
         ulimit -n "$MAX_FD" ||
             warn "Could not set maximum file descriptor limit to $MAX_FD"
     esac
@@ -193,11 +198,15 @@
     done
 fi
 
-# Collect all arguments for the java command;
-#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
-#     shell script including quotes and variable substitutions, so put them in
-#     double quotes to make sure that they get re-expanded; and
-#   * put everything else in single quotes, so that it's not re-expanded.
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+#     and any embedded shellness will be escaped.
+#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+#     treated as '${Hostname}' itself on the command line.
 
 set -- \
         "-Dorg.gradle.appname=$APP_BASE_NAME" \
@@ -205,6 +214,12 @@
         org.gradle.wrapper.GradleWrapperMain \
         "$@"
 
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+    die "xargs is not available"
+fi
+
 # Use "xargs" to parse quoted args.
 #
 # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
diff --git a/third_party/android_build_tools/gradle_wrapper/gradlew.bat b/third_party/android_build_tools/gradle_wrapper/gradlew.bat
index ac1b06f..6689b85 100755
--- a/third_party/android_build_tools/gradle_wrapper/gradlew.bat
+++ b/third_party/android_build_tools/gradle_wrapper/gradlew.bat
@@ -14,7 +14,7 @@
 @rem limitations under the License.

 @rem

 

-@if "%DEBUG%" == "" @echo off

+@if "%DEBUG%"=="" @echo off

 @rem ##########################################################################

 @rem

 @rem  Gradle startup script for Windows

@@ -25,7 +25,8 @@
 if "%OS%"=="Windows_NT" setlocal

 

 set DIRNAME=%~dp0

-if "%DIRNAME%" == "" set DIRNAME=.

+if "%DIRNAME%"=="" set DIRNAME=.

+@rem This is normally unused

 set APP_BASE_NAME=%~n0

 set APP_HOME=%DIRNAME%

 

@@ -40,7 +41,7 @@
 

 set JAVA_EXE=java.exe

 %JAVA_EXE% -version >NUL 2>&1

-if "%ERRORLEVEL%" == "0" goto execute

+if %ERRORLEVEL% equ 0 goto execute

 

 echo.

 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

@@ -75,13 +76,15 @@
 

 :end

 @rem End local scope for the variables with windows NT shell

-if "%ERRORLEVEL%"=="0" goto mainEnd

+if %ERRORLEVEL% equ 0 goto mainEnd

 

 :fail

 rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of

 rem the _cmd.exe /c_ return code!

-if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1

-exit /b 1

+set EXIT_CODE=%ERRORLEVEL%

+if %EXIT_CODE% equ 0 set EXIT_CODE=1

+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%

+exit /b %EXIT_CODE%

 

 :mainEnd

 if "%OS%"=="Windows_NT" endlocal

diff --git a/third_party/angle b/third_party/angle
index 6b68373..95756ae 160000
--- a/third_party/angle
+++ b/third_party/angle
@@ -1 +1 @@
-Subproject commit 6b6837324b784c4c68408606af2cdb6930166186
+Subproject commit 95756ae2acbe88a57cc33cff02eeb5e7eb127876
diff --git a/third_party/blink/public/mojom/content_extraction/ai_page_content.mojom b/third_party/blink/public/mojom/content_extraction/ai_page_content.mojom
index 4834ad41..991d9062 100644
--- a/third_party/blink/public/mojom/content_extraction/ai_page_content.mojom
+++ b/third_party/blink/public/mojom/content_extraction/ai_page_content.mojom
@@ -30,6 +30,8 @@
   kUnorderedList,
   kForm,
   kFigure,
+  kTable,
+  kTableCell,
 };
 
 struct AIPageContentGeometry {
@@ -79,6 +81,19 @@
   bool likely_ad_frame;
 };
 
+struct AIPageContentTableRow {
+  array<AIPageContentNode> cells;
+};
+
+struct AIPageContentTableData {
+  // The name of the table, coming from the caption.
+  string? table_name;
+
+  array<AIPageContentTableRow> header_rows;
+  array<AIPageContentTableRow> body_rows;
+  array<AIPageContentTableRow> footer_rows;
+};
+
 struct AIPageContentAttributes {
   // The IDs of the DOM nodes whose content is represented by this ContentNode.
   array<int32> dom_node_ids;
@@ -102,6 +117,9 @@
   AIPageContentIframeData? iframe_data;
 
   // TODO(crbug.com/380493777): Add FormData if attribute_type is FORM.
+
+  // Only set if attribute_type is TABLE.
+  AIPageContentTableData? table_data;
 };
 
 // A semantic chunk of information on a page. It can represent text, structured
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 8537ad0..9ff7fc0 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
@@ -1292,7 +1292,7 @@
   kFetchResponseConstructionWithStream = 1826,
   kLocationOrigin = 1827,
   kCanvas2DFilter = 1830,
-  kCanvas2DImageSmoothingQuality = 1831,
+  kOBSOLETE_Canvas2DImageSmoothingQuality = 1831,
   kCanvasToBlob = 1832,
   kCanvasToDataURL = 1833,
   kOffscreenCanvasConvertToBlob = 1834,
@@ -4599,6 +4599,7 @@
   kVerticalFormControls = 5213,
   kV8AuthenticatorAttestationResponse_GetPublicKey_Method = 5214,
   kCloseWatcherScriptConstructor = 5215,
+  kCanvas2DImageSmoothingQuality2 = 5216,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots. Also don't add extra
diff --git a/third_party/blink/public/mojom/webauthn/authenticator.mojom b/third_party/blink/public/mojom/webauthn/authenticator.mojom
index 0a196436..41f5264 100644
--- a/third_party/blink/public/mojom/webauthn/authenticator.mojom
+++ b/third_party/blink/public/mojom/webauthn/authenticator.mojom
@@ -330,6 +330,7 @@
   PaymentCredentialInstrument instrument;
   string? payee_name;
   url.mojom.Origin? payee_origin;
+  array<uint8>? browser_bound_public_key;
 };
 
 // TODO(https://crbug.com/1239249): Move to payment_request.mojom after this
diff --git a/third_party/blink/renderer/controller/BUILD.gn b/third_party/blink/renderer/controller/BUILD.gn
index 555c721..6ff75a6 100644
--- a/third_party/blink/renderer/controller/BUILD.gn
+++ b/third_party/blink/renderer/controller/BUILD.gn
@@ -193,8 +193,6 @@
       "//build/config/fuchsia/test/mark_vmo_executable.shard.test-cml",
     ]
   }
-
-  fuzztests = [ "BlinkAttributeFuzzTestFixture.NoElementAttributeCrashes" ]
 }
 
 test("blink_perf_tests") {
@@ -304,7 +302,6 @@
     "//third_party/blink/renderer/platform:test_support",
     "//third_party/blink/renderer/platform:unit_tests",
     "//third_party/blink/renderer/platform/wtf",
-    "//third_party/fuzztest",
     "//third_party/libwebp",
     "//third_party/zlib",
     "//url",
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 407169fd..679005c 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1516,7 +1516,6 @@
     "//third_party/blink/renderer/core:unit_test_support",
     "//third_party/blink/renderer/core/sanitizer:unit_test_support",
     "//third_party/blink/renderer/platform:test_support",
-    "//third_party/fuzztest",
     "//ui/accessibility:ax_base",
     "//ui/base/cursor",
     "//ui/base/cursor/mojom:cursor_type_blink",
diff --git a/third_party/blink/renderer/core/css/css_gap_decoration_property_enums.h b/third_party/blink/renderer/core/css/css_gap_decoration_property_enums.h
index 21a5e66..b8ff9d377 100644
--- a/third_party/blink/renderer/core/css/css_gap_decoration_property_enums.h
+++ b/third_party/blink/renderer/core/css/css_gap_decoration_property_enums.h
@@ -10,7 +10,7 @@
 enum class CSSGapDecorationPropertyType {
   kColor,
   kWidth,
-  // TODO(crbug.com/357648037): Add kStyle when implemented.
+  kStyle,
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5
index 8a30f42..1acb9367 100644
--- a/third_party/blink/renderer/core/css/css_properties.json5
+++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -6255,7 +6255,7 @@
     },
     {
       name: "column-rule-style",
-      property_methods: ["CSSValueFromComputedStyleInternal"],
+      property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
       field_group: "*",
       field_template: "external",
       include_paths: ["third_party/blink/renderer/core/style/gap_data_list.h"],
diff --git a/third_party/blink/renderer/core/css/css_scope_rule.cc b/third_party/blink/renderer/core/css/css_scope_rule.cc
index 68047813..4276bd1 100644
--- a/third_party/blink/renderer/core/css/css_scope_rule.cc
+++ b/third_party/blink/renderer/core/css/css_scope_rule.cc
@@ -7,6 +7,7 @@
 #include "third_party/blink/renderer/core/css/css_markup.h"
 #include "third_party/blink/renderer/core/css/css_style_rule.h"
 #include "third_party/blink/renderer/core/css/css_style_sheet.h"
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
 #include "third_party/blink/renderer/core/css/style_rule.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 
@@ -86,12 +87,34 @@
     }
   }
 
+  // Replace the inner StyleRuleScope with a new rule using the specified
+  // prelude.
+
   CSSStyleSheet* style_sheet = parentStyleSheet();
   StyleSheetContents* contents =
       style_sheet ? style_sheet->Contents() : nullptr;
-
-  GetStyleRuleScope().SetPreludeText(execution_context, value, nesting_type,
-                                     parent_rule_for_nesting, contents);
+  auto* parser_context =
+      MakeGarbageCollected<CSSParserContext>(*execution_context);
+  CSSParserTokenStream stream(value);
+  StyleScope* new_style_scope = StyleScope::Parse(
+      stream, parser_context, nesting_type, parent_rule_for_nesting, contents);
+  if (!new_style_scope || !stream.AtEnd()) {
+    // Quietly no-op if the provided prelude doesn't parse (similar to the
+    // behavior of CSSStyleRule::setSelectorText).
+    return;
+  }
+  // Any '&' selectors in child rules must now point to new_style_scope's
+  // internally-held style rule.
+  HeapVector<Member<StyleRuleBase>> new_child_rules;
+  new_child_rules.ReserveInitialCapacity(
+      GetStyleRuleScope().ChildRules().size());
+  for (StyleRuleBase* child_rule : GetStyleRuleScope().ChildRules()) {
+    // TODO(crbug.com/363019839): Re-nest instead.
+    new_child_rules.push_back(child_rule->Copy());
+    new_child_rules.back()->Reparent(new_style_scope->RuleForNesting());
+  }
+  group_rule_ = MakeGarbageCollected<StyleRuleScope>(
+      *new_style_scope, std::move(new_child_rules));
 }
 
 StyleRuleScope& CSSScopeRule::GetStyleRuleScope() {
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
index 9dee5ae..5a9957a 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
+++ b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
@@ -1168,6 +1168,10 @@
                            color_id);
 }
 
+bool CSSParserFastPaths::IsBorderStyleValue(CSSValueID value_id) {
+  return value_id >= CSSValueID::kNone && value_id <= CSSValueID::kDouble;
+}
+
 bool CSSParserFastPaths::IsValidKeywordPropertyAndValue(
     CSSPropertyID property_id,
     CSSValueID value_id,
@@ -1204,7 +1208,7 @@
     case CSSPropertyID::kBorderInlineEndStyle:
     case CSSPropertyID::kBorderInlineStartStyle:
     case CSSPropertyID::kColumnRuleStyle:
-      return value_id >= CSSValueID::kNone && value_id <= CSSValueID::kDouble;
+      return IsBorderStyleValue(value_id);
     case CSSPropertyID::kBoxSizing:
       return value_id == CSSValueID::kBorderBox ||
              value_id == CSSValueID::kContentBox;
@@ -1804,7 +1808,6 @@
     CSSPropertyID::kWebkitBoxOrient,
     CSSPropertyID::kWebkitBoxPack,
     CSSPropertyID::kColumnFill,
-    CSSPropertyID::kColumnRuleStyle,
     CSSPropertyID::kFlexDirection,
     CSSPropertyID::kFlexWrap,
     CSSPropertyID::kFontKerning,
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h
index 0c893612..1ffeff0 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h
+++ b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h
@@ -44,6 +44,8 @@
     return handled_by_keyword_fast_paths_properties_.Has(property_id);
   }
 
+  static bool IsBorderStyleValue(CSSValueID);
+
   static bool IsValidKeywordPropertyAndValue(CSSPropertyID,
                                              CSSValueID,
                                              CSSParserMode);
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
index 0673369..642edfc 100644
--- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
+++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -4988,7 +4988,12 @@
     case CSSGapDecorationPropertyType::kWidth:
       return ConsumeLineWidth(stream, context,
                               css_parsing_utils::UnitlessQuirk::kForbid);
-      // TODO(crbug.com/357648037): Add kStyle when implemented.
+    case CSSGapDecorationPropertyType::kStyle: {
+      if (CSSParserFastPaths::IsBorderStyleValue(stream.Peek().Id())) {
+        return ConsumeIdent(stream);
+      }
+      return nullptr;
+    }
   }
 }
 
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
index 450d5b6..a3c12447 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -2291,6 +2291,14 @@
       style.ColumnRuleColor(), style, value_phase);
 }
 
+const CSSValue* ColumnRuleStyle::ParseSingleValue(
+    CSSParserTokenStream& stream,
+    const CSSParserContext& context,
+    const CSSParserLocalContext&) const {
+  return css_parsing_utils::ConsumeGapDecorationPropertyList(
+      stream, context, CSSGapDecorationPropertyType::kStyle);
+}
+
 const CSSValue* ColumnRuleStyle::CSSValueFromComputedStyleInternal(
     const ComputedStyle& style,
     const LayoutObject*,
diff --git a/third_party/blink/renderer/core/css/style_rule.cc b/third_party/blink/renderer/core/css/style_rule.cc
index 2c5ae08..6ba507f0 100644
--- a/third_party/blink/renderer/core/css/style_rule.cc
+++ b/third_party/blink/renderer/core/css/style_rule.cc
@@ -676,25 +676,6 @@
   StyleRuleGroup::TraceAfterDispatch(visitor);
 }
 
-void StyleRuleScope::SetPreludeText(const ExecutionContext* execution_context,
-                                    String value,
-                                    CSSNestingType nesting_type,
-                                    StyleRule* parent_rule_for_nesting,
-                                    StyleSheetContents* style_sheet) {
-  auto* parser_context =
-      MakeGarbageCollected<CSSParserContext>(*execution_context);
-  CSSParserTokenStream stream(value);
-
-  style_scope_ = StyleScope::Parse(stream, parser_context, nesting_type,
-                                   parent_rule_for_nesting, style_sheet);
-  if (!stream.AtEnd()) {
-    style_scope_ = nullptr;
-  }
-
-  // Reparent rules within the @scope's body.
-  Reparent(style_scope_->RuleForNesting());
-}
-
 StyleRuleGroup::StyleRuleGroup(RuleType type,
                                HeapVector<Member<StyleRuleBase>> rules)
     : StyleRuleBase(type), child_rules_(std::move(rules)) {}
diff --git a/third_party/blink/renderer/core/css/style_rule.h b/third_party/blink/renderer/core/css/style_rule.h
index 29c6d3f9..6fda4a9 100644
--- a/third_party/blink/renderer/core/css/style_rule.h
+++ b/third_party/blink/renderer/core/css/style_rule.h
@@ -51,7 +51,6 @@
 class CSSRule;
 class CSSStyleSheet;
 class ExecutionContext;
-class StyleSheetContents;
 
 class CORE_EXPORT StyleRuleBase : public GarbageCollected<StyleRuleBase> {
  public:
@@ -412,13 +411,6 @@
   void TraceAfterDispatch(blink::Visitor*) const;
 
   const StyleScope& GetStyleScope() const { return *style_scope_; }
-
-  void SetPreludeText(const ExecutionContext*,
-                      String,
-                      CSSNestingType,
-                      StyleRule* parent_rule_for_nesting,
-                      StyleSheetContents* style_sheet);
-
  private:
   Member<const StyleScope> style_scope_;
 };
diff --git a/third_party/blink/renderer/core/css/style_rule_test.cc b/third_party/blink/renderer/core/css/style_rule_test.cc
index e319701..982f520 100644
--- a/third_party/blink/renderer/core/css/style_rule_test.cc
+++ b/third_party/blink/renderer/core/css/style_rule_test.cc
@@ -93,60 +93,63 @@
 }
 
 TEST_F(StyleRuleTest, SetPreludeTextReparentsStyleRules) {
-  auto* scope_rule = DynamicTo<StyleRuleScope>(
+  CSSStyleSheet* sheet = css_test_helpers::CreateStyleSheet(GetDocument());
+  auto* scope_rule = DynamicTo<CSSScopeRule>(
       css_test_helpers::ParseRule(GetDocument(), R"CSS(
       @scope (.a) to (.b &) {
         .c & { }
       }
-    )CSS"));
+    )CSS")
+          ->CreateCSSOMWrapper(/*position_hint=*/0, sheet));
 
   ASSERT_TRUE(scope_rule);
-  ASSERT_EQ(1u, scope_rule->ChildRules().size());
-  StyleRule& child_rule = To<StyleRule>(*scope_rule->ChildRules()[0]);
+  ASSERT_EQ(1u, scope_rule->GetStyleRuleScope().ChildRules().size());
+  StyleRule& child_rule_before =
+      To<StyleRule>(*scope_rule->GetStyleRuleScope().ChildRules()[0]);
 
-  const StyleScope& scope_before = scope_rule->GetStyleScope();
+  const StyleScope& scope_before =
+      scope_rule->GetStyleRuleScope().GetStyleScope();
   StyleRule* rule_before = scope_before.RuleForNesting();
   ASSERT_TRUE(rule_before);
   EXPECT_EQ(".a", rule_before->SelectorsText());
 
   EXPECT_EQ(rule_before, FindParentSelector(scope_before.To())->ParentRule());
-  EXPECT_EQ(rule_before,
-            FindParentSelector(child_rule.FirstSelector())->ParentRule());
+  EXPECT_EQ(
+      rule_before,
+      FindParentSelector(child_rule_before.FirstSelector())->ParentRule());
 
-  // Note that CSSNestingType::kNone here refers to the nesting context outside
-  // of `scope_rule` (which in this case has no parent rule).
   scope_rule->SetPreludeText(GetDocument().GetExecutionContext(),
-                             "(.x) to (.b &)", CSSNestingType::kNone,
-                             /* parent_rule_for_nesting */ nullptr,
+                             "(.x) to (.b &)");
 
-                             /* style_sheet */ nullptr);
-
-  const StyleScope& scope_after = scope_rule->GetStyleScope();
+  DLOG(INFO) << "A";
+  const StyleScope& scope_after =
+      scope_rule->GetStyleRuleScope().GetStyleScope();
   StyleRule* rule_after = scope_after.RuleForNesting();
   ASSERT_TRUE(rule_after);
   EXPECT_EQ(".x", rule_after->SelectorsText());
+  StyleRule& child_rule_afer =
+      To<StyleRule>(*scope_rule->GetStyleRuleScope().ChildRules()[0]);
 
   // Verify that '&' (in '.b &') now points to `rule_after`.
   EXPECT_EQ(rule_after, FindParentSelector(scope_after.To())->ParentRule());
   // Verify that '&' (in '.c &') now points to `rule_after`.
   EXPECT_EQ(rule_after,
-            FindParentSelector(child_rule.FirstSelector())->ParentRule());
+            FindParentSelector(child_rule_afer.FirstSelector())->ParentRule());
 }
 
 TEST_F(StyleRuleTest, SetPreludeTextWithEscape) {
-  auto* scope_rule = DynamicTo<StyleRuleScope>(
+  CSSStyleSheet* sheet = css_test_helpers::CreateStyleSheet(GetDocument());
+  auto* scope_rule = DynamicTo<CSSScopeRule>(
       css_test_helpers::ParseRule(GetDocument(), R"CSS(
       @scope (.a) to (.b &) {
         .c & { }
       }
-    )CSS"));
+    )CSS")
+          ->CreateCSSOMWrapper(/*position_hint=*/0, sheet));
 
   // Don't crash.
   scope_rule->SetPreludeText(GetDocument().GetExecutionContext(),
-                             "(.x) to (.\\1F60A)", CSSNestingType::kNone,
-                             /* parent_rule_for_nesting */ nullptr,
-
-                             /* style_sheet */ nullptr);
+                             "(.x) to (.\\1F60A)");
 }
 
 TEST_F(StyleRuleTest, SetPreludeTextPreservesNestingContext) {
@@ -278,4 +281,32 @@
   EXPECT_FALSE(scope_rule->GetStyleRuleScope().GetStyleScope().IsImplicit());
 }
 
+TEST_F(StyleRuleTest, SetPreludeTextInvalid) {
+  CSSStyleSheet* sheet = css_test_helpers::CreateStyleSheet(GetDocument());
+  auto* css_scope_rule = DynamicTo<CSSScopeRule>(
+      css_test_helpers::ParseRule(GetDocument(), "@scope (.a) {}")
+          ->CreateCSSOMWrapper(/*position_hint=*/0, sheet));
+
+  StyleRuleScope* before_rule = &css_scope_rule->GetStyleRuleScope();
+  // Don't crash:
+  css_scope_rule->SetPreludeText(GetDocument().GetExecutionContext(),
+                                 "(.a) to !!!!");
+  StyleRuleScope* after_rule = &css_scope_rule->GetStyleRuleScope();
+  EXPECT_EQ(after_rule, before_rule);
+}
+
+TEST_F(StyleRuleTest, SetPreludeTextUnexpectedTrailingTokens) {
+  CSSStyleSheet* sheet = css_test_helpers::CreateStyleSheet(GetDocument());
+  auto* css_scope_rule = DynamicTo<CSSScopeRule>(
+      css_test_helpers::ParseRule(GetDocument(), "@scope (.a) {}")
+          ->CreateCSSOMWrapper(/*position_hint=*/0, sheet));
+
+  StyleRuleScope* before_rule = &css_scope_rule->GetStyleRuleScope();
+  // Don't crash:
+  css_scope_rule->SetPreludeText(GetDocument().GetExecutionContext(),
+                                 "(.a) to (.b) trailing");
+  StyleRuleScope* after_rule = &css_scope_rule->GetStyleRuleScope();
+  EXPECT_EQ(after_rule, before_rule);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index c62dbd6..4e103dc 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -3701,17 +3701,13 @@
     return false;
   }
 
-  // ::scroll-marker-group boxes are created outside their originating element's
-  // box and cannot be skipped if the originating element is a size container
-  // because the pseudo element and its box need to be created before layout.
-  if (!style.ScrollMarkerGroupNone()) {
-    return false;
-  }
-
-  // Same as above about ::scroll-marker-group goes about ::scroll-button().
-  // Note: using generic kPseudoIdScrollButton here, as style collection only
-  // sets generic pseudo style flag on originating element.
-  if (CanGeneratePseudoElement(kPseudoIdScrollButton)) {
+  // ::scroll-marker-group and ::scroll-button() boxes are created outside their
+  // originating element's box and cannot be skipped if the originating element
+  // is a size container because the pseudo element and its box need to be
+  // created before layout.
+  if (!style.ScrollMarkerGroupNone() ||
+      CanGeneratePseudoElement(kPseudoIdScrollButton) ||
+      HasSiblingBoxPseudoElements()) {
     return false;
   }
 
@@ -8719,6 +8715,22 @@
   return false;
 }
 
+bool Element::HasSiblingBoxPseudoElements() const {
+  const ElementRareDataVector* rare_data = GetElementRareData();
+  if (!rare_data) {
+    return false;
+  }
+  for (PseudoId pseudo_id :
+       {kPseudoIdScrollUpButton, kPseudoIdScrollDownButton,
+        kPseudoIdScrollLeftButton, kPseudoIdScrollRightButton,
+        kPseudoIdScrollMarkerGroupAfter, kPseudoIdScrollMarkerGroupBefore}) {
+    if (rare_data->GetPseudoElement(pseudo_id)) {
+      return true;
+    }
+  }
+  return false;
+}
+
 bool Element::MayTriggerVirtualKeyboard() const {
   return IsEditable(*this);
 }
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h
index 8add4c51..8c8b4c4 100644
--- a/third_party/blink/renderer/core/dom/element.h
+++ b/third_party/blink/renderer/core/dom/element.h
@@ -1655,6 +1655,12 @@
   template <typename Functor>
   bool PseudoElementStylesDependOnFunc(Functor& func) const;
 
+  // Returns true if this element has generate a pseudo element whose box is a
+  // sibling box of its originating element's box. In this case we cannot skip
+  // style recalc for size containers because that would break necessary layout
+  // containment by modifying the box tree outside the container during layout.
+  bool HasSiblingBoxPseudoElements() const;
+
   void ScrollLayoutBoxBy(const ScrollToOptions*);
   void ScrollLayoutBoxTo(const ScrollToOptions*);
   void ScrollFrameBy(const ScrollToOptions*);
diff --git a/third_party/blink/renderer/core/html/build.gni b/third_party/blink/renderer/core/html/build.gni
index d1115229..f559957 100644
--- a/third_party/blink/renderer/core/html/build.gni
+++ b/third_party/blink/renderer/core/html/build.gni
@@ -670,7 +670,6 @@
   "forms/text_control_element_test.cc",
   "forms/type_ahead_test.cc",
   "html_anchor_element_test.cc",
-  "html_attribute_fuzztest.cc",
   "html_dimension_test.cc",
   "html_element_test.cc",
   "html_embed_element_test.cc",
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc
index b23268a..f735bb6 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc
+++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc
@@ -57,11 +57,6 @@
   CHECK(host_);
 }
 
-SkColorInfo CanvasRenderingContext::CanvasRenderingContextSkColorInfo() const {
-  return SkColorInfo(kN32_SkColorType, kPremul_SkAlphaType,
-                     SkColorSpace::MakeSRGB());
-}
-
 void CanvasRenderingContext::Dispose() {
   RenderTaskEnded();
 
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h
index dee95f1..6a2d3fa3 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h
+++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h
@@ -178,7 +178,7 @@
     return nullptr;
   }
 
-  virtual SkColorInfo CanvasRenderingContextSkColorInfo() const;
+  virtual SkColorInfo CanvasRenderingContextSkColorInfo() const = 0;
 
   virtual scoped_refptr<StaticBitmapImage> GetImage(FlushReason) = 0;
   virtual bool IsComposited() const = 0;
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 4a49120a..36c8d9b7 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
@@ -1149,18 +1149,18 @@
         // size. Hence, we need to query the adjusted size of DrawingBuffer.
         gfx::Size adjusted_size = context_->DrawingBufferSize();
         if (!adjusted_size.IsEmpty()) {
-          SkColorInfo color_info =
-              GetRenderingContextSkColorInfo().makeAlphaType(
-                  kUnpremul_SkAlphaType);
-          if (color_info.colorType() == kN32_SkColorType)
-            color_info = color_info.makeColorType(kRGBA_8888_SkColorType);
-          else
-            color_info = color_info.makeColorType(kRGBA_F16_SkColorType);
+          SkColorType color_type = GetRenderingContextSkColorType();
+          if (color_type == kN32_SkColorType) {
+            color_type = kRGBA_8888_SkColorType;
+          } else {
+            color_type = kRGBA_F16_SkColorType;
+          }
           image_bitmap = StaticBitmapImage::Create(
               std::move(pixel_data),
               SkImageInfo::Make(
                   SkISize::Make(adjusted_size.width(), adjusted_size.height()),
-                  color_info));
+                  color_type, kUnpremul_SkAlphaType,
+                  GetRenderingContextSkColorSpace()));
         }
       }
     }
diff --git a/third_party/blink/renderer/core/html/forms/file_input_type.cc b/third_party/blink/renderer/core/html/forms/file_input_type.cc
index 0dd6016..31c3ecc 100644
--- a/third_party/blink/renderer/core/html/forms/file_input_type.cc
+++ b/third_party/blink/renderer/core/html/forms/file_input_type.cc
@@ -400,8 +400,6 @@
 }
 
 void FileInputType::DisabledAttributeChanged() {
-  DCHECK(RuntimeEnabledFeatures::CreateInputShadowTreeDuringLayoutEnabled() ||
-         IsShadowHost(GetElement()));
   if (Element* button = UploadButton()) {
     button->SetBooleanAttribute(html_names::kDisabledAttr,
                                 GetElement().IsDisabledFormControl());
@@ -409,8 +407,6 @@
 }
 
 void FileInputType::MultipleAttributeChanged() {
-  DCHECK(RuntimeEnabledFeatures::CreateInputShadowTreeDuringLayoutEnabled() ||
-         IsShadowHost(GetElement()));
   if (Element* button = UploadButton()) {
     button->setAttribute(
         html_names::kValueAttr,
diff --git a/third_party/blink/renderer/core/html/forms/html_button_element.cc b/third_party/blink/renderer/core/html/forms/html_button_element.cc
index db7f9c4..55b9e7115 100644
--- a/third_party/blink/renderer/core/html/forms/html_button_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_button_element.cc
@@ -141,7 +141,7 @@
   }
 
   if (!IsInTreeScope() || IsDisabledFormControl() ||
-      (Form() && CanBeSuccessfulSubmitButton())) {
+      (Form() && FastHasAttribute(html_names::kTypeAttr) && type_ == kSubmit)) {
     return nullptr;
   }
 
@@ -248,24 +248,44 @@
 
 void HTMLButtonElement::DefaultEventHandler(Event& event) {
   if (event.type() == event_type_names::kDOMActivate) {
+    bool potentialCommand = (FastHasAttribute(html_names::kCommandforAttr) ||
+                             FastHasAttribute(html_names::kCommandAttr));
+    bool implicitSubmit =
+        type_ == kSubmit && !FastHasAttribute(html_names::kTypeAttr);
+
     if (!IsDisabledFormControl()) {
       if (Form() && type_ == kSubmit) {
+        if (implicitSubmit && potentialCommand) {
+          AddConsoleMessage(mojom::blink::ConsoleMessageSource::kOther,
+                            mojom::blink::ConsoleMessageLevel::kWarning,
+                            "Buttons associated with forms that include "
+                            "command or commandfor attributes are "
+                            "ambiguous, and require a type=button attribute. "
+                            "No action will be taken.");
+          return;
+        } else if (potentialCommand) {
+          DCHECK(FastHasAttribute(html_names::kTypeAttr));
+          AddConsoleMessage(
+              mojom::blink::ConsoleMessageSource::kOther,
+              mojom::blink::ConsoleMessageLevel::kWarning,
+              "Buttons with an explicit type=submit will always submit a form, "
+              "so command or commandfor attributes will be ignored.");
+        }
         Form()->PrepareForSubmission(&event, this);
         event.SetDefaultHandled();
         return;
       }
       if (Form() && type_ == kReset) {
+        if (potentialCommand) {
+          AddConsoleMessage(mojom::blink::ConsoleMessageSource::kOther,
+                            mojom::blink::ConsoleMessageLevel::kWarning,
+                            "Buttons with a type of reset will ignore the "
+                            "command or commandfor attributes.");
+        }
         Form()->reset();
         event.SetDefaultHandled();
         return;
       }
-      if (Form() && type_ != kButton && commandForElement()) {
-        AddConsoleMessage(
-            mojom::blink::ConsoleMessageSource::kOther,
-            mojom::blink::ConsoleMessageLevel::kWarning,
-            "commandfor is ignored on form buttons without type=button.");
-        return;
-      }
     }
 
     // Buttons with a commandfor will dispatch a CommandEvent on the
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.cc b/third_party/blink/renderer/core/html/forms/html_input_element.cc
index adbd02d..3300bcd 100644
--- a/third_party/blink/renderer/core/html/forms/html_input_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_input_element.cc
@@ -379,9 +379,6 @@
 }
 
 void HTMLInputElement::setType(const AtomicString& type) {
-  if (!RuntimeEnabledFeatures::CreateInputShadowTreeDuringLayoutEnabled()) {
-    EnsureShadowSubtree();
-  }
   setAttribute(html_names::kTypeAttr, type);
 }
 
@@ -404,8 +401,7 @@
   if (!default_value.IsNull())
     input_type_->WarnIfValueIsInvalid(default_value);
 
-  if (!RuntimeEnabledFeatures::CreateInputShadowTreeDuringLayoutEnabled() ||
-      input_type_view_->HasCreatedShadowSubtree()) {
+  if (input_type_view_->HasCreatedShadowSubtree()) {
     input_type_view_->UpdateView();
   } else {
     input_type_view_->set_needs_update_view_in_create_shadow_subtree(true);
@@ -492,9 +488,7 @@
   // No need for CreateShadowSubtreeIfNeeded() to call UpdateView() as we'll
   // do that later on in this function (and calling UpdateView() here is
   // problematic as state hasn't fully been updated).
-  if (RuntimeEnabledFeatures::CreateInputShadowTreeDuringLayoutEnabled()) {
-    input_type_view_->set_needs_update_view_in_create_shadow_subtree(false);
-  }
+  input_type_view_->set_needs_update_view_in_create_shadow_subtree(false);
   input_type_view_->CreateShadowSubtreeIfNeeded(true);
 
   UpdateWillValidateCache();
@@ -867,7 +861,6 @@
     input_type_->WarnIfValueIsInvalidAndElementIsVisible(value);
     input_type_->InRangeChanged();
     if (input_type_view_->HasCreatedShadowSubtree() ||
-        !RuntimeEnabledFeatures::CreateInputShadowTreeDuringLayoutEnabled() ||
         !input_type_view_->NeedsShadowSubtree()) {
       input_type_view_->ValueAttributeChanged();
     } else {
@@ -1770,8 +1763,7 @@
     if (!Form()) {
       AddToRadioButtonGroup();
     }
-    if (RuntimeEnabledFeatures::CreateInputShadowTreeDuringLayoutEnabled() &&
-        !input_type_view_->HasCreatedShadowSubtree() &&
+    if (!input_type_view_->HasCreatedShadowSubtree() &&
         input_type_view_->NeedsShadowSubtree()) {
       scheduled_create_shadow_tree_ = true;
       GetDocument().ScheduleShadowTreeCreation(*this);
@@ -1780,10 +1772,6 @@
   ResetListAttributeTargetObserver();
   LogAddElementIfIsolatedWorldAndInDocument("input", html_names::kTypeAttr,
                                             html_names::kFormactionAttr);
-  if (!RuntimeEnabledFeatures::CreateInputShadowTreeDuringLayoutEnabled()) {
-    EventDispatchForbiddenScope::AllowUserAgentEvents allow_events;
-    input_type_view_->CreateShadowSubtreeIfNeeded();
-  }
   return kInsertionShouldCallDidNotifySubtreeInsertions;
 }
 
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element_test.cc b/third_party/blink/renderer/core/html/forms/html_input_element_test.cc
index dded891..87fef47 100644
--- a/third_party/blink/renderer/core/html/forms/html_input_element_test.cc
+++ b/third_party/blink/renderer/core/html/forms/html_input_element_test.cc
@@ -157,11 +157,7 @@
       GetDocument(), CreateElementFlags::ByParser(&GetDocument()));
   EXPECT_EQ(nullptr, input->UserAgentShadowRoot());
   input->ParserSetAttributes(Vector<Attribute, kAttributePrealloc>());
-  if (RuntimeEnabledFeatures::CreateInputShadowTreeDuringLayoutEnabled()) {
-    EXPECT_EQ(nullptr, input->UserAgentShadowRoot());
-  } else {
-    EXPECT_NE(nullptr, input->UserAgentShadowRoot());
-  }
+  EXPECT_EQ(nullptr, input->UserAgentShadowRoot());
 }
 
 TEST_F(HTMLInputElementTest, NoAssertWhenMovedInNewDocument) {
diff --git a/third_party/blink/renderer/core/html/forms/image_input_type.cc b/third_party/blink/renderer/core/html/forms/image_input_type.cc
index 8ab3db6..f60944a 100644
--- a/third_party/blink/renderer/core/html/forms/image_input_type.cc
+++ b/third_party/blink/renderer/core/html/forms/image_input_type.cc
@@ -237,8 +237,7 @@
   if (use_fallback_content_)
     return;
   use_fallback_content_ = true;
-  if (!HasCreatedShadowSubtree() &&
-      RuntimeEnabledFeatures::CreateInputShadowTreeDuringLayoutEnabled()) {
+  if (!HasCreatedShadowSubtree()) {
     return;
   }
   if (GetElement().GetDocument().InStyleRecalc())
@@ -252,8 +251,7 @@
   if (!use_fallback_content_)
     return;
   use_fallback_content_ = false;
-  if (!HasCreatedShadowSubtree() &&
-      RuntimeEnabledFeatures::CreateInputShadowTreeDuringLayoutEnabled()) {
+  if (!HasCreatedShadowSubtree()) {
     return;
   }
   if (ShadowRoot* root = GetElement().UserAgentShadowRoot())
diff --git a/third_party/blink/renderer/core/html/forms/input_type_view.cc b/third_party/blink/renderer/core/html/forms/input_type_view.cc
index 00a3174e..6597ae6 100644
--- a/third_party/blink/renderer/core/html/forms/input_type_view.cc
+++ b/third_party/blink/renderer/core/html/forms/input_type_view.cc
@@ -147,13 +147,11 @@
   // not fully be up to date, so that it's problematic to do the following.
   // Additionally the following is not necessary when the type is changing,
   // because HTMLInputElement effectively has similar logic.
-  if (RuntimeEnabledFeatures::CreateInputShadowTreeDuringLayoutEnabled() &&
-      !is_type_changing) {
+  if (!is_type_changing) {
     if (needs_update_view_in_create_shadow_subtree_) {
       UpdateView();
     }
-    // When CreateInputShadowTreeDuringLayoutEnabled is true, placeholder
-    // updates are ignored. Update now if needed.
+    // Placeholder updates are ignored. Update now if needed.
     if (!GetElement().SuggestedValue().empty() ||
         GetElement().FastHasAttribute(html_names::kPlaceholderAttr)) {
       GetElement().UpdatePlaceholderVisibility();
diff --git a/third_party/blink/renderer/core/html/forms/input_type_view.h b/third_party/blink/renderer/core/html/forms/input_type_view.h
index 3eaf48b..a4539f4 100644
--- a/third_party/blink/renderer/core/html/forms/input_type_view.h
+++ b/third_party/blink/renderer/core/html/forms/input_type_view.h
@@ -128,7 +128,6 @@
   // changing the input-type.
   void CreateShadowSubtreeIfNeeded(bool is_type_changing = false);
   void set_needs_update_view_in_create_shadow_subtree(bool value) {
-    DCHECK(RuntimeEnabledFeatures::CreateInputShadowTreeDuringLayoutEnabled());
     needs_update_view_in_create_shadow_subtree_ = value;
   }
   virtual bool IsInnerEditorValueEmpty() const { return false; }
diff --git a/third_party/blink/renderer/core/html/forms/text_control_element.cc b/third_party/blink/renderer/core/html/forms/text_control_element.cc
index 7160ad86..9c0c282 100644
--- a/third_party/blink/renderer/core/html/forms/text_control_element.cc
+++ b/third_party/blink/renderer/core/html/forms/text_control_element.cc
@@ -207,8 +207,7 @@
   bool place_holder_was_visible = IsPlaceholderVisible();
   HTMLElement* placeholder = PlaceholderElement();
   if (!placeholder) {
-    if (RuntimeEnabledFeatures::CreateInputShadowTreeDuringLayoutEnabled() &&
-        !InnerEditorElement()) {
+    if (!InnerEditorElement()) {
       // The place holder visibility needs to be updated as it may be used by
       // CSS selectors.
       SetPlaceholderVisibility(PlaceholderShouldBeVisible());
diff --git a/third_party/blink/renderer/core/html/forms/text_field_input_type.cc b/third_party/blink/renderer/core/html/forms/text_field_input_type.cc
index 56346f26..9407791 100644
--- a/third_party/blink/renderer/core/html/forms/text_field_input_type.cc
+++ b/third_party/blink/renderer/core/html/forms/text_field_input_type.cc
@@ -555,8 +555,7 @@
 
 HTMLElement* TextFieldInputType::UpdatePlaceholderText(
     bool is_suggested_value) {
-  if (!HasCreatedShadowSubtree() &&
-      RuntimeEnabledFeatures::CreateInputShadowTreeDuringLayoutEnabled()) {
+  if (!HasCreatedShadowSubtree()) {
     return nullptr;
   }
   if (!SupportsPlaceholder()) {
diff --git a/third_party/blink/renderer/core/html/html_attribute_fuzztest.cc b/third_party/blink/renderer/core/html/html_attribute_fuzztest.cc
deleted file mode 100644
index 7081e16c..0000000
--- a/third_party/blink/renderer/core/html/html_attribute_fuzztest.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/functional/bind.h"
-#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/qualified_name.h"
-#include "third_party/blink/renderer/core/execution_context/security_context.h"
-#include "third_party/blink/renderer/core/frame/local_dom_window.h"
-#include "third_party/blink/renderer/core/html_names.h"
-#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/fuzztest/src/fuzztest/fuzztest.h"
-#include "third_party/fuzztest/src/fuzztest/googletest_fixture_adapter.h"
-
-namespace blink {
-
-class BlinkSetupFixture : public RenderingTest {
- public:
-  BlinkSetupFixture()
-      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
-
- protected:
-  void SetUp() override {
-    RenderingTest::SetUp();
-    SecurityContext& security_context =
-        GetDocument().GetFrame()->DomWindow()->GetSecurityContext();
-    security_context.SetSecurityOriginForTesting(nullptr);
-    security_context.SetSecurityOrigin(
-        SecurityOrigin::CreateFromString("https://fuzztestorigin.test"));
-  }
-};
-
-}  // namespace blink
-
-class BlinkAttributeFuzzTestFixture
-    : public fuzztest::PerFuzzTestFixtureAdapter<blink::BlinkSetupFixture> {
- public:
-  void NoElementAttributeCrashes(blink::html_names::HTMLTag tag,
-                                 const std::string& attribute_name,
-                                 const std::string& attribute_value) {
-    blink::Document& doc = GetDocument();
-    blink::Element* element =
-        doc.CreateRawElement(blink::html_names::TagToQualifiedName(tag));
-
-    blink::DummyExceptionStateForTesting exception_state;
-
-    element->setAttribute(WTF::AtomicString(WTF::String(attribute_name)),
-                          WTF::AtomicString(WTF::String(attribute_value)),
-                          exception_state);
-    doc.body()->AppendChild(element);
-    doc.body()->RemoveChildren();
-    blink::ThreadState::Current()->CollectAllGarbageForTesting();
-  }
-};
-
-// A domain which returns an integer within the total number of known
-// HTML elements, and can index into the blink::html_names::HTMLTag array.
-// This is not quite the optimal choice: ideally, we'd have a domain
-// which returns the string of the tag, such that test cases are stable
-// across Chromium versions when tags are added or removed. However, this
-// proves to be difficult because all the Blink string types require
-// garbage collection/allocation stuff to be initialized, and it isn't
-// at the time that this domain function is run. If this fuzzer proves
-// useful, though, we could expose more APIs from html_names.h.
-auto AnyKnownTag() {
-  return fuzztest::Map(
-      [](int tag_id) {
-        return static_cast<blink::html_names::HTMLTag>(tag_id);
-      },
-      fuzztest::InRange(0U, blink::html_names::kTagsCount - 1));
-}
-
-FUZZ_TEST_F(BlinkAttributeFuzzTestFixture, NoElementAttributeCrashes)
-    .WithDomains(AnyKnownTag(),
-                 // A note on the choice of domains for attribute names
-                 // and values.
-                 // This fuzzer would be quicker if we exposed a table
-                 // from html_names.h for all known valid attribute names.
-                 // But it might not actually explore parsing code which
-                 // chokes on invalid attribute names. Similarly,
-                 // we could use domains for any string rather than
-                 // just printable strings, to even more thoroughly explore
-                 // the parsing code. But this seems a good compromise.
-                 fuzztest::PrintableAsciiString(),
-                 fuzztest::PrintableAsciiString());
diff --git a/third_party/blink/renderer/core/html/html_dialog_element.cc b/third_party/blink/renderer/core/html/html_dialog_element.cc
index 8b901ab..debca03 100644
--- a/third_party/blink/renderer/core/html/html_dialog_element.cc
+++ b/third_party/blink/renderer/core/html/html_dialog_element.cc
@@ -33,6 +33,7 @@
 #include "third_party/blink/renderer/core/dom/focus_params.h"
 #include "third_party/blink/renderer/core/events/pointer_event.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/web_feature.h"
@@ -208,13 +209,8 @@
   if (!IsOpen()) {
     return;
   }
-  if (ClosedBy() == ClosedByState::kNone) {
-    exception_state.ThrowDOMException(
-        DOMExceptionCode::kInvalidStateError,
-        "To use requestClose, the dialog's closedBy state must not be 'none'.");
-    return;
-  }
   CHECK(close_watcher_);
+  close_watcher_->setEnabled(true);
   request_close_return_value_ = return_value;
   close_watcher_->requestClose();
   SetCloseWatcherEnabledState();
@@ -483,10 +479,9 @@
     return;
   }
   CHECK(IsOpen());
+  CHECK(window->GetFrame());
   close_watcher_ = CloseWatcher::Create(*window);
-  if (!close_watcher_) {
-    return;
-  }
+  CHECK(close_watcher_);
   if (RuntimeEnabledFeatures::HTMLDialogLightDismissEnabled()) {
     SetCloseWatcherEnabledState();
   }
diff --git a/third_party/blink/renderer/core/html/html_hr_element.cc b/third_party/blink/renderer/core/html/html_hr_element.cc
index 745d5c5..03a55b0 100644
--- a/third_party/blink/renderer/core/html/html_hr_element.cc
+++ b/third_party/blink/renderer/core/html/html_hr_element.cc
@@ -67,14 +67,18 @@
           style, CSSPropertyID::kMarginRight, CSSValueID::kAuto);
     }
   } else if (name == html_names::kWidthAttr) {
-    bool ok;
-    int v = value.ToInt(&ok);
-    if (ok && !v) {
-      AddPropertyToPresentationAttributeStyle(
-          style, CSSPropertyID::kWidth, 1,
-          CSSPrimitiveValue::UnitType::kPixels);
-    } else {
+    if (RuntimeEnabledFeatures::HTMLHRWidthAllowZeroEnabled()) {
       AddHTMLLengthToStyle(style, CSSPropertyID::kWidth, value);
+    } else {
+      bool ok;
+      int v = value.ToInt(&ok);
+      if (ok && !v) {
+        AddPropertyToPresentationAttributeStyle(
+            style, CSSPropertyID::kWidth, 1,
+            CSSPrimitiveValue::UnitType::kPixels);
+      } else {
+        AddHTMLLengthToStyle(style, CSSPropertyID::kWidth, value);
+      }
     }
   } else if (name == html_names::kColorAttr) {
     for (CSSPropertyID property_id :
diff --git a/third_party/blink/renderer/core/layout/anchor_query_map.cc b/third_party/blink/renderer/core/layout/anchor_query_map.cc
index 2347733..3fb21d5 100644
--- a/third_party/blink/renderer/core/layout/anchor_query_map.cc
+++ b/third_party/blink/renderer/core/layout/anchor_query_map.cc
@@ -285,7 +285,7 @@
           fragmentainer.converter.ToLogical(
               offset_from_fragmentainer + child.offset, child->Size()) +
           fragmentainer.offset;
-      children.push_back(LogicalFragmentLink{child.fragment, child_offset});
+      children.push_back(LogicalFragmentLink(*child.fragment, child_offset));
     }
     AddFragmentainerChildren(children,
                              fragmentainer.converter.GetWritingDirection());
diff --git a/third_party/blink/renderer/core/layout/column_layout_algorithm.cc b/third_party/blink/renderer/core/layout/column_layout_algorithm.cc
index 9187d3e..93a9db1 100644
--- a/third_party/blink/renderer/core/layout/column_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/column_layout_algorithm.cc
@@ -904,7 +904,7 @@
       for (wtf_size_t i = 0; i < new_columns.size(); i++) {
         auto& new_column = new_columns[i];
         columns.push_back(
-            LogicalFragmentLink{&new_column.Fragment(), new_column.offset});
+            LogicalFragmentLink(new_column.Fragment(), new_column.offset));
 
         // Because the current set of columns haven't been added to the builder
         // yet, any OOF descendants won't have been propagated up yet. Instead,
diff --git a/third_party/blink/renderer/core/layout/fragment_builder.cc b/third_party/blink/renderer/core/layout/fragment_builder.cc
index 01b1494..50ff268 100644
--- a/third_party/blink/renderer/core/layout/fragment_builder.cc
+++ b/third_party/blink/renderer/core/layout/fragment_builder.cc
@@ -110,7 +110,7 @@
                                    const PhysicalFragment& new_child,
                                    const LogicalOffset offset) {
   DCHECK_LT(index, children_.size());
-  children_[index] = LogicalFragmentLink{std::move(&new_child), offset};
+  children_[index] = LogicalFragmentLink(new_child, offset);
 }
 
 HeapVector<Member<LayoutBoxModelObject>>&
@@ -409,7 +409,7 @@
   // In order to know where list-markers are within the children list (for the
   // |SimplifiedLayoutAlgorithm|) we always place them as the first child.
   if (child->IsListMarker()) {
-    children_.push_front(LogicalFragmentLink{std::move(child), child_offset});
+    children_.push_front(LogicalFragmentLink(*child, child_offset));
     return;
   }
 
@@ -418,13 +418,12 @@
     // ::placeholder earlier.
     const wtf_size_t size = children_.size();
     if (size > 0) {
-      children_.insert(size - 1,
-                       LogicalFragmentLink{std::move(child), child_offset});
+      children_.insert(size - 1, LogicalFragmentLink(*child, child_offset));
       return;
     }
   }
 
-  children_.push_back(LogicalFragmentLink{std::move(child), child_offset});
+  children_.push_back(LogicalFragmentLink(*child, child_offset));
 }
 
 void FragmentBuilder::AddOutOfFlowChildCandidate(
diff --git a/third_party/blink/renderer/core/layout/logical_fragment_link.h b/third_party/blink/renderer/core/layout/logical_fragment_link.h
index 411f27e..0baaca7a 100644
--- a/third_party/blink/renderer/core/layout/logical_fragment_link.h
+++ b/third_party/blink/renderer/core/layout/logical_fragment_link.h
@@ -19,6 +19,9 @@
   DISALLOW_NEW();
 
  public:
+  LogicalFragmentLink(const PhysicalFragment& fragment, LogicalOffset offset)
+      : fragment(&fragment), offset(offset) {}
+
   const LogicalOffset& Offset() const { return offset; }
   const PhysicalFragment* get() const { return fragment.Get(); }
 
diff --git a/third_party/blink/renderer/core/layout/paginated_root_layout_algorithm.cc b/third_party/blink/renderer/core/layout/paginated_root_layout_algorithm.cc
index cc8e133d..0d695564 100644
--- a/third_party/blink/renderer/core/layout/paginated_root_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/paginated_root_layout_algorithm.cc
@@ -85,7 +85,7 @@
     // so that we don't have to add work-arounds to ignore it on the paint side.
     LogicalOffset origin =
         converter.ToLogical(PhysicalOffset(), result.fragment->Size());
-    page_containers.emplace_back(result.fragment, origin);
+    page_containers.emplace_back(*result.fragment, origin);
 
     page_area_params.break_token = result.fragmentainer_break_token;
     counters_context = std::move(result.counters_context);
@@ -141,7 +141,7 @@
 
       page_area_params.break_token = result.fragmentainer_break_token;
       counters_context = std::move(result.counters_context);
-      page_containers.emplace_back(result.fragment, old_container.offset);
+      page_containers.emplace_back(*result.fragment, old_container.offset);
       page_index++;
     }
   }
diff --git a/third_party/blink/renderer/core/layout/text_autosizer.cc b/third_party/blink/renderer/core/layout/text_autosizer.cc
index a297079..70722a8 100644
--- a/third_party/blink/renderer/core/layout/text_autosizer.cc
+++ b/third_party/blink/renderer/core/layout/text_autosizer.cc
@@ -57,6 +57,7 @@
 #include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/platform/network/network_utils.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/wtf/hash_functions.h"
 #include "ui/gfx/geometry/rect.h"
 
 namespace blink {
@@ -875,7 +876,8 @@
 
     // TODO(kojii): The width can be computed from style only when it's fixed.
     // consider for adding: writing mode, padding.
-    data.width_ = width.IsFixed() ? width.GetFloatValue() : .0f;
+    data.width_ =
+        width.IsFixed() ? WTF::NormalizeSign(width.GetFloatValue()) : 0.0f;
   }
 
   // Use nodeIndex as a rough approximation of column number
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc b/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc
index 10ba56b4..6a81f4e4 100644
--- a/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc
+++ b/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc
@@ -175,18 +175,14 @@
   return scrollbar_->GetTheme().UsesNinePatchTrackAndButtonsResource();
 }
 
-gfx::Size ScrollbarLayerDelegate::NinePatchTrackAndButtonsCanvasSize(
-    float scale) const {
+gfx::Size ScrollbarLayerDelegate::NinePatchTrackAndButtonsCanvasSize() const {
   CHECK(UsesNinePatchTrackAndButtonsResource());
-  return scrollbar_->GetTheme().NinePatchTrackAndButtonsCanvasSize(*scrollbar_,
-                                                                   scale);
+  return scrollbar_->GetTheme().NinePatchTrackAndButtonsCanvasSize(*scrollbar_);
 }
 
-gfx::Rect ScrollbarLayerDelegate::NinePatchTrackAndButtonsAperture(
-    float scale) const {
+gfx::Rect ScrollbarLayerDelegate::NinePatchTrackAndButtonsAperture() const {
   CHECK(UsesNinePatchTrackAndButtonsResource());
-  return scrollbar_->GetTheme().NinePatchTrackAndButtonsAperture(*scrollbar_,
-                                                                 scale);
+  return scrollbar_->GetTheme().NinePatchTrackAndButtonsAperture(*scrollbar_);
 }
 
 bool ScrollbarLayerDelegate::ShouldPaint() const {
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h b/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h
index f48cc886..def9321 100644
--- a/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h
+++ b/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h
@@ -59,8 +59,8 @@
   bool UsesSolidColorThumb() const override;
   gfx::Insets SolidColorThumbInsets() const override;
   bool UsesNinePatchTrackAndButtonsResource() const override;
-  gfx::Size NinePatchTrackAndButtonsCanvasSize(float scale) const override;
-  gfx::Rect NinePatchTrackAndButtonsAperture(float scale) const override;
+  gfx::Size NinePatchTrackAndButtonsCanvasSize() const override;
+  gfx::Rect NinePatchTrackAndButtonsAperture() const override;
   gfx::Rect ShrinkMainThreadedMinimalModeThumbRect(
       gfx::Rect& rect) const override;
 
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_theme.h b/third_party/blink/renderer/core/scroll/scrollbar_theme.h
index 189d1000..09de0eb8 100644
--- a/third_party/blink/renderer/core/scroll/scrollbar_theme.h
+++ b/third_party/blink/renderer/core/scroll/scrollbar_theme.h
@@ -228,20 +228,12 @@
   virtual gfx::Size NinePatchTrackAndButtonsCanvasSize(const Scrollbar&) const {
     NOTREACHED();
   }
-  virtual gfx::Size NinePatchTrackAndButtonsCanvasSize(const Scrollbar&,
-                                                       float scale) const {
-    NOTREACHED();
-  }
 
   // For a nine-patch resource, the aperture defines the center patch that will
   // be stretched out.
   virtual gfx::Rect NinePatchTrackAndButtonsAperture(const Scrollbar&) const {
     NOTREACHED();
   }
-  virtual gfx::Rect NinePatchTrackAndButtonsAperture(const Scrollbar&,
-                                                     float scale) const {
-    NOTREACHED();
-  }
 
   virtual bool AllowsHitTest() const { return true; }
 
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_theme_aura.cc b/third_party/blink/renderer/core/scroll/scrollbar_theme_aura.cc
index 6832b732..4c11888 100644
--- a/third_party/blink/renderer/core/scroll/scrollbar_theme_aura.cc
+++ b/third_party/blink/renderer/core/scroll/scrollbar_theme_aura.cc
@@ -30,7 +30,6 @@
 
 #include "third_party/blink/renderer/core/scroll/scrollbar_theme_aura.h"
 
-#include "base/numerics/safe_conversions.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "cc/input/scrollbar.h"
@@ -535,57 +534,35 @@
 
 gfx::Size ScrollbarThemeAura::NinePatchTrackAndButtonsCanvasSize(
     const Scrollbar& scrollbar) const {
-  return NinePatchTrackAndButtonsCanvasSize(scrollbar, /*scale=*/1.f);
-}
-
-gfx::Size ScrollbarThemeAura::NinePatchTrackAndButtonsCanvasSize(
-    const Scrollbar& scrollbar,
-    float scale) const {
   CHECK(UsesNinePatchTrackAndButtonsResource());
-  const gfx::SizeF button_size =
-      ScaleSize(gfx::SizeF(ButtonSize(scrollbar)), scale);
+  const gfx::Size button_size = ButtonSize(scrollbar);
   if (button_size.IsEmpty()) {
     return gfx::Size(1, 1);
   }
-  const gfx::Size scrollbar_size = ScaleToCeiledSize(scrollbar.Size(), scale);
+  const gfx::Size scrollbar_size = scrollbar.Size();
   if (scrollbar.Orientation() == kVerticalScrollbar) {
     return gfx::Size(
         button_size.width(),
-        std::min(scrollbar_size.height(),
-                 base::ClampCeil(button_size.height() * 2 + scale)));
+        std::min(scrollbar_size.height(), button_size.height() * 2 + 1));
   } else {
-    return gfx::Size(std::min(scrollbar_size.width(),
-                              base::ClampCeil(button_size.width() * 2 + scale)),
-                     button_size.height());
+    return gfx::Size(
+        std::min(scrollbar_size.width(), button_size.width() * 2 + 1),
+        button_size.height());
   }
 }
 
 gfx::Rect ScrollbarThemeAura::NinePatchTrackAndButtonsAperture(
     const Scrollbar& scrollbar) const {
-  return NinePatchTrackAndButtonsAperture(scrollbar, /*scale=*/1.f);
-}
-
-gfx::Rect ScrollbarThemeAura::NinePatchTrackAndButtonsAperture(
-    const Scrollbar& scrollbar,
-    float scale) const {
   CHECK(UsesNinePatchTrackAndButtonsResource());
-  const gfx::Size canvas_size =
-      NinePatchTrackAndButtonsCanvasSize(scrollbar, scale);
-  if (canvas_size == ScaleToCeiledSize(scrollbar.Size(), scale)) {
+  const gfx::Size scrollbar_size = scrollbar.Size();
+  const gfx::Size canvas_size = NinePatchTrackAndButtonsCanvasSize(scrollbar);
+  if (canvas_size == scrollbar_size) {
     return gfx::Rect(canvas_size);
   }
-
-  // If the canvas' length is even, then shift the aperture one pixel back from
-  // the middle and make it two pixels wide to maintain symmetry in the
-  // arrows when scaling.
   if (scrollbar.Orientation() == kVerticalScrollbar) {
-    const int offset = 1 - canvas_size.height() % 2;
-    return gfx::Rect(0, canvas_size.height() / 2 - offset, canvas_size.width(),
-                     1 + offset);
+    return gfx::Rect(0, canvas_size.height() / 2, canvas_size.width(), 1);
   } else {
-    const int offset = 1 - canvas_size.width() % 2;
-    return gfx::Rect(canvas_size.width() / 2 - offset, 0, 1 + offset,
-                     canvas_size.height());
+    return gfx::Rect(canvas_size.width() / 2, 0, 1, canvas_size.height());
   }
 }
 
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_theme_aura.h b/third_party/blink/renderer/core/scroll/scrollbar_theme_aura.h
index be33281f..c49737d 100644
--- a/third_party/blink/renderer/core/scroll/scrollbar_theme_aura.h
+++ b/third_party/blink/renderer/core/scroll/scrollbar_theme_aura.h
@@ -82,11 +82,7 @@
   SkColor4f ThumbColor(const Scrollbar&) const override;
   bool UsesNinePatchTrackAndButtonsResource() const override;
   gfx::Rect NinePatchTrackAndButtonsAperture(const Scrollbar&) const override;
-  gfx::Rect NinePatchTrackAndButtonsAperture(const Scrollbar&,
-                                             float scale) const override;
   gfx::Size NinePatchTrackAndButtonsCanvasSize(const Scrollbar&) const override;
-  gfx::Size NinePatchTrackAndButtonsCanvasSize(const Scrollbar&,
-                                               float scale) const override;
 
   // During a thumb drag, if the pointer moves outside a certain threshold in
   // the non-scrolling direction, the scroller is expected to "snap back" to the
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_theme_aura_test.cc b/third_party/blink/renderer/core/scroll/scrollbar_theme_aura_test.cc
index dfd0b39a..5fcf9831 100644
--- a/third_party/blink/renderer/core/scroll/scrollbar_theme_aura_test.cc
+++ b/third_party/blink/renderer/core/scroll/scrollbar_theme_aura_test.cc
@@ -20,7 +20,7 @@
 
 class ScrollbarThemeAuraButtonOverride final : public ScrollbarThemeAura {
  public:
-  ScrollbarThemeAuraButtonOverride() = default;
+  ScrollbarThemeAuraButtonOverride() : has_scrollbar_buttons_(true) {}
 
   void SetHasScrollbarButtons(bool value) { has_scrollbar_buttons_ = value; }
 
@@ -61,7 +61,7 @@
   using ScrollbarThemeAura::UsesNinePatchTrackAndButtonsResource;
 
  private:
-  bool has_scrollbar_buttons_ = true;
+  bool has_scrollbar_buttons_;
 };
 
 }  // namespace
@@ -423,54 +423,6 @@
                    /*track_and_buttons_expectation=*/false);
 }
 
-TEST_P(ScrollbarThemeAuraTest, VerticalNinePatchScalesCorrectly) {
-  if (!RuntimeEnabledFeatures::AuraScrollbarUsesNinePatchTrackEnabled()) {
-    GTEST_SKIP();
-  }
-
-  ScrollbarThemeAuraButtonOverride theme;
-  ASSERT_TRUE(theme.UsesNinePatchTrackAndButtonsResource());
-  MockScrollableArea* mock_scrollable_area = CreateMockScrollableArea();
-  Scrollbar* scrollbar = Scrollbar::CreateForTesting(
-      mock_scrollable_area, kVerticalScrollbar, &theme);
-  gfx::Rect frame_rect(12, 34, 15, 100);
-  scrollbar->SetFrameRect(frame_rect);
-  const float scale = GetParam();
-  const gfx::Size expected_canvas_size(
-      frame_rect.width() * scale,
-      base::ClampCeil(frame_rect.width() * scale * 2 + scale));
-  EXPECT_EQ(expected_canvas_size,
-            theme.NinePatchTrackAndButtonsCanvasSize(*scrollbar, scale));
-  const int offset = 1 - expected_canvas_size.height() % 2;
-  EXPECT_EQ(gfx::Rect(0, expected_canvas_size.height() / 2 - offset,
-                      expected_canvas_size.width(), 1 + offset),
-            theme.NinePatchTrackAndButtonsAperture(*scrollbar, scale));
-}
-
-TEST_P(ScrollbarThemeAuraTest, HorizontalNinePatchScalesCorrectly) {
-  if (!RuntimeEnabledFeatures::AuraScrollbarUsesNinePatchTrackEnabled()) {
-    GTEST_SKIP();
-  }
-
-  ScrollbarThemeAuraButtonOverride theme;
-  ASSERT_TRUE(theme.UsesNinePatchTrackAndButtonsResource());
-  MockScrollableArea* mock_scrollable_area = CreateMockScrollableArea();
-  Scrollbar* scrollbar = Scrollbar::CreateForTesting(
-      mock_scrollable_area, kHorizontalScrollbar, &theme);
-  gfx::Rect frame_rect(12, 34, 100, 15);
-  scrollbar->SetFrameRect(frame_rect);
-  const float scale = GetParam();
-  const gfx::Size expected_canvas_size(
-      base::ClampCeil(frame_rect.height() * scale * 2 + scale),
-      frame_rect.height() * scale);
-  EXPECT_EQ(expected_canvas_size,
-            theme.NinePatchTrackAndButtonsCanvasSize(*scrollbar, scale));
-  const int offset = 1 - expected_canvas_size.width() % 2;
-  EXPECT_EQ(gfx::Rect(expected_canvas_size.width() / 2 - offset, 0, 1 + offset,
-                      expected_canvas_size.height()),
-            theme.NinePatchTrackAndButtonsAperture(*scrollbar, scale));
-}
-
 INSTANTIATE_TEST_SUITE_P(All,
                          ScrollbarThemeAuraTest,
                          ::testing::Values(1.f, 1.25f, 1.5f, 1.75f, 2.f));
diff --git a/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h b/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h
index dff20bb..5fbaa02 100644
--- a/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h
+++ b/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h
@@ -57,6 +57,12 @@
   static DOMArrayBuffer* CreateOrNull(size_t num_elements,
                                       size_t element_byte_size);
   static DOMArrayBuffer* CreateOrNull(base::span<const uint8_t> source);
+  // TODO(tsepez): should be declared UNSAFE_BUFFER_USAGE.
+  static DOMArrayBuffer* CreateOrNull(const void* source, size_t byte_length) {
+    // SAFETY: Caller guarantees that `source` contains `byte_length` bytes.
+    return CreateOrNull(UNSAFE_BUFFERS(
+        base::span(static_cast<const uint8_t*>(source), byte_length)));
+  }
 
   // Only for use by XMLHttpRequest::responseArrayBuffer,
   // Internals::serializeObject, and
diff --git a/third_party/blink/renderer/core/typed_arrays/dom_typed_array.h b/third_party/blink/renderer/core/typed_arrays/dom_typed_array.h
index 2204fd52..19337e9 100644
--- a/third_party/blink/renderer/core/typed_arrays/dom_typed_array.h
+++ b/third_party/blink/renderer/core/typed_arrays/dom_typed_array.h
@@ -40,7 +40,11 @@
   static ThisType* Create(base::span<const ValueType> array)
     requires std::is_trivially_copyable_v<ValueType>
   {
-    DOMArrayBuffer* buffer = DOMArrayBuffer::Create(base::as_bytes(array));
+    // Intentionally avoids using `as_bytes`, since that requires
+    // `std::has_unique_object_representations_v<ValueType>`, which we neither
+    // need here nor can guarantee.
+    DOMArrayBuffer* buffer =
+        DOMArrayBuffer::Create(array.data(), array.size_bytes());
     return Create(buffer, 0, array.size());
   }
 
@@ -53,8 +57,11 @@
   static ThisType* CreateOrNull(base::span<const ValueType> array)
     requires std::is_trivially_copyable_v<ValueType>
   {
+    // Intentionally avoids using `as_bytes`, since that requires
+    // `std::has_unique_object_representations_v<ValueType>`, which we neither
+    // need here nor can guarantee.
     DOMArrayBuffer* buffer =
-        DOMArrayBuffer::CreateOrNull(base::as_bytes(array));
+        DOMArrayBuffer::CreateOrNull(array.data(), array.size_bytes());
     return buffer ? Create(buffer, 0, array.size()) : nullptr;
   }
 
diff --git a/third_party/blink/renderer/modules/ai/ai.cc b/third_party/blink/renderer/modules/ai/ai.cc
index ee3b121..9ea89a6 100644
--- a/third_party/blink/renderer/modules/ai/ai.cc
+++ b/third_party/blink/renderer/modules/ai/ai.cc
@@ -81,7 +81,7 @@
 AILanguageDetectorFactory* AI::languageDetector() {
   if (!ai_language_detector_factory_) {
     ai_language_detector_factory_ =
-        MakeGarbageCollected<AILanguageDetectorFactory>();
+        MakeGarbageCollected<AILanguageDetectorFactory>(GetExecutionContext());
   }
   return ai_language_detector_factory_.Get();
 }
diff --git a/third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector.cc b/third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector.cc
index 76b99d7d..52e127d 100644
--- a/third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector.cc
+++ b/third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector.cc
@@ -4,11 +4,16 @@
 
 #include "third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector.h"
 
-#include "third_party/blink/renderer/platform/language_detection/detect.h"
-
 namespace blink {
 
-AILanguageDetector::AILanguageDetector() = default;
+AILanguageDetector::AILanguageDetector(
+    LanguageDetectionModel* language_detection_model)
+    : language_detection_model_(language_detection_model) {}
+
+void AILanguageDetector::Trace(Visitor* visitor) const {
+  visitor->Trace(language_detection_model_);
+  ScriptWrappable::Trace(visitor);
+}
 
 ScriptPromise<IDLSequence<LanguageDetectionResult>> AILanguageDetector::detect(
     ScriptState* script_state,
@@ -26,8 +31,9 @@
       ScriptPromiseResolver<IDLSequence<LanguageDetectionResult>>>(
       script_state);
 
-  DetectLanguage(input, WTF::BindOnce(AILanguageDetector::OnDetectComplete,
-                                      WrapPersistent(resolver)));
+  language_detection_model_->DetectLanguage(
+      input, WTF::BindOnce(AILanguageDetector::OnDetectComplete,
+                           WrapPersistent(resolver)));
   return resolver->Promise();
 }
 
@@ -36,7 +42,7 @@
 }
 
 HeapVector<Member<LanguageDetectionResult>> AILanguageDetector::ConvertResult(
-    WTF::Vector<LanguagePrediction> predictions) {
+    WTF::Vector<LanguageDetectionModel::LanguagePrediction> predictions) {
   HeapVector<Member<LanguageDetectionResult>> result;
   for (const auto& prediction : predictions) {
     auto* one = MakeGarbageCollected<LanguageDetectionResult>();
@@ -49,8 +55,8 @@
 
 void AILanguageDetector::OnDetectComplete(
     ScriptPromiseResolver<IDLSequence<LanguageDetectionResult>>* resolver,
-    base::expected<WTF::Vector<LanguagePrediction>, DetectLanguageError>
-        result) {
+    base::expected<WTF::Vector<LanguageDetectionModel::LanguagePrediction>,
+                   DetectLanguageError> result) {
   if (result.has_value()) {
     // Order the result from most to least confident.
     std::sort(result.value().rbegin(), result.value().rend());
diff --git a/third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector.h b/third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector.h
index e9435302..ea350452 100644
--- a/third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector.h
+++ b/third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector.h
@@ -11,7 +11,7 @@
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ai_language_detector_detect_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_language_detection_result.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-#include "third_party/blink/renderer/platform/language_detection/detect.h"
+#include "third_party/blink/renderer/platform/language_detection/language_detection_model.h"
 
 namespace blink {
 
@@ -19,9 +19,11 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  explicit AILanguageDetector();
+  explicit AILanguageDetector(LanguageDetectionModel* language_detection_model);
   ~AILanguageDetector() override = default;
 
+  void Trace(Visitor* visitor) const override;
+
   ScriptPromise<IDLSequence<LanguageDetectionResult>> detect(
       ScriptState* script_state,
       const WTF::String& input,
@@ -31,11 +33,14 @@
 
   // TODO(crbug.com/349927087): Make the functions below free functions.
   static HeapVector<Member<LanguageDetectionResult>> ConvertResult(
-      WTF::Vector<LanguagePrediction> predictions);
+      WTF::Vector<LanguageDetectionModel::LanguagePrediction> predictions);
   static void OnDetectComplete(
       ScriptPromiseResolver<IDLSequence<LanguageDetectionResult>>* resolver,
-      base::expected<WTF::Vector<LanguagePrediction>, DetectLanguageError>
-          result);
+      base::expected<WTF::Vector<LanguageDetectionModel::LanguagePrediction>,
+                     DetectLanguageError> result);
+
+ private:
+  Member<LanguageDetectionModel> language_detection_model_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector_factory.cc b/third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector_factory.cc
index e9e2cdf..ebec155 100644
--- a/third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector_factory.cc
+++ b/third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector_factory.cc
@@ -8,7 +8,29 @@
 #include "third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector.h"
 
 namespace blink {
-AILanguageDetectorFactory::AILanguageDetectorFactory() = default;
+AILanguageDetectorFactory::AILanguageDetectorFactory(ExecutionContext* context)
+    : ExecutionContextClient(context) {}
+
+void AILanguageDetectorFactory::Trace(Visitor* visitor) const {
+  ScriptWrappable::Trace(visitor);
+  ExecutionContextClient::Trace(visitor);
+}
+
+namespace {
+void HandleCreateDetectorCallback(
+    ScriptPromiseResolver<blink::AILanguageDetector>* resolver,
+    base::expected<LanguageDetectionModel*, DetectLanguageError> maybe_model) {
+  if (maybe_model.has_value()) {
+    resolver->Resolve(
+        MakeGarbageCollected<AILanguageDetector>(maybe_model.value()));
+  } else {
+    switch (maybe_model.error()) {
+      case DetectLanguageError::kUnavailable:
+        resolver->Reject("Model not available");
+    }
+  }
+}
+}  // namespace
 
 ScriptPromise<AILanguageDetector> AILanguageDetectorFactory::create(
     ScriptState* script_state,
@@ -24,7 +46,10 @@
   auto* resolver =
       MakeGarbageCollected<ScriptPromiseResolver<AILanguageDetector>>(
           script_state);
-  resolver->Resolve(MakeGarbageCollected<AILanguageDetector>());
+  LanguageDetectionModel::Create(
+      GetExecutionContext()->GetBrowserInterfaceBroker(),
+      WTF::BindOnce(&HandleCreateDetectorCallback, WrapPersistent(resolver)));
+
   return resolver->Promise();
 }
 
diff --git a/third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector_factory.h b/third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector_factory.h
index 8ee88d4..6dc052cf 100644
--- a/third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector_factory.h
+++ b/third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector_factory.h
@@ -6,17 +6,23 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_AI_ON_DEVICE_TRANSLATION_AI_LANGUAGE_DETECTOR_FACTORY_H_
 
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ai_language_detector_create_options.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
 #include "third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector.h"
 #include "third_party/blink/renderer/modules/ai/on_device_translation/ai_language_detector_capabilities.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 
 namespace blink {
-class AILanguageDetectorFactory final : public ScriptWrappable {
+// `ExecutionContextClient` gives us access to the browser interface broker.
+class AILanguageDetectorFactory final : public ScriptWrappable,
+                                        ExecutionContextClient {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  explicit AILanguageDetectorFactory();
+  explicit AILanguageDetectorFactory(ExecutionContext* context);
 
+  void Trace(Visitor* visitor) const override;
+
+  // Creates an `AILanguageDetector`, with a model ready to use.
   ScriptPromise<AILanguageDetector> create(
       ScriptState* script_state,
       AILanguageDetectorCreateOptions* options,
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.idl b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.idl
index b542d02..f82cb39 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.idl
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.idl
@@ -39,7 +39,7 @@
 
     // image smoothing
     attribute boolean imageSmoothingEnabled; // (default True)
-    [MeasureAs=Canvas2DImageSmoothingQuality] attribute ImageSmoothingQuality imageSmoothingQuality; // (default "low")
+    [MeasureAs=Canvas2DImageSmoothingQuality2] attribute ImageSmoothingQuality imageSmoothingQuality; // (default "low")
 
     // colors and styles (see also the CanvasDrawingStyles interface)
     [HighEntropy, SetterCallWith=Isolate, RaisesException=Setter, GetterCallWith=ScriptState] attribute any strokeStyle; // (default black)
diff --git a/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.h b/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.h
index 00422bf..e9ee5623 100644
--- a/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.h
+++ b/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.h
@@ -41,6 +41,11 @@
   scoped_refptr<StaticBitmapImage> GetImage(FlushReason) final;
 
   void SetUV(const gfx::PointF& left_top, const gfx::PointF& right_bottom);
+
+  SkColorInfo CanvasRenderingContextSkColorInfo() const final {
+    return SkColorInfo(kN32_SkColorType, kPremul_SkAlphaType,
+                       SkColorSpace::MakeSRGB());
+  }
   bool IsComposited() const final { return true; }
   bool PushFrame() override;
 
diff --git a/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent.cc b/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent.cc
index 7b7f2b6..3e2cb6a7 100644
--- a/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent.cc
+++ b/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent.cc
@@ -17,6 +17,10 @@
 #include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
+#include "third_party/blink/renderer/core/layout/table/layout_table.h"
+#include "third_party/blink/renderer/core/layout/table/layout_table_caption.h"
+#include "third_party/blink/renderer/core/layout/table/layout_table_row.h"
+#include "third_party/blink/renderer/core/layout/table/layout_table_section.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 
@@ -32,7 +36,7 @@
 constexpr float kHeading5FontSizeMultiplier = 0.83;
 constexpr float kHeading6FontSizeMultiplier = 0.67;
 
-// TODO(khushalsagar): This is duplicating logic from
+// TODO(b/383128653): This is duplicating logic from
 // UnsupportedTagTypeValueForNode, consider reusing it.
 bool IsHeadingTag(const HTMLElement& element) {
   return element.HasTagName(html_names::kH1Tag) ||
@@ -124,6 +128,14 @@
     return mojom::blink::AIPageContentAttributeType::kFigure;
   }
 
+  if (object.IsTable()) {
+    return mojom::blink::AIPageContentAttributeType::kTable;
+  }
+
+  if (object.IsTableCell()) {
+    return mojom::blink::AIPageContentAttributeType::kTableCell;
+  }
+
   // TODO: Add FormData for attribute_type = FORM.
   return std::nullopt;
 }
@@ -254,6 +266,11 @@
         child_content_node->content_attributes->attribute_type ==
             mojom::blink::AIPageContentAttributeType::kIframe) {
       ProcessIframe(*GetIFrame(*child), *child_content_node);
+    } else if (child_content_node &&
+        child_content_node->content_attributes->attribute_type ==
+            mojom::blink::AIPageContentAttributeType::kTable) {
+      ProcessTable(To<LayoutTable>(*child), *child_content_node,
+                   document_style);
     } else {
       auto& node_for_child =
           child_content_node ? *child_content_node : content_node;
@@ -359,11 +376,11 @@
     image_info->image_bounding_box =
         image->AbsoluteBoundingBoxRect(kMapCoordinatesFlags);
     if (auto* image_element = DynamicTo<HTMLImageElement>(image->GetNode())) {
-      // TODO(khushalsagar): A11y stack generates alt text using image data
+      // TODO(b/383127202): A11y stack generates alt text using image data
       // which could be reused for this.
       image_info->image_caption = image_element->AltText();
     }
-    // TODO(khushalsagar): Include image source origin.
+    // TODO(b/382558422): Include image source origin.
     attributes.image_info.emplace_back(std::move(image_info));
   }
 }
@@ -393,4 +410,67 @@
   geometry.visible_bounding_box = ToEnclosingRect(visible_bounding_box);
 }
 
+void AIPageContentAgent::ProcessTable(
+    const LayoutTable& object,
+    mojom::blink::AIPageContentNode& content_node,
+    const ComputedStyle& document_style) const {
+  auto table_data = mojom::blink::AIPageContentTableData::New();
+  for (auto* child = object.FirstChild(); child; child = child->NextSibling()) {
+    if (child->IsTableCaption()) {
+      ProcessTableCaption(To<LayoutTableCaption>(*child), *table_data);
+    }
+    if (child->IsTableSection()) {
+      ProcessTableSection(To<LayoutTableSection>(*child), *table_data,
+                          document_style);
+    }
+  }
+  content_node.content_attributes->table_data = std::move(table_data);
+}
+
+void AIPageContentAgent::ProcessTableCaption(
+    const LayoutTableCaption& object,
+    mojom::blink::AIPageContentTableData& table_data) const {
+  StringBuilder table_name;
+  for (auto* child = object.FirstChild(); child; child = child->NextSibling()) {
+    if (const auto* layout_text = DynamicTo<LayoutText>(*child)) {
+      table_name.Append(layout_text->TransformedText());
+    }
+  }
+  table_data.table_name = table_name.ToString();
+}
+
+void AIPageContentAgent::ProcessTableSection(
+    const LayoutTableSection& object,
+    mojom::blink::AIPageContentTableData& table_data,
+    const ComputedStyle& document_style) const {
+  auto* element = DynamicTo<HTMLElement>(object.GetNode());
+  for (auto* child = object.FirstChild(); child; child = child->NextSibling()) {
+    auto row = mojom::blink::AIPageContentTableRow::New();
+    ProcessTableRow(To<LayoutTableRow>(*child), *row, document_style);
+    if (element && element->HasTagName(html_names::kTheadTag)) {
+      table_data.header_rows.emplace_back(std::move(row));
+    } else if (element && element->HasTagName(html_names::kTfootTag)) {
+      table_data.footer_rows.emplace_back(std::move(row));
+    } else {
+      table_data.body_rows.emplace_back(std::move(row));
+    }
+  }
+}
+
+void AIPageContentAgent::ProcessTableRow(
+    const LayoutTableRow& object,
+    mojom::blink::AIPageContentTableRow& table_row,
+    const ComputedStyle& document_style) const {
+  for (auto* child = object.FirstChild(); child; child = child->NextSibling()) {
+    // Add the cell contents as a ContentNode.
+    // TODO(b/383127685): Consider adding additional information as
+    // CellContentData, such as the cell's column span.
+    auto child_content_node = MaybeGenerateContentNode(*child);
+    MaybeAddNodeContent(*child, *child_content_node->content_attributes,
+                        document_style);
+    ProcessNode(*child, *child_content_node, document_style);
+    table_row.cells.emplace_back(std::move(child_content_node));
+  }
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent.h b/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent.h
index e9efd46e..4f4ab2b 100644
--- a/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent.h
+++ b/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent.h
@@ -16,9 +16,13 @@
 
 namespace blink {
 class Document;
-class LayoutObject;
-class LocalFrame;
 class LayoutIFrame;
+class LayoutObject;
+class LayoutTable;
+class LayoutTableCaption;
+class LayoutTableSection;
+class LayoutTableRow;
+class LocalFrame;
 
 // AIPageContent is responsible for handling requests for inner-text. It calls
 // to InnerTextBuilder to handle building of the text.
@@ -64,6 +68,18 @@
                  mojom::blink::AIPageContentAttributes& attributes) const;
   void AddNodeGeometry(const LayoutObject& object,
                        mojom::blink::AIPageContentGeometry& geometry) const;
+  void ProcessTable(const LayoutTable& object,
+                    mojom::blink::AIPageContentNode& content_node,
+                    const ComputedStyle& document_style) const;
+  void ProcessTableCaption(
+      const LayoutTableCaption& object,
+      mojom::blink::AIPageContentTableData& table_data) const;
+  void ProcessTableSection(const LayoutTableSection& object,
+                           mojom::blink::AIPageContentTableData& table_data,
+                           const ComputedStyle& document_style) const;
+  void ProcessTableRow(const LayoutTableRow& object,
+                       mojom::blink::AIPageContentTableRow& table_row,
+                       const ComputedStyle& document_style) const;
 
   HeapMojoReceiverSet<mojom::blink::AIPageContentAgent, AIPageContentAgent>
       receiver_set_;
diff --git a/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent_unittest.cc b/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent_unittest.cc
index 65870ea..90d89a4 100644
--- a/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent_unittest.cc
+++ b/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent_unittest.cc
@@ -488,5 +488,191 @@
   EXPECT_TRUE(text.text_info[7]->text_style->has_emphasis);
 }
 
+TEST_F(AIPageContentAgentTest, Table) {
+  frame_test_helpers::LoadHTMLString(
+      helper_.LocalMainFrame(),
+      "<body>"
+      "  <table>"
+      "    <caption>Table caption</caption>"
+      "    <thead>"
+      "      <th colspan='2'>Header</th>"
+      "    </thead>"
+      "    <tr>"
+      "      <td>Row 1 Column 1</td>"
+      "      <td>Row 1 Column 2</td>"
+      "    </tr>"
+      "    <tr>"
+      "      <td>Row 2 Column 1</td>"
+      "      <td>Row 2 Column 2</td>"
+      "    </tr>"
+      "    <tfoot>"
+      "      <td>Footer 1</td>"
+      "      <td>Footer 2</td>"
+      "    </tfoot>"
+      "  </table>"
+      "</body>",
+      url_test_helpers::ToKURL("http://foobar.com"));
+
+  auto* agent = AIPageContentAgent::GetOrCreateForTesting(
+      *helper_.LocalMainFrame()->GetFrame()->GetDocument());
+  ASSERT_TRUE(agent);
+
+  auto content = agent->GetAIPageContentSync();
+  ASSERT_TRUE(content);
+  ASSERT_TRUE(content->root_node);
+
+  const auto& root = *content->root_node;
+  ASSERT_EQ(root.children_nodes.size(), 1u);
+
+  const auto& table = *root.children_nodes[0]->content_attributes;
+  EXPECT_EQ(table.attribute_type,
+            mojom::blink::AIPageContentAttributeType::kTable);
+  ASSERT_TRUE(table.table_data);
+
+  EXPECT_EQ(table.table_data->table_name, "Table caption");
+
+  const auto& header_rows = table.table_data->header_rows;
+  EXPECT_EQ(header_rows.size(), 1u);
+
+  const auto& header_row = header_rows[0]->cells;
+  EXPECT_EQ(header_row.size(), 1u);
+  EXPECT_EQ(header_row[0]->content_attributes->text_info[0]->text_content,
+            "Header");
+
+  const auto& body_rows = table.table_data->body_rows;
+  EXPECT_EQ(body_rows.size(), 2u);
+
+  const auto& row_1 = body_rows[0]->cells;
+  EXPECT_EQ(row_1.size(), 2u);
+  EXPECT_EQ(row_1[0]->content_attributes->text_info[0]->text_content,
+            "Row 1 Column 1");
+  EXPECT_EQ(row_1[1]->content_attributes->text_info[0]->text_content,
+            "Row 1 Column 2");
+
+  const auto& row_2 = body_rows[1]->cells;
+  EXPECT_EQ(row_2.size(), 2u);
+  EXPECT_EQ(row_2[0]->content_attributes->text_info[0]->text_content,
+            "Row 2 Column 1");
+  EXPECT_EQ(row_2[1]->content_attributes->text_info[0]->text_content,
+            "Row 2 Column 2");
+
+  const auto& footer_rows = table.table_data->footer_rows;
+  EXPECT_EQ(footer_rows.size(), 1u);
+
+  const auto& footer_row = footer_rows[0]->cells;
+  EXPECT_EQ(footer_row.size(), 2u);
+  EXPECT_EQ(footer_row[0]->content_attributes->text_info[0]->text_content,
+            "Footer 1");
+  EXPECT_EQ(footer_row[1]->content_attributes->text_info[0]->text_content,
+            "Footer 2");
+}
+
+TEST_F(AIPageContentAgentTest, TableMadeWithCss) {
+  frame_test_helpers::LoadHTMLString(
+      helper_.LocalMainFrame(),
+      "<body>"
+      "    <style>"
+      "        .table {"
+      "            display: table;"
+      "            border-collapse: collapse;"
+      "            width: 100%;"
+      "        }"
+      "        .row {"
+      "            display: table-row;"
+      "        }"
+      "        .cell {"
+      "            display: table-cell;"
+      "            border: 1px solid #000;"
+      "            padding: 8px;"
+      "            text-align: center;"
+      "        }"
+      "        .header {"
+      "            background-color: #f4f4f4;"
+      "            font-weight: bold;"
+      "        }"
+      "    </style>"
+      "    <div class='table'>"
+      //       Header Rows
+      "        <div class='row header'>"
+      "            <div class='cell' colspan='2'>Personal Info</div>"
+      "            <div class='cell' colspan='2'>Contact Info</div>"
+      "        </div>"
+      "        <div class='row header'>"
+      "            <div class='cell'>Name</div>"
+      "            <div class='cell'>Age</div>"
+      "            <div class='cell'>Email</div>"
+      "            <div class='cell'>Phone</div>"
+      "        </div>"
+      //       Body Rows
+      "        <div class='row'>"
+      "            <div class='cell'>John Doe</div>"
+      "            <div class='cell'>30</div>"
+      "            <div class='cell'>john.doe@example.com</div>"
+      "            <div class='cell'>123-456-7890</div>"
+      "        </div>"
+      "        <div class='row'>"
+      "            <div class='cell'>Jane Smith</div>"
+      "            <div class='cell'>28</div>"
+      "            <div class='cell'>jane.smith@example.com</div>"
+      "            <div class='cell'>987-654-3210</div>"
+      "        </div>"
+      "    </div>"
+      "</body>",
+      url_test_helpers::ToKURL("http://foobar.com"));
+
+  auto* agent = AIPageContentAgent::GetOrCreateForTesting(
+      *helper_.LocalMainFrame()->GetFrame()->GetDocument());
+  ASSERT_TRUE(agent);
+
+  auto content = agent->GetAIPageContentSync();
+  ASSERT_TRUE(content);
+  ASSERT_TRUE(content->root_node);
+
+  const auto& root = *content->root_node;
+  ASSERT_EQ(root.children_nodes.size(), 1u);
+
+  const auto& table = *root.children_nodes[0]->content_attributes;
+  EXPECT_EQ(table.attribute_type,
+            mojom::blink::AIPageContentAttributeType::kTable);
+  ASSERT_TRUE(table.table_data);
+
+  const auto& body_rows = table.table_data->body_rows;
+  EXPECT_EQ(body_rows.size(), 4u);
+
+  const auto& row_1 = body_rows[0]->cells;
+  EXPECT_EQ(row_1.size(), 2u);
+  EXPECT_EQ(row_1[0]->content_attributes->text_info[0]->text_content,
+            "Personal Info");
+  EXPECT_EQ(row_1[1]->content_attributes->text_info[0]->text_content,
+            "Contact Info");
+
+  const auto& row_2 = body_rows[1]->cells;
+  EXPECT_EQ(row_2.size(), 4u);
+  EXPECT_EQ(row_2[0]->content_attributes->text_info[0]->text_content, "Name");
+  EXPECT_EQ(row_2[1]->content_attributes->text_info[0]->text_content, "Age");
+  EXPECT_EQ(row_2[2]->content_attributes->text_info[0]->text_content, "Email");
+  EXPECT_EQ(row_2[3]->content_attributes->text_info[0]->text_content, "Phone");
+
+  const auto& row_3 = body_rows[2]->cells;
+  EXPECT_EQ(row_3.size(), 4u);
+  EXPECT_EQ(row_3[0]->content_attributes->text_info[0]->text_content,
+            "John Doe");
+  EXPECT_EQ(row_3[1]->content_attributes->text_info[0]->text_content, "30");
+  EXPECT_EQ(row_3[2]->content_attributes->text_info[0]->text_content,
+            "john.doe@example.com");
+  EXPECT_EQ(row_3[3]->content_attributes->text_info[0]->text_content,
+            "123-456-7890");
+
+  const auto& row_4 = body_rows[3]->cells;
+  EXPECT_EQ(row_4.size(), 4u);
+  EXPECT_EQ(row_4[0]->content_attributes->text_info[0]->text_content,
+            "Jane Smith");
+  EXPECT_EQ(row_4[1]->content_attributes->text_info[0]->text_content, "28");
+  EXPECT_EQ(row_4[2]->content_attributes->text_info[0]->text_content,
+            "jane.smith@example.com");
+  EXPECT_EQ(row_4[3]->content_attributes->text_info[0]->text_content,
+            "987-654-3210");
+}
+
 }  // namespace
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.idl b/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.idl
index c9e2aea..b86e848b 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.idl
+++ b/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.idl
@@ -9,20 +9,20 @@
 ] interface PaintRenderingContext2D {
     // state
     void save(); // push state on state stack
-    [RaisesException] void restore(); // pop state stack if top state was pushed by save, and restore state
+    [NoAllocDirectCall, RaisesException] void restore(); // pop state stack if top state was pushed by save, and restore state
     [MeasureAs=Canvas2DLayers, RuntimeEnabled=Canvas2dLayers, CallWith=ScriptState] void beginLayer(); // push state on state stack and creates bitmap for subsequent draw ops
     [MeasureAs=Canvas2DLayers, RuntimeEnabled=Canvas2dLayersWithOptions, CallWith=ScriptState, RaisesException] void beginLayer(BeginLayerOptions options); // push state on state stack and creates bitmap for subsequent draw ops
-    [RuntimeEnabled=Canvas2dLayers, RaisesException] void endLayer(); // pop state stack if top state was pushed by beginLayer, restore state and draw the bitmap
+    [NoAllocDirectCall, RuntimeEnabled=Canvas2dLayers, RaisesException] void endLayer(); // pop state stack if top state was pushed by beginLayer, restore state and draw the bitmap
     // Clear the canvas and reset the path
     void reset();
 
     // transformations (default transform is the identity matrix)
     [HighEntropy] void scale(unrestricted double x, unrestricted double y);
-    [HighEntropy] void rotate(unrestricted double angle);
+    [HighEntropy, NoAllocDirectCall] void rotate(unrestricted double angle);
     [HighEntropy] void translate(unrestricted double x, unrestricted double y);
     [HighEntropy] void transform(unrestricted double a, unrestricted double b, unrestricted double c, unrestricted double d, unrestricted double e, unrestricted double f);
-    void setTransform(unrestricted double a, unrestricted double b, unrestricted double c, unrestricted double d, unrestricted double e, unrestricted double f);
-    void resetTransform();
+    [HighEntropy] void setTransform(unrestricted double a, unrestricted double b, unrestricted double c, unrestricted double d, unrestricted double e, unrestricted double f);
+    [NoAllocDirectCall] void resetTransform();
     [RaisesException] void setTransform(optional DOMMatrixInit transform = {});
     DOMMatrix getTransform();
 
@@ -34,7 +34,7 @@
 
     // image smoothing
     attribute boolean imageSmoothingEnabled; // (default True)
-    [RuntimeEnabled=CanvasImageSmoothing] attribute ImageSmoothingQuality imageSmoothingQuality; // (default "low")
+    [RuntimeEnabled=CanvasImageSmoothing, MeasureAs=Canvas2DImageSmoothingQuality2] attribute ImageSmoothingQuality imageSmoothingQuality; // (default "low")
 
     // colors and styles (see also the CanvasDrawingStyles interface)
     [HighEntropy, SetterCallWith=Isolate, RaisesException=Setter, GetterCallWith=ScriptState] attribute any strokeStyle; // (default black)
@@ -51,23 +51,23 @@
     [HighEntropy] attribute DOMString shadowColor;
 
     // rects
-    [HighEntropy] void clearRect(unrestricted double x, unrestricted double y, unrestricted double width, unrestricted double height);
-    [HighEntropy] void fillRect(unrestricted double x, unrestricted double y, unrestricted double width, unrestricted double height);
-    [HighEntropy] void strokeRect(unrestricted double x, unrestricted double y, unrestricted double width, unrestricted double height);
+    [HighEntropy, NoAllocDirectCall] void clearRect(unrestricted double x, unrestricted double y, unrestricted double width, unrestricted double height);
+    [HighEntropy, NoAllocDirectCall] void fillRect(unrestricted double x, unrestricted double y, unrestricted double width, unrestricted double height);
+    [HighEntropy, NoAllocDirectCall] void strokeRect(unrestricted double x, unrestricted double y, unrestricted double width, unrestricted double height);
 
     // path API (see also CanvasPath)
-    [HighEntropy] void beginPath();
+    [HighEntropy, NoAllocDirectCall] void beginPath();
     [HighEntropy] void fill(optional CanvasFillRule winding);
     [HighEntropy] void fill(Path2D path, optional CanvasFillRule winding);
-    [HighEntropy] void stroke();
+    [HighEntropy, NoAllocDirectCall] void stroke();
     [HighEntropy] void stroke(Path2D path);
 
-    void clip(optional CanvasFillRule winding);
-    void clip(Path2D path, optional CanvasFillRule winding);
-    [HighEntropy, Measure] boolean isPointInPath(unrestricted double x, unrestricted double y, optional CanvasFillRule winding);
-    [HighEntropy, Measure] boolean isPointInPath(Path2D path, unrestricted double x, unrestricted double y, optional CanvasFillRule winding);
-    [HighEntropy, Measure] boolean isPointInStroke(unrestricted double x, unrestricted double y);
-    [HighEntropy, Measure] boolean isPointInStroke(Path2D path, unrestricted double x, unrestricted double y);
+    [HighEntropy] void clip(optional CanvasFillRule winding);
+    [HighEntropy] void clip(Path2D path, optional CanvasFillRule winding);
+    [HighEntropy, MeasureAs=Canvas2DIsPointInPath] boolean isPointInPath(unrestricted double x, unrestricted double y, optional CanvasFillRule winding);
+    [HighEntropy, MeasureAs=Canvas2DIsPointInPath] boolean isPointInPath(Path2D path, unrestricted double x, unrestricted double y, optional CanvasFillRule winding);
+    [HighEntropy, MeasureAs=Canvas2DIsPointInStroke] boolean isPointInStroke(unrestricted double x, unrestricted double y);
+    [HighEntropy, MeasureAs=Canvas2DIsPointInStroke] boolean isPointInStroke(Path2D path, unrestricted double x, unrestricted double y);
 
     // drawing images
     [RaisesException] void drawImage(CanvasImageSource image, unrestricted double x, unrestricted double y);
diff --git a/third_party/blink/renderer/modules/on_device_translation/language_detector.cc b/third_party/blink/renderer/modules/on_device_translation/language_detector.cc
index 7b5cad2e..1a90e308 100644
--- a/third_party/blink/renderer/modules/on_device_translation/language_detector.cc
+++ b/third_party/blink/renderer/modules/on_device_translation/language_detector.cc
@@ -5,8 +5,6 @@
 #include "third_party/blink/renderer/modules/on_device_translation/language_detector.h"
 
 #include "base/memory/scoped_refptr.h"
-#include "base/task/sequenced_task_runner.h"
-#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_language_detection_result.h"
@@ -16,14 +14,16 @@
 #include "third_party/blink/renderer/platform/bindings/exception_code.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-#include "third_party/blink/renderer/platform/language_detection/detect.h"
+#include "third_party/blink/renderer/platform/language_detection/language_detection_model.h"
 
 namespace blink {
 
-LanguageDetector::LanguageDetector() = default;
+LanguageDetector::LanguageDetector(
+    LanguageDetectionModel* language_detection_model)
+    : language_detection_model_(language_detection_model) {}
 
 void LanguageDetector::Trace(Visitor* visitor) const {
+  visitor->Trace(language_detection_model_);
   ScriptWrappable::Trace(visitor);
 }
 
@@ -43,8 +43,9 @@
       ScriptPromiseResolver<IDLSequence<LanguageDetectionResult>>>(
       script_state);
 
-  DetectLanguage(input, WTF::BindOnce(AILanguageDetector::OnDetectComplete,
-                                      WrapPersistent(resolver)));
+  language_detection_model_->DetectLanguage(
+      input, WTF::BindOnce(AILanguageDetector::OnDetectComplete,
+                           WrapPersistent(resolver)));
   return resolver->Promise();
 }
 
diff --git a/third_party/blink/renderer/modules/on_device_translation/language_detector.h b/third_party/blink/renderer/modules/on_device_translation/language_detector.h
index 590f466..86064fc 100644
--- a/third_party/blink/renderer/modules/on_device_translation/language_detector.h
+++ b/third_party/blink/renderer/modules/on_device_translation/language_detector.h
@@ -6,7 +6,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_ON_DEVICE_TRANSLATION_LANGUAGE_DETECTOR_H_
 
 #include "base/memory/scoped_refptr.h"
-#include "base/task/sequenced_task_runner.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_language_detection_result.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -15,12 +14,14 @@
 
 namespace blink {
 
+class LanguageDetectionModel;
+
 // The class that represents a Detector with source and target language.
 class LanguageDetector final : public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  explicit LanguageDetector();
+  explicit LanguageDetector(LanguageDetectionModel* language_detection_model);
   ~LanguageDetector() override = default;
 
   void Trace(Visitor* visitor) const override;
@@ -30,6 +31,9 @@
       ScriptState* script_state,
       const WTF::String& input,
       ExceptionState& exception_state);
+
+ private:
+  Member<LanguageDetectionModel> language_detection_model_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/on_device_translation/translation.cc b/third_party/blink/renderer/modules/on_device_translation/translation.cc
index 7e97c11..fd4678d 100644
--- a/third_party/blink/renderer/modules/on_device_translation/translation.cc
+++ b/third_party/blink/renderer/modules/on_device_translation/translation.cc
@@ -20,7 +20,10 @@
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/language_detection/language_detection_model.h"
 #include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace blink {
 namespace {
@@ -278,6 +281,22 @@
   return promise;
 }
 
+namespace {
+void HandleCreateDetectorCallback(
+    ScriptPromiseResolver<blink::LanguageDetector>* resolver,
+    base::expected<LanguageDetectionModel*, DetectLanguageError> maybe_model) {
+  if (maybe_model.has_value()) {
+    resolver->Resolve(
+        MakeGarbageCollected<LanguageDetector>(maybe_model.value()));
+  } else {
+    switch (maybe_model.error()) {
+      case DetectLanguageError::kUnavailable:
+        resolver->Reject("Model not available");
+    }
+  }
+}
+}  // namespace
+
 // TODO(crbug.com/349927087): The new version is
 // AILanguageDetectorFactory::create(). Delete this old version.
 ScriptPromise<LanguageDetector> Translation::createDetector(
@@ -292,7 +311,10 @@
   auto* resolver =
       MakeGarbageCollected<ScriptPromiseResolver<LanguageDetector>>(
           script_state);
-  resolver->Resolve(MakeGarbageCollected<LanguageDetector>());
+  LanguageDetectionModel::Create(
+      GetExecutionContext()->GetBrowserInterfaceBroker(),
+      WTF::BindOnce(&HandleCreateDetectorCallback, WrapPersistent(resolver)));
+
   return resolver->Promise();
 }
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc
index 3d63ddc..9718e2d 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc
@@ -103,8 +103,10 @@
 }
 
 SkColorInfo GPUCanvasContext::CanvasRenderingContextSkColorInfo() const {
-  if (!swap_buffers_)
-    return CanvasRenderingContext::CanvasRenderingContextSkColorInfo();
+  if (!swap_buffers_) {
+    return SkColorInfo(kN32_SkColorType, kPremul_SkAlphaType,
+                       SkColorSpace::MakeSRGB());
+  }
   return SkColorInfo(viz::ToClosestSkColorType(
                          /*gpu_compositing=*/true, swap_buffers_->Format()),
                      alpha_mode_ == V8GPUCanvasAlphaMode::Enum::kOpaque
@@ -241,14 +243,11 @@
   // If it was possible to prepare the transferable resource, the
   // ClientSharedImage must also be valid.
   CHECK(client_si);
-
-  // TODO(crbug.com/378688985): Move this inside PrepareTransferableResource.
-  transferable_resource.origin = client_si->surface_origin();
-
   auto canvas_resource = ExternalCanvasResource::Create(
       std::move(client_si), transferable_resource,
-      transferable_resource.resource_source, std::move(release_callback),
-      GetContextProviderWeakPtr(), /*resource_provider=*/nullptr);
+      transferable_resource.resource_source, transferable_resource.hdr_metadata,
+      std::move(release_callback), GetContextProviderWeakPtr(),
+      /*resource_provider=*/nullptr);
   if (!canvas_resource)
     return false;
 
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 521198f..c4caa949 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1250,8 +1250,8 @@
     "keyboard_codes.h",
     "language.cc",
     "language.h",
-    "language_detection/detect.cc",
-    "language_detection/detect.h",
+    "language_detection/language_detection_model.cc",
+    "language_detection/language_detection_model.h",
     "link_hash.cc",
     "link_hash.h",
     "media/media_player_client.h",
@@ -1764,6 +1764,8 @@
     "//cc",
     "//cc/ipc",
     "//cc/mojo_embedder",
+    "//components/language_detection/content/common",
+    "//components/language_detection/content/renderer",
     "//components/language_detection/core",
     "//components/paint_preview/common",
     "//components/search_engines:search_engine_utils",
diff --git a/third_party/blink/renderer/platform/fonts/font_description.cc b/third_party/blink/renderer/platform/fonts/font_description.cc
index 50d5b295..d2e5049f 100644
--- a/third_party/blink/renderer/platform/fonts/font_description.cc
+++ b/third_party/blink/renderer/platform/fonts/font_description.cc
@@ -355,19 +355,6 @@
     fields_.typesetting_features_ |= blink::kCaps;
 }
 
-namespace {
-
-// This converts -0.0 to 0.0, so that they have the same hash value. This
-// ensures that equal FontDescription have the same hash value.
-float NormalizeSign(float number) {
-  if (number == 0.0) [[unlikely]] {
-    return 0.0;
-  }
-  return number;
-}
-
-}  // namespace
-
 unsigned FontDescription::StyleHashWithoutFamilyList() const {
   unsigned hash = 0;
   const FontFeatureSettings* settings = FeatureSettings();
@@ -392,11 +379,11 @@
     WTF::AddIntToHash(hash, locale.Hash());
   }
 
-  WTF::AddFloatToHash(hash, NormalizeSign(specified_size_));
-  WTF::AddFloatToHash(hash, NormalizeSign(computed_size_));
-  WTF::AddFloatToHash(hash, NormalizeSign(adjusted_size_));
-  WTF::AddFloatToHash(hash, NormalizeSign(letter_spacing_));
-  WTF::AddFloatToHash(hash, NormalizeSign(word_spacing_));
+  WTF::AddFloatToHash(hash, specified_size_);
+  WTF::AddFloatToHash(hash, computed_size_);
+  WTF::AddFloatToHash(hash, adjusted_size_);
+  WTF::AddFloatToHash(hash, letter_spacing_);
+  WTF::AddFloatToHash(hash, word_spacing_);
   WTF::AddIntToHash(hash, fields_as_unsigned_.parts[0]);
   WTF::AddIntToHash(hash, fields_as_unsigned_.parts[1]);
   WTF::AddIntToHash(hash, font_selection_request_.GetHash());
diff --git a/third_party/blink/renderer/platform/fonts/font_palette.cc b/third_party/blink/renderer/platform/fonts/font_palette.cc
index 04c98c0..e7d5bd1b 100644
--- a/third_party/blink/renderer/platform/fonts/font_palette.cc
+++ b/third_party/blink/renderer/platform/fonts/font_palette.cc
@@ -12,28 +12,15 @@
 
 namespace blink {
 
-namespace {
-
-// This converts -0.0 to 0.0, so that they have the same hash value. This
-// ensures that equal FontDescription have the same hash value.
-float NormalizeSign(float number) {
-  if (number == 0.0) [[unlikely]] {
-    return 0.0;
-  }
-  return number;
-}
-
-}  // namespace
-
 unsigned FontPalette::GetHash() const {
   unsigned computed_hash = 0;
   WTF::AddIntToHash(computed_hash, palette_keyword_);
 
   if (palette_keyword_ == kInterpolablePalette) {
-    WTF::AddFloatToHash(computed_hash, NormalizeSign(percentages_.start));
-    WTF::AddFloatToHash(computed_hash, NormalizeSign(percentages_.end));
-    WTF::AddFloatToHash(computed_hash, NormalizeSign(normalized_percentage_));
-    WTF::AddFloatToHash(computed_hash, NormalizeSign(alpha_multiplier_));
+    WTF::AddFloatToHash(computed_hash, percentages_.start);
+    WTF::AddFloatToHash(computed_hash, percentages_.end);
+    WTF::AddFloatToHash(computed_hash, normalized_percentage_);
+    WTF::AddFloatToHash(computed_hash, alpha_multiplier_);
     WTF::AddIntToHash(computed_hash,
                       static_cast<uint8_t>(color_interpolation_space_));
     if (hue_interpolation_method_.has_value()) {
diff --git a/third_party/blink/renderer/platform/fonts/font_size_adjust.cc b/third_party/blink/renderer/platform/fonts/font_size_adjust.cc
index 564d26c..f39d5c4 100644
--- a/third_party/blink/renderer/platform/fonts/font_size_adjust.cc
+++ b/third_party/blink/renderer/platform/fonts/font_size_adjust.cc
@@ -11,8 +11,7 @@
 
 unsigned FontSizeAdjust::GetHash() const {
   unsigned computed_hash = 0;
-  // Normalize negative zero.
-  WTF::AddFloatToHash(computed_hash, value_ == 0.0 ? 0.0 : value_);
+  WTF::AddFloatToHash(computed_hash, value_);
   WTF::AddIntToHash(computed_hash, static_cast<const unsigned>(metric_));
   WTF::AddIntToHash(computed_hash, static_cast<const unsigned>(type_));
   return computed_hash;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
index 73dd725..47d164bb 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -808,6 +808,7 @@
     scoped_refptr<gpu::ClientSharedImage> client_si,
     const viz::TransferableResource& transferable_resource,
     viz::TransferableResource::ResourceSource resource_source,
+    gfx::HDRMetadata hdr_metadata,
     viz::ReleaseCallback release_callback,
     base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
     base::WeakPtr<CanvasResourceProvider> provider) {
@@ -816,8 +817,8 @@
   CHECK(client_si->mailbox() == transferable_resource.mailbox());
   auto resource = AdoptRef(new ExternalCanvasResource(
       std::move(client_si), transferable_resource, resource_source,
-      std::move(release_callback), std::move(context_provider_wrapper),
-      std::move(provider)));
+      hdr_metadata, std::move(release_callback),
+      std::move(context_provider_wrapper), std::move(provider)));
   return resource->IsValid() ? resource : nullptr;
 }
 
@@ -919,7 +920,7 @@
       transferable_resource_.sync_token(), client_si_->size(),
       client_si_->format(), is_overlay_candidate_, resource_source_);
   out_resource->color_space = client_si_->color_space();
-  out_resource->hdr_metadata = transferable_resource_.hdr_metadata;
+  out_resource->hdr_metadata = hdr_metadata_;
   out_resource->origin = client_si_->surface_origin();
 
   return true;
@@ -929,18 +930,20 @@
     scoped_refptr<gpu::ClientSharedImage> client_si,
     const viz::TransferableResource& transferable_resource,
     viz::TransferableResource::ResourceSource resource_source,
+    gfx::HDRMetadata hdr_metadata,
     viz::ReleaseCallback out_callback,
     base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
     base::WeakPtr<CanvasResourceProvider> provider)
     : CanvasResource(std::move(provider),
-                     transferable_resource.size,
-                     transferable_resource.format,
+                     client_si->size(),
+                     client_si->format(),
                      kPremul_SkAlphaType,
-                     transferable_resource.color_space),
+                     client_si->color_space()),
       client_si_(std::move(client_si)),
       context_provider_wrapper_(std::move(context_provider_wrapper)),
       transferable_resource_(transferable_resource),
       resource_source_(resource_source),
+      hdr_metadata_(hdr_metadata),
       is_overlay_candidate_(
           client_si_->usage().Has(gpu::SHARED_IMAGE_USAGE_SCANOUT)),
       release_callback_(std::move(out_callback)) {
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.h b/third_party/blink/renderer/platform/graphics/canvas_resource.h
index e48958b5..00b7bdb 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource.h
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource.h
@@ -448,6 +448,7 @@
       scoped_refptr<gpu::ClientSharedImage> client_si,
       const viz::TransferableResource& transferable_resource,
       viz::TransferableResource::ResourceSource resource_source,
+      gfx::HDRMetadata hdr_metadata,
       viz::ReleaseCallback release_callback,
       base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
       base::WeakPtr<CanvasResourceProvider>);
@@ -483,6 +484,7 @@
       scoped_refptr<gpu::ClientSharedImage> client_si,
       const viz::TransferableResource& transferable_resource,
       viz::TransferableResource::ResourceSource resource_source,
+      gfx::HDRMetadata hdr_metadata,
       viz::ReleaseCallback out_callback,
       base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
       base::WeakPtr<CanvasResourceProvider>);
@@ -492,6 +494,7 @@
       context_provider_wrapper_;
   viz::TransferableResource transferable_resource_;
   viz::TransferableResource::ResourceSource resource_source_;
+  gfx::HDRMetadata hdr_metadata_;
   bool is_overlay_candidate_ = false;
   viz::ReleaseCallback release_callback_;
   bool is_origin_clean_ = true;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc
index e779766b..01dd19cb 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc
@@ -698,7 +698,7 @@
 
   scoped_refptr<ExternalCanvasResource> resource =
       ExternalCanvasResource::Create(client_si, tr, tr.resource_source,
-                                     viz::ReleaseCallback(),
+                                     tr.hdr_metadata, viz::ReleaseCallback(),
                                      SharedGpuContext::ContextProviderWrapper(),
                                      provider->CreateWeakPtr());
 
diff --git a/third_party/blink/renderer/platform/graphics/color.cc b/third_party/blink/renderer/platform/graphics/color.cc
index ab4be4b..67c755e 100644
--- a/third_party/blink/renderer/platform/graphics/color.cc
+++ b/third_party/blink/renderer/platform/graphics/color.cc
@@ -871,21 +871,12 @@
   }
 }
 
-// This converts -0.0 to 0.0, so that they have the same hash value. This
-// ensures that equal FontDescription have the same hash value.
-float NormalizeSign(float number) {
-  if (number == 0.0) [[unlikely]] {
-    return 0.0;
-  }
-  return number;
-}
-
 unsigned Color::GetHash() const {
   unsigned result = WTF::HashInt(static_cast<uint8_t>(color_space_));
-  WTF::AddFloatToHash(result, NormalizeSign(param0_));
-  WTF::AddFloatToHash(result, NormalizeSign(param1_));
-  WTF::AddFloatToHash(result, NormalizeSign(param2_));
-  WTF::AddFloatToHash(result, NormalizeSign(alpha_));
+  WTF::AddFloatToHash(result, param0_);
+  WTF::AddFloatToHash(result, param1_);
+  WTF::AddFloatToHash(result, param2_);
+  WTF::AddFloatToHash(result, alpha_);
   WTF::AddIntToHash(result, param0_is_none_);
   WTF::AddIntToHash(result, param1_is_none_);
   WTF::AddIntToHash(result, param2_is_none_);
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
index cc982c4..ff81117 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -833,8 +833,8 @@
 
   return ExternalCanvasResource::Create(
       color_buffer->shared_image, resource, resource.resource_source,
-      viz::ReleaseCallback(), context_provider_->GetWeakPtr(),
-      resource_provider);
+      resource.hdr_metadata, viz::ReleaseCallback(),
+      context_provider_->GetWeakPtr(), resource_provider);
 }
 
 scoped_refptr<CanvasResource> DrawingBuffer::ExportCanvasResource() {
@@ -859,7 +859,8 @@
   CHECK(client_si);
   return ExternalCanvasResource::Create(
       client_si, out_resource, out_resource.resource_source,
-      std::move(out_release_callback), context_provider_->GetWeakPtr(),
+      out_resource.hdr_metadata, std::move(out_release_callback),
+      context_provider_->GetWeakPtr(),
       /*resource_provider=*/nullptr);
 }
 
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
index 741cf6a..8a9dbdd 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
@@ -303,6 +303,8 @@
   out_resource->color_space =
       current_swap_buffer_->GetSharedImage()->color_space();
   out_resource->hdr_metadata = hdr_metadata_;
+  out_resource->origin =
+      current_swap_buffer_->GetSharedImage()->surface_origin();
 
   // This holds a ref on the SwapBuffers that will keep it alive until the
   // mailbox is released (and while the release callback is running).
diff --git a/third_party/blink/renderer/platform/heap/DEPS b/third_party/blink/renderer/platform/heap/DEPS
index c75bd33..3d141e8 100644
--- a/third_party/blink/renderer/platform/heap/DEPS
+++ b/third_party/blink/renderer/platform/heap/DEPS
@@ -18,6 +18,7 @@
     "+third_party/blink/renderer/platform/instrumentation/histogram.h",
     "+third_party/blink/renderer/platform/instrumentation",
     "+third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h",
+    "+third_party/blink/renderer/platform/language_detection",
     "+third_party/blink/renderer/platform/platform_export.h",
     "+third_party/blink/renderer/platform/runtime_enabled_features.h",
     "+third_party/blink/renderer/platform/scheduler/public",
diff --git a/third_party/blink/renderer/platform/language_detection/DEPS b/third_party/blink/renderer/platform/language_detection/DEPS
index 77669c6..550ffb5 100644
--- a/third_party/blink/renderer/platform/language_detection/DEPS
+++ b/third_party/blink/renderer/platform/language_detection/DEPS
@@ -7,6 +7,8 @@
 
     # Dependencies.
     "+components/language_detection/core",
+    "+components/language_detection/content/renderer",
+    "+third_party/blink/renderer/platform/heap",
     "+third_party/blink/renderer/platform/platform_export.h",
     "+third_party/blink/renderer/platform/wtf",
 ]
diff --git a/third_party/blink/renderer/platform/language_detection/detect.cc b/third_party/blink/renderer/platform/language_detection/detect.cc
deleted file mode 100644
index e3dc485..0000000
--- a/third_party/blink/renderer/platform/language_detection/detect.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/language_detection/detect.h"
-
-#include <map>
-#include <string>
-
-#include "base/functional/callback.h"
-#include "components/language_detection/core/language_detection_model.h"
-#include "components/language_detection/core/language_detection_provider.h"
-#include "third_party/blink/renderer/platform/wtf/functional.h"
-#include "third_party/blink/renderer/platform/wtf/hash_map.h"
-#include "third_party/blink/renderer/platform/wtf/hash_traits.h"
-#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
-
-namespace {
-
-void DetectLanguageWithModel(
-    const WTF::String& text,
-    blink::DetectLanguageCallback on_complete,
-    language_detection::LanguageDetectionModel& model) {
-  if (!model.IsAvailable()) {
-    std::move(on_complete)
-        .Run(base::unexpected(blink::DetectLanguageError::kUnavailable));
-    return;
-  }
-  WTF::String content = text;
-  content.Ensure16Bit();
-  std::vector<language_detection::Prediction> predictions =
-      model.PredictWithScan(
-          std::u16string_view(content.Characters16(), content.length()));
-
-  WTF::Vector<blink::LanguagePrediction> blink_predictions;
-  blink_predictions.ReserveInitialCapacity(
-      static_cast<wtf_size_t>(predictions.size()));
-  for (const auto& it : predictions) {
-    blink_predictions.emplace_back(it.language, it.score);
-  }
-  std::move(on_complete).Run(std::move(blink_predictions));
-}
-
-}  // namespace
-
-namespace blink {
-
-void DetectLanguage(const WTF::String& text,
-                    DetectLanguageCallback on_complete) {
-  auto& model = language_detection::GetLanguageDetectionModel();
-  model.AddOnModelLoadedCallback(
-      WTF::BindOnce(DetectLanguageWithModel, text, std::move(on_complete)));
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/language_detection/detect.h b/third_party/blink/renderer/platform/language_detection/detect.h
deleted file mode 100644
index fe585a3..0000000
--- a/third_party/blink/renderer/platform/language_detection/detect.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LANGUAGE_DETECTION_DETECT_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LANGUAGE_DETECTION_DETECT_H_
-
-#include "base/functional/callback_forward.h"
-#include "base/types/expected.h"
-#include "components/language_detection/core/language_detection_model.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-enum class DetectLanguageError {
-  // 0 intentionally skipped.
-  // The model was not available for use.
-  kUnavailable = 1,
-};
-
-using LanguagePrediction = language_detection::Prediction;
-using DetectLanguageCallback = base::OnceCallback<void(
-    base::expected<WTF::Vector<LanguagePrediction>, DetectLanguageError>)>;
-// This uses the TFLite model to detect the languages contained in `text`.
-// The model operates on a limited number characters at a time. This function
-// splits `text` into chunks of characters within the limit and averages the
-// model's results across all of the chunks. This has the effect of measuring
-// what fraction of the string is in what language, even though the model was
-// trained on monolingual inputs.
-//
-// This is an asynchronous operation. The result will be passed to the
-// `on_complete` callback.
-PLATFORM_EXPORT void DetectLanguage(const WTF::String& text,
-                                    DetectLanguageCallback on_complete);
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LANGUAGE_DETECTION_DETECT_H_
diff --git a/third_party/blink/renderer/platform/language_detection/language_detection_model.cc b/third_party/blink/renderer/platform/language_detection/language_detection_model.cc
new file mode 100644
index 0000000..2ba01a6
--- /dev/null
+++ b/third_party/blink/renderer/platform/language_detection/language_detection_model.cc
@@ -0,0 +1,88 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/language_detection/language_detection_model.h"
+
+#include <map>
+#include <string>
+#include <string_view>
+
+#include "base/functional/bind.h"
+#include "base/functional/callback.h"
+#include "base/no_destructor.h"
+#include "base/types/expected.h"
+#include "components/language_detection/content/renderer/language_detection_model_manager.h"
+#include "components/language_detection/core/language_detection_model.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
+#include "third_party/blink/public/platform/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/hash_traits.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
+
+namespace {
+
+// Keep one model and one manager, shared across all blink uses.
+// TODO(https://crbug.com/368206184): This will need to change to accommodate
+// workers, as the model is not threadsafe.
+language_detection::LanguageDetectionModelManager&
+GetLanguageDetectionModelManager() {
+  static base::NoDestructor<language_detection::LanguageDetectionModel> model;
+  static base::NoDestructor<language_detection::LanguageDetectionModelManager>
+      instance(*model);
+  return *instance;
+}
+
+}  // namespace
+
+namespace blink {
+
+// static
+void LanguageDetectionModel::Create(
+    const blink::BrowserInterfaceBrokerProxy& interface_broker,
+    CreateLanguageDetectionModelCallback callback) {
+  GetLanguageDetectionModelManager().GetLanguageDetectionModel(
+      interface_broker,
+      WTF::BindOnce(OnModelResponseReceived, std::move(callback)));
+}
+
+void LanguageDetectionModel::OnModelResponseReceived(
+    CreateLanguageDetectionModelCallback callback,
+    language_detection::LanguageDetectionModel* model) {
+  std::move(callback).Run(
+      model ? MaybeModel(MakeGarbageCollected<LanguageDetectionModel>(*model))
+            : base::unexpected(DetectLanguageError::kUnavailable));
+}
+
+LanguageDetectionModel::LanguageDetectionModel(
+    const language_detection::LanguageDetectionModel& language_detection_model)
+    : language_detection_model_(language_detection_model) {}
+
+void LanguageDetectionModel::Trace(Visitor* visitor) const {}
+
+void LanguageDetectionModel::DetectLanguage(
+    const WTF::String& text,
+    DetectLanguageCallback on_complete) {
+  if (!language_detection_model_->IsAvailable()) {
+    std::move(on_complete)
+        .Run(base::unexpected(blink::DetectLanguageError::kUnavailable));
+    return;
+  }
+  WTF::String text_16 = text;
+  text_16.Ensure16Bit();
+  auto score_by_language = language_detection_model_->PredictWithScan(
+      std::u16string_view(text_16.Characters16(), text_16.length()));
+
+  WTF::Vector<LanguagePrediction> predictions;
+  predictions.reserve(static_cast<wtf_size_t>(score_by_language.size()));
+  for (const auto& it : score_by_language) {
+    predictions.emplace_back(it.language, it.score);
+  }
+  std::move(on_complete).Run(predictions);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/platform/language_detection/language_detection_model.h b/third_party/blink/renderer/platform/language_detection/language_detection_model.h
new file mode 100644
index 0000000..515fde3
--- /dev/null
+++ b/third_party/blink/renderer/platform/language_detection/language_detection_model.h
@@ -0,0 +1,79 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LANGUAGE_DETECTION_LANGUAGE_DETECTION_MODEL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LANGUAGE_DETECTION_LANGUAGE_DETECTION_MODEL_H_
+
+#include "base/functional/callback_forward.h"
+#include "base/memory/raw_ref.h"
+#include "base/types/expected.h"
+#include "components/language_detection/core/language_detection_model.h"
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class BrowserInterfaceBrokerProxy;
+
+enum class DetectLanguageError {
+  // 0 intentionally skipped.
+  // The model was not available for use.
+  kUnavailable = 1,
+};
+
+// Manages getting and holding a language detection model.
+//
+// Use this by calling `Create` and waiting for the callback to be called.
+// If a model is returned, at that point it can be used to detect language.
+class PLATFORM_EXPORT LanguageDetectionModel
+    : public GarbageCollected<LanguageDetectionModel> {
+ public:
+  using MaybeModel =
+      base::expected<LanguageDetectionModel*, DetectLanguageError>;
+  using CreateLanguageDetectionModelCallback =
+      base::OnceCallback<void(MaybeModel)>;
+
+  // Creates an instance and passes it to `callback` when the model has been
+  // loaded (or we know that it will fail to load). `interface_broker` can be
+  // used to communicate with the browser to find the model.
+  static void Create(const blink::BrowserInterfaceBrokerProxy& interface_broker,
+                     CreateLanguageDetectionModelCallback callback);
+
+  // Public for `MakeGarbageCollected`, use `Create` instead.
+  explicit LanguageDetectionModel(
+      const language_detection::LanguageDetectionModel&
+          language_detection_model);
+
+  void Trace(Visitor* visitor) const;
+
+  using LanguagePrediction = language_detection::Prediction;
+  using DetectLanguageCallback = base::OnceCallback<void(
+      base::expected<WTF::Vector<LanguagePrediction>, DetectLanguageError>)>;
+
+  // Detects the language(s) used in the string using the TFLite model on the
+  // whole string.
+  //
+  // This is an asynchronous operation. The result will be passed to the
+  // `on_complete` callback.
+  void DetectLanguage(const WTF::String& text,
+                      DetectLanguageCallback on_complete);
+
+ private:
+  // `Create` passes this to be called with the result of requesting a model.
+  // It will call `callback` with the appropriate value based on the response.
+  static void OnModelResponseReceived(
+      CreateLanguageDetectionModelCallback callback,
+      language_detection::LanguageDetectionModel* model);
+
+  // This model is shared across all execution contexts in the process.
+  const raw_ref<const language_detection::LanguageDetectionModel>
+      language_detection_model_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LANGUAGE_DETECTION_LANGUAGE_DETECTION_MODEL_H_
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 7a29a51..8a60a6c 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -712,6 +712,11 @@
       status: "experimental",
     },
     {
+      // https://crbug.com/377325952
+      name: "CanvasInterventions",
+      browser_process_read_write_access: true,
+    },
+    {
       // https://github.com/Igalia/explainers/blob/main/canvas-formatted-text/html-in-canvas.md
       name: "CanvasPlaceElement",
       status: "experimental",
@@ -916,12 +921,6 @@
       name: "CorsRFC1918",
     },
     {
-      // Controls whether form elements may delay editor creation until layout.
-      // This is a kill switch. See https://crbug.com/325613706 for details.
-      name: "CreateInputShadowTreeDuringLayout",
-      status: "stable"
-    },
-    {
       // Allow WebAuthn relying parties to report information about existing
       // credentials back to credential storage providers.
       // Enabled by default on M132. Remove flag on or after M135.
@@ -2263,6 +2262,12 @@
       name: "HTMLEmbedElementNotForceLayout",
       status: "stable",
     },
+    // The width attribute on the hr element, previously converted 0 values to 1px.
+    // This will ship in M133, so should be safe to remove in M135.
+    {
+      name: "HTMLHRWidthAllowZero",
+      status: "stable"
+    },
     // Adds support for the experimental `interesttarget`
     // attributes, as specified in the open-ui "Interest Invokers" explainer.
     // https://open-ui.org/components/interest-invokers.explainer/
diff --git a/third_party/blink/renderer/platform/wtf/bloom_filter.h b/third_party/blink/renderer/platform/wtf/bloom_filter.h
index 1d355aaa..95d2d29 100644
--- a/third_party/blink/renderer/platform/wtf/bloom_filter.h
+++ b/third_party/blink/renderer/platform/wtf/bloom_filter.h
@@ -140,108 +140,6 @@
   bit_array_[BitArrayIndex(key)] |= BitMask(key);
 }
 
-// Counting bloom filter with k=2 and 8 bit counters. Uses 2^keyBits bytes of
-// memory.  False positive rate is approximately (1-e^(-2n/m))^2, where n is
-// the number of unique keys and m is the table size (==2^keyBits).
-template <unsigned keyBits>
-class CountingBloomFilter {
-  USING_FAST_MALLOC(CountingBloomFilter);
-
- public:
-  static_assert(keyBits <= 16, "bloom filter key size check");
-
-  static const size_t kTableSize = 1 << keyBits;
-  static const unsigned kKeyMask = (1 << keyBits) - 1;
-  static uint8_t MaximumCount() { return std::numeric_limits<uint8_t>::max(); }
-
-  CountingBloomFilter() { Clear(); }
-
-  void Add(unsigned hash);
-  void Remove(unsigned hash);
-
-  // The filter may give false positives (claim it may contain a key it doesn't)
-  // but never false negatives (claim it doesn't contain a key it does).
-  bool MayContain(unsigned hash) const {
-    return FirstSlot(hash) && SecondSlot(hash);
-  }
-
-  // The filter must be cleared before reuse even if all keys are removed.
-  // Otherwise overflowed keys will stick around.
-  void Clear();
-
-#if DCHECK_IS_ON()
-  // Slow.
-  bool LikelyEmpty() const;
-  bool IsClear() const;
-#endif
-
- private:
-  uint8_t& FirstSlot(unsigned hash) { return table_[hash & kKeyMask]; }
-  uint8_t& SecondSlot(unsigned hash) { return table_[(hash >> 16) & kKeyMask]; }
-  const uint8_t& FirstSlot(unsigned hash) const {
-    return table_[hash & kKeyMask];
-  }
-  const uint8_t& SecondSlot(unsigned hash) const {
-    return table_[(hash >> 16) & kKeyMask];
-  }
-
-  uint8_t table_[kTableSize];
-};
-
-template <unsigned keyBits>
-inline void CountingBloomFilter<keyBits>::Add(unsigned hash) {
-  uint8_t& first = FirstSlot(hash);
-  uint8_t& second = SecondSlot(hash);
-  if (first < MaximumCount()) [[likely]] {
-    ++first;
-  }
-  if (second < MaximumCount()) [[likely]] {
-    ++second;
-  }
-}
-
-template <unsigned keyBits>
-inline void CountingBloomFilter<keyBits>::Remove(unsigned hash) {
-  uint8_t& first = FirstSlot(hash);
-  uint8_t& second = SecondSlot(hash);
-  DCHECK(first);
-  DCHECK(second);
-  // In case of an overflow, the slot sticks in the table until clear().
-  if (first < MaximumCount()) [[likely]] {
-    --first;
-  }
-  if (second < MaximumCount()) [[likely]] {
-    --second;
-  }
-}
-
-template <unsigned keyBits>
-inline void CountingBloomFilter<keyBits>::Clear() {
-  memset(table_, 0, kTableSize);
-}
-
-#if DCHECK_IS_ON()
-template <unsigned keyBits>
-bool CountingBloomFilter<keyBits>::LikelyEmpty() const {
-  for (size_t n = 0; n < kTableSize; ++n) {
-    if (table_[n] && table_[n] != MaximumCount())
-      return false;
-  }
-  return true;
-}
-
-template <unsigned keyBits>
-bool CountingBloomFilter<keyBits>::IsClear() const {
-  for (size_t n = 0; n < kTableSize; ++n) {
-    if (table_[n])
-      return false;
-  }
-  return true;
-}
-#endif
-
 }  // namespace WTF
 
-using WTF::CountingBloomFilter;
-
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_BLOOM_FILTER_H_
diff --git a/third_party/blink/renderer/platform/wtf/hash_functions.h b/third_party/blink/renderer/platform/wtf/hash_functions.h
index 42345eb..8757218 100644
--- a/third_party/blink/renderer/platform/wtf/hash_functions.h
+++ b/third_party/blink/renderer/platform/wtf/hash_functions.h
@@ -22,6 +22,8 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_HASH_FUNCTIONS_H_
 
 #include <stdint.h>
+
+#include <concepts>
 #include <type_traits>
 
 #include "base/bit_cast.h"
@@ -56,7 +58,7 @@
 
 // Thomas Wang's 32 Bit Mix Function:
 // https://web.archive.org/web/20060507103516/http://www.cris.com/~Ttwang/tech/inthash.htm
-inline unsigned HashInt(uint32_t key) {
+constexpr unsigned HashInt(uint32_t key) {
   key += ~(key << 15);
   key ^= (key >> 10);
   key += (key << 3);
@@ -66,19 +68,19 @@
   return key;
 }
 
-inline unsigned HashInt(uint16_t key16) {
+constexpr unsigned HashInt(uint16_t key16) {
   uint32_t key = key16;
   return HashInt(key);
 }
 
-inline unsigned HashInt(uint8_t key8) {
+constexpr unsigned HashInt(uint8_t key8) {
   uint32_t key = key8;
   return HashInt(key);
 }
 
 // Thomas Wang's 64 bit Mix Function:
 // https://web.archive.org/web/20060507103516/http://www.cris.com/~Ttwang/tech/inthash.htm
-inline unsigned HashInt(uint64_t key) {
+constexpr unsigned HashInt(uint64_t key) {
   key += ~(key << 32);
   key ^= (key >> 22);
   key += ~(key << 13);
@@ -94,7 +96,7 @@
 
 // Compound integer hash method:
 // http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000
-inline unsigned HashInts(unsigned key1, unsigned key2) {
+constexpr unsigned HashInts(unsigned key1, unsigned key2) {
   unsigned short_random1 = 277951225;          // A random 32-bit value.
   unsigned short_random2 = 95187966;           // A random 32-bit value.
   uint64_t long_random = 19248658165952623LL;  // A random, odd 64-bit value.
@@ -107,35 +109,45 @@
 }
 
 template <typename T>
-unsigned HashInt(T key) {
-  static_assert(std::is_integral_v<T> || std::is_enum_v<T>);
+  requires(std::integral<T> || std::is_enum_v<T>)
+constexpr unsigned HashInt(T key) {
   return internal::HashInt(static_cast<internal::IntHashBits<T>>(key));
 }
 
 template <typename T>
-unsigned HashFloat(T key) {
-  static_assert(std::is_floating_point_v<T>);
-  return internal::HashInt(base::bit_cast<internal::IntHashBits<T>>(key));
+  requires std::floating_point<T>
+constexpr T NormalizeSign(T number) {
+  // Converts -0.0 to 0.0, so that they have the same hash value.
+  return number + T{0};
 }
 
 template <typename T>
-bool FloatEqualForHash(T a, T b) {
-  static_assert(std::is_floating_point_v<T>);
-  return base::bit_cast<internal::IntHashBits<T>>(a) ==
-         base::bit_cast<internal::IntHashBits<T>>(b);
+  requires std::floating_point<T>
+constexpr unsigned HashFloat(T key) {
+  return internal::HashInt(
+      base::bit_cast<internal::IntHashBits<T>>(NormalizeSign(key)));
 }
 
 template <typename T>
-unsigned HashPointer(T* key) {
+  requires std::floating_point<T>
+constexpr bool FloatEqualForHash(T a, T b) {
+  return base::bit_cast<internal::IntHashBits<T>>(NormalizeSign(a)) ==
+         base::bit_cast<internal::IntHashBits<T>>(NormalizeSign(b));
+}
+
+template <typename T>
+inline unsigned HashPointer(T* key) {
   return HashInt(reinterpret_cast<internal::IntHashBits<T*>>(key));
 }
 
 // Useful compounding hash functions.
-inline void AddIntToHash(unsigned& hash, unsigned key) {
+constexpr void AddIntToHash(unsigned& hash, unsigned key) {
   hash = ((hash << 5) + hash) + key;  // Djb2
 }
 
-inline void AddFloatToHash(unsigned& hash, float value) {
+// Normalizes -0.0 to +0.0 to reduce risk of hash and value comparisons
+// mismatching.
+constexpr void AddFloatToHash(unsigned& hash, float value) {
   AddIntToHash(hash, HashFloat(value));
 }
 
diff --git a/third_party/blink/renderer/platform/wtf/hash_map_test.cc b/third_party/blink/renderer/platform/wtf/hash_map_test.cc
index 90c5975..6ba29d2 100644
--- a/third_party/blink/renderer/platform/wtf/hash_map_test.cc
+++ b/third_party/blink/renderer/platform/wtf/hash_map_test.cc
@@ -90,37 +90,6 @@
   EXPECT_EQ((1 << 10) - 1, encountered_keys);
 }
 
-struct TestDoubleHashTraits : HashTraits<double> {
-  static const unsigned kMinimumTableSize = 8;
-};
-
-using DoubleHashMap = HashMap<double, int64_t, TestDoubleHashTraits>;
-
-int BucketForKey(double key) {
-  return WTF::GetHash(key) & (TestDoubleHashTraits::kMinimumTableSize - 1);
-}
-
-TEST(HashMapTest, DoubleHashCollisions) {
-  // The "clobber" key here is one that ends up stealing the bucket that the -0
-  // key originally wants to be in. This makes the 0 and -0 keys collide and
-  // the test then fails unless the FloatHash::equals() implementation can
-  // distinguish them.
-  const double kClobberKey = 6;
-  const double kZeroKey = 0;
-  const double kNegativeZeroKey = -kZeroKey;
-
-  DoubleHashMap map;
-
-  map.insert(kClobberKey, 1);
-  map.insert(kZeroKey, 2);
-  map.insert(kNegativeZeroKey, 3);
-
-  EXPECT_EQ(BucketForKey(kClobberKey), BucketForKey(kNegativeZeroKey));
-  EXPECT_EQ(1, map.at(kClobberKey));
-  EXPECT_EQ(2, map.at(kZeroKey));
-  EXPECT_EQ(3, map.at(kNegativeZeroKey));
-}
-
 using OwnPtrHashMap = HashMap<int, std::unique_ptr<DestructCounter>>;
 
 TEST(HashMapTest, OwnPtrAsValue) {
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
index 86df118..ef48a26 100755
--- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
+++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -2517,8 +2517,7 @@
             or basename.endswith('_test') or basename.endswith('_test_helpers')
             or basename.endswith('_test_utils')
             or basename.endswith('_unittest') or basename.endswith('_fuzzer')
-            or basename.endswith('_perftest')
-            or basename.endswith('_fuzztest')):
+            or basename.endswith('_perftest')):
         return results
     entries = _find_matching_entries(path)
     if not entries:
diff --git a/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder.py b/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder.py
index c718847..875de17 100644
--- a/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder.py
+++ b/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder.py
@@ -32,11 +32,12 @@
 import json
 import logging
 import re
+from collections import OrderedDict, defaultdict
+from typing import Collection, Mapping, NamedTuple, Optional, Sequence, Set, Tuple
 
 from blinkpy.web_tests.layout_package.json_results_generator import convert_times_trie_to_flat_paths
 from blinkpy.web_tests.models.typ_types import ResultType
 from blinkpy.web_tests.port.base import Port
-from collections import OrderedDict
 
 _log = logging.getLogger(__name__)
 
@@ -369,53 +370,27 @@
 
     A test will be run only if it passes every filter.
     """
-
-    def glob_sort_key(k):
-        if k and k[0] == '-':
-            return (len(k[1:]), k[1:])
-        elif k and k[0] == '+':
-            return (len(k[1:]), k[1:])
-        else:
-            return (len(k), k)
-
     for terms in filters:
-        # Validate the filter
-        for term in terms:
-            if (term.startswith('-') and not term[1:]) or not term:
-                raise ValueError('Empty filter entry "%s"' % (term, ))
-            for i, c in enumerate(term):
-                if i == len(term) - 1:
-                    continue
-                if c == '*' and (i == 0 or term[i - 1] != '\\'):
-                    raise ValueError('Bad test filter "%s" specified; '
-                                     'unescaped wildcards are only allowed at '
-                                     'the end' % (term, ))
-            if term.startswith('-') and term[1:] in terms:
-                raise ValueError('Both "%s" and "%s" specified in test '
-                                 'filter' % (term, term[1:]))
-
-        # Separate the negative/positive globless terms and glob terms
-        include_by_default = all(term.startswith('-') for term in terms)
-        exact_neg_terms, exact_pos_terms, glob_terms = _extract_terms(terms)
+        # Although `FilterTrie` also happens to support exact terms, it's
+        # slower than simply checking for membership in a set of test names, so
+        # partition the terms into exact/glob.
+        exact_pos_terms, exact_neg_terms, glob_terms = _extract_terms(terms)
+        include_by_default = not exact_pos_terms and not any(
+            include for _, include in glob_terms)
+        glob_trie = FilterTrie.from_terms(glob_terms)
 
         filtered_tests = []
         for test in tests:
-            # Check for the exact test name
             if test in exact_neg_terms:
                 continue
             if test in exact_pos_terms:
                 filtered_tests.append(test)
                 continue
 
-            # Check globs, this could be done with a trie to avoid this loop
-            # but glob terms should be lower volume than exact terms
-            include = include_by_default
-            for glob in sorted(glob_terms, key=glob_sort_key):
-                if glob.startswith('-'):
-                    include = include and not fnmatch.fnmatch(test, glob[1:])
-                else:
-                    include = include or fnmatch.fnmatch(
-                        test, glob[1:] if glob[0] == '+' else glob)
+            include = glob_trie.should_include(
+                test.split(Port.TEST_PATH_SEPARATOR))
+            if include is None:
+                include = include_by_default
             if include:
                 filtered_tests.append(test)
         tests = filtered_tests
@@ -423,29 +398,114 @@
     return tests
 
 
-def _extract_terms(filter):
+ParsedTerm = Tuple[str, bool]
+
+
+class FilterTrie(NamedTuple):
+    children: Mapping[str, 'FilterTrie']
+    # `None` indicates no term terminates at this node.
+    include: Optional[bool] = None
+
+    @classmethod
+    def from_terms(cls, terms: Collection[ParsedTerm]) -> 'FilterTrie':
+        include_for_trie, child_terms_by_next_part = None, defaultdict(list)
+        for test, include in terms:
+            next_part, _, rest = test.partition(Port.TEST_PATH_SEPARATOR)
+            if next_part:
+                child_terms_by_next_part[next_part].append((rest, include))
+            else:
+                assert include_for_trie is None, 'contradictory terms'
+                include_for_trie = include
+
+        # Pre-sort the children so that `should_include()` honors the
+        # longest-glob-wins rule.
+        children = OrderedDict()
+        for next_part in sorted(child_terms_by_next_part,
+                                key=_remove_glob,
+                                reverse=True):
+            children[next_part] = cls.from_terms(
+                child_terms_by_next_part[next_part])
+        return cls(children, include_for_trie)
+
+    def should_include(self, test_parts: Sequence[str]) -> Optional[bool]:
+        """Determine whether a test should run or not.
+
+        Arguments:
+            test_parts: The path components of the test. URL query parameters
+                should be attached to the last component.
+
+        Returns:
+            Whether the test should be included. If `None`, there's no
+            definitive answer because no terms matched.
+        """
+        if not test_parts:
+            # Exact match found when all path parts have been exhausted.
+            return self.include
+        next_part, *rest = test_parts
+        if child := self.children.get(next_part):
+            # Look for the rest of an exact match or more specific glob, which
+            # always beats this node's glob (or that of one of its ancestors).
+            if (include := child.should_include(rest)) is not None:
+                return include
+        # If there's no exact match for a child directory/test, there can
+        # still be a glob match at this directory.
+        for maybe_glob, child in self.children.items():
+            if maybe_glob.endswith('*') and next_part.startswith(
+                    _remove_glob(maybe_glob)):
+                assert child.include is not None, 'glob must terminate term'
+                return child.include
+        return None
+
+
+def _extract_terms(
+        terms: Collection[str]) -> Tuple[Set[str], Set[str], Set[ParsedTerm]]:
     """Extract terms of the filter into exact +/- terms and glob terms.
 
     The +/- prefix char for exact terms will also be stripped as they are no
     longer needed to identify the term as a positive or negative filter. Any
     prefix in globbed terms (terms with a *) will preserve the sign.
     """
-    exact_negative_terms = set()
-    exact_positive_terms = set()
-    glob_terms = set()
-    for term in filter:
-        is_glob = False
-        for i, c in enumerate(term):
-            if c == '*' and (i == 0 or term[i - 1] != '\\'):
-                glob_terms.add(term)
-                is_glob = True
-                break
-        if is_glob:
-            continue
-        elif term[0] == '-':
-            exact_negative_terms.add(term[1:])
-        elif term[0] == '+':
-            exact_positive_terms.add(term[1:])
+    exact_pos_terms, exact_neg_terms, glob_terms = set(), set(), set()
+    for term in terms:
+        test, include = _strip_sign(term)
+        if not test:
+            raise ValueError(f'Empty filter entry {term!r}')
+        if _has_illegal_wildcard(test):
+            raise ValueError(f'Bad test filter {term!r} specified; '
+                             'unescaped wildcards are only allowed at the end')
+
+        if test.endswith('*'):
+            glob_terms.add((test, include))
+        elif include:
+            exact_pos_terms.add(test)
         else:
-            exact_positive_terms.add(term)
-    return exact_negative_terms, exact_positive_terms, list(glob_terms)
+            exact_neg_terms.add(test)
+
+    contradictory_terms = (exact_pos_terms & exact_neg_terms) | {
+        test
+        for test, include in glob_terms if (test, not include) in glob_terms
+    }
+    if test := next(iter(contradictory_terms), None):
+        raise ValueError(
+            f'Both "+{test}" and "-{test}" specified in test filter')
+    return exact_pos_terms, exact_neg_terms, glob_terms
+
+
+def _strip_sign(term: str) -> ParsedTerm:
+    if term.startswith('-'):
+        return term[len('-'):], False
+    elif term.startswith('+'):
+        return term[len('+'):], True
+    return term, True
+
+
+def _remove_glob(test: str) -> str:
+    return test[:-len('*')] if test.endswith('*') else test
+
+
+def _has_illegal_wildcard(term: str) -> bool:
+    # Remove any legal wildcard and add an initial dummy character, which fails
+    # terms starting with `*` that aren't just `*`.
+    term = ' ' + _remove_glob(term)
+    return any(prev != '\\' and char == '*'
+               for prev, char in zip(term[:-1], term[1:]))
diff --git a/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder_unittest.py b/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder_unittest.py
index 39f97f7..dea1562c 100644
--- a/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder_unittest.py
@@ -4,10 +4,12 @@
 
 import optparse
 import unittest
+from collections import OrderedDict
 
 from blinkpy.common.host_mock import MockHost
 from blinkpy.common.system.filesystem_mock import MockFileSystem
 from blinkpy.web_tests.controllers import web_test_finder
+from blinkpy.web_tests.controllers.web_test_finder import FilterTrie
 from blinkpy.web_tests.models import test_expectations
 
 
@@ -412,3 +414,72 @@
             self.check([], [['a/*', '-a/*']], [])
         # This is allowed, but maybe it shouldn't be?
         self.check([], [['a/a.html', '+a/a.html']], [])
+
+
+class FilterTrieTests(unittest.TestCase):
+    """Additional coverage for the internal structure of `FilterTrie`."""
+
+    def test_exact_test(self):
+        trie = FilterTrie.from_terms([('a/b/c.html', False),
+                                      ('a/b/d.html', True),
+                                      ('a/e.html', False)])
+        expected_trie = FilterTrie({
+            'a':
+            FilterTrie({
+                'b':
+                FilterTrie({
+                    'c.html': FilterTrie({}, False),
+                    'd.html': FilterTrie({}, True),
+                }),
+                'e.html':
+                FilterTrie({}, False),
+            }),
+        })
+
+        self.assertEqual(expected_trie, trie)
+        self.assertFalse(trie.should_include(['a', 'b', 'c.html']))
+        self.assertTrue(trie.should_include(['a', 'b', 'd.html']))
+        self.assertFalse(trie.should_include(['a', 'e.html']))
+        self.assertIsNone(trie.should_include(['a', 'f.html']))
+
+    def test_glob(self):
+        trie = FilterTrie.from_terms([('a/b*', True), ('*', False)])
+        expected_trie = FilterTrie(
+            OrderedDict([
+                ('a', FilterTrie({
+                    'b*': FilterTrie({}, True),
+                })),
+                ('*', FilterTrie({}, False)),
+            ]))
+
+        self.assertEqual(expected_trie, trie)
+        self.assertTrue(trie.should_include(['a', 'b-c.html']))
+        self.assertTrue(trie.should_include(['a', 'b', 'd.html']))
+        self.assertFalse(trie.should_include(['a', 'e.html']))
+
+    def test_exact_test_overrides_glob(self):
+        trie = FilterTrie.from_terms([('a-b.html', False), ('a*', True)])
+        expected_trie = FilterTrie(
+            OrderedDict([
+                ('a-b.html', FilterTrie({}, False)),
+                ('a*', FilterTrie({}, True)),
+            ]))
+
+        self.assertEqual(expected_trie, trie)
+        self.assertFalse(trie.should_include(['a-b.html']))
+        self.assertTrue(trie.should_include(['a-c.html']))
+        self.assertIsNone(trie.should_include(['b.html']))
+
+    def test_special_characters(self):
+        trie = FilterTrie.from_terms([('a.html?b&c*', True),
+                                      ('a.html?b*', False)])
+        expected_trie = FilterTrie(
+            OrderedDict([
+                ('a.html?b&c*', FilterTrie({}, True)),
+                ('a.html?b*', FilterTrie({}, False)),
+            ]))
+
+        self.assertEqual(expected_trie, trie)
+        self.assertTrue(trie.should_include(['a.html?b&c']))
+        self.assertTrue(trie.should_include(['a.html?b&c&d']))
+        self.assertFalse(trie.should_include(['a.html?b']))
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests
index c098760..ac60238 100644
--- a/third_party/blink/web_tests/SlowTests
+++ b/third_party/blink/web_tests/SlowTests
@@ -1452,7 +1452,6 @@
 crbug.com/369600187 external/wpt/css/css-anchor-position/anchor-size-parse-valid.html [ Slow ]
 
 # Flaky timeouts - assuming the tests are slow.
-crbug.com/369200429 fast/events/touch/gesture/gesture-tap-hover-clear.html [ Slow ]
 crbug.com/374035637 [ Debug Mac14 ] fast/css-grid-layout/grid-auto-repeat-huge-grid-004.html [ Slow ]
 crbug.com/374035637 [ Debug Mac14 ] fast/css-grid-layout/grid-auto-repeat-huge-grid-010.html [ Slow ]
 crbug.com/374035637 [ Debug Mac14 ] fast/css-grid-layout/grid-auto-repeat-huge-grid-016.html [ Slow ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index c14ce38..d55d786 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2689,9 +2689,19 @@
 crbug.com/343720396 external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-unsafe-none.https.html?1-2 [ Crash Failure Timeout ]
 
 # ====== New tests from wpt-importer added here ======
+external/wpt/css/css-rhythm/replaced-elements/block-level-canvas-margins-affected-by-block-step-size.html [ Failure ]
+external/wpt/css/css-rhythm/replaced-elements/block-level-embed-margins-affected-by-block-step-size.html [ Failure ]
+external/wpt/css/css-rhythm/replaced-elements/block-level-iframe-margins-affected-by-block-step-size.html [ Failure ]
+external/wpt/css/css-rhythm/replaced-elements/block-level-img-margins-affected-by-block-step-size.html [ Failure ]
+external/wpt/css/css-rhythm/replaced-elements/block-level-object-margins-affected-by-block-step-size.html [ Failure ]
+external/wpt/css/css-rhythm/replaced-elements/block-level-svg-margins-affected-by-block-step-size.html [ Failure ]
+external/wpt/css/css-rhythm/replaced-elements/block-level-video-margins-affected-by-block-step-size.html [ Failure ]
+[ Mac14 ] external/wpt/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-unsafe-none.https.html?5-6 [ Crash Failure ]
+[ Mac15 ] external/wpt/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-unsafe-none.https.html?5-6 [ Crash Failure ]
 crbug.com/382953502 external/wpt/webrtc/simulcast/setParameters-maxFramerate.https.html [ Skip Timeout ]
 crbug.com/382552065 [ Mac13 ] external/wpt/css/css-writing-modes/abs-pos-replaced-vrl-001.html [ Failure ]
 crbug.com/382552065 [ Mac14 ] external/wpt/css/css-writing-modes/abs-pos-replaced-vrl-001.html [ Failure ]
+[ Linux ] wpt_internal/css/css-images/img-view-box-contents-opaque.html [ Failure ]
 [ Mac13 ] wpt_internal/css/css-images/img-view-box-contents-opaque.html [ Failure ]
 [ Mac14 ] wpt_internal/css/css-images/img-view-box-contents-opaque.html [ Failure ]
 crbug.com/382547589 [ Mac13 ] external/wpt/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-unsafe-none.https.html?1-2 [ Crash ]
@@ -2828,6 +2838,8 @@
 crbug.com/377942353 [ Win10.20h2 ] external/wpt/signed-exchange/reporting/sxg-reporting-navigation-failed-zero-success-fraction.tentative.html [ Crash Failure Timeout ]
 crbug.com/377942353 [ Mac13 ] external/wpt/webrtc-encoded-transform/tentative/RTCEncodedAudioFrame-clone.https.html [ Timeout ]
 crbug.com/377942353 [ Mac13 ] external/wpt/webrtc-encoded-transform/tentative/RTCPeerConnection-insertable-streams-video-frames.https.html [ Timeout ]
+crbug.com/377942353 [ Mac14 ] external/wpt/webrtc-encoded-transform/tentative/RTCPeerConnection-insertable-streams-video-frames.https.html [ Timeout ]
+crbug.com/377942353 [ Mac15 ] external/wpt/webrtc-encoded-transform/tentative/RTCPeerConnection-insertable-streams-video-frames.https.html [ Timeout ]
 crbug.com/379008005 [ Mac15 ] external/wpt/webrtc/protocol/unknown-mediatypes.html [ Timeout ]
 crbug.com/377942353 [ Win10.20h2 ] virtual/split-http-cache/external/wpt/signed-exchange/reporting/sxg-reporting-navigation-signature_verification_error-downgraded.tentative.html [ Crash Timeout ]
 crbug.com/378750944 [ Win10.20h2 ] external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator_user_agent.tentative.html [ Crash Timeout ]
@@ -2989,6 +3001,7 @@
 crbug.com/366307017 [ Linux ] external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cues-enter-exit.html [ Failure Pass ]
 [ Mac15 ] external/wpt/html/browsers/history/the-location-interface/location_hash_set_empty_string.html [ Failure Timeout ]
 [ Win11-arm64 ] external/wpt/html/browsers/history/the-location-interface/location_hash_set_empty_string.html [ Failure Pass Timeout ]
+crbug.com/364935894 [ Mac13 ] external/wpt/webrtc-encoded-transform/RTCRtpScriptTransform-encoded-transform.https.html [ Timeout ]
 crbug.com/364935894 [ Mac14 ] external/wpt/webrtc-encoded-transform/RTCRtpScriptTransform-encoded-transform.https.html [ Timeout ]
 crbug.com/364935894 [ Mac12 ] external/wpt/webrtc-encoded-transform/RTCRtpScriptTransform-encoded-transform.https.html [ Timeout ]
 [ Linux ] wpt_internal/html/semantics/forms/the-select-element/customizable-select/select-only-picker-opt-in.tentative.html [ Failure ]
@@ -7987,6 +8000,7 @@
 crbug.com/356930166 [ Mac15 ] external/wpt/webrtc-svc/RTCRtpParameters-scalability-vp8.html [ Skip Timeout ]
 crbug.com/356930166 [ Mac15 ] external/wpt/webrtc-svc/RTCRtpParameters-scalability-vp9.html [ Skip Timeout ]
 crbug.com/356930166 [ Mac13 ] external/wpt/webrtc/getstats.html [ Timeout ]
+crbug.com/356930166 [ Mac14 ] external/wpt/webrtc/getstats.html [ Timeout ]
 crbug.com/356930166 [ Mac15 ] external/wpt/webrtc/getstats.html [ Timeout ]
 crbug.com/356930166 [ Mac15 ] external/wpt/webrtc/idlharness.https.window.html [ Skip Timeout ]
 crbug.com/356930166 [ Mac13 ] external/wpt/webrtc/legacy/simplecall_callbacks.https.html [ Timeout ]
@@ -8611,7 +8625,6 @@
 crbug.com/363353213 [ Mac11 ] external/wpt/webrtc-encoded-transform/RTCRtpScriptTransform-encoded-transform.https.html [ Failure Pass ]
 crbug.com/363353213 [ Mac11-arm64 ] external/wpt/webrtc-encoded-transform/RTCRtpScriptTransform-encoded-transform.https.html [ Failure Pass ]
 crbug.com/363353213 [ Mac12-arm64 ] external/wpt/webrtc-encoded-transform/RTCRtpScriptTransform-encoded-transform.https.html [ Failure Pass ]
-crbug.com/363353213 [ Mac13 ] external/wpt/webrtc-encoded-transform/RTCRtpScriptTransform-encoded-transform.https.html [ Failure Pass ]
 crbug.com/363353213 [ Mac13-arm64 ] external/wpt/webrtc-encoded-transform/RTCRtpScriptTransform-encoded-transform.https.html [ Failure Pass ]
 crbug.com/363353213 [ Mac14-arm64 ] external/wpt/webrtc-encoded-transform/RTCRtpScriptTransform-encoded-transform.https.html [ Failure Pass ]
 crbug.com/363353213 [ Mac15 ] external/wpt/webrtc-encoded-transform/RTCRtpScriptTransform-encoded-transform.https.html [ Failure Pass ]
@@ -8882,3 +8895,6 @@
 
 # Gardener 2024-12-06
 crbug.com/382519579 [ Linux ] external/wpt/long-animation-frame/tentative/loaf-script-window-attribution.html [ Failure Pass ]
+
+crbug.com/383105114 [ Linux ] tables/mozilla/bugs/bug78162.html [ Failure Pass ]
+crbug.com/383105114 [ Win ] tables/mozilla/bugs/bug78162.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 44a511f..c7da63b 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -822,9 +822,7 @@
   {
     "prefix": "fluent-non-overlay-scrollbar",
     "platforms": ["Linux", "Win"],
-    "bases": ["fast/scrolling/scrollbars",
-              "external/wpt/css/css-scrollbars",
-              "scrollbars/scaled-rendering"],
+    "bases": ["fast/scrolling/scrollbars", "external/wpt/css/css-scrollbars"],
     "args": ["--enable-features=FluentScrollbar",
              "--enable-threaded-compositing"],
     "expires": "Jul 1, 2025",
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index 91ba278..235c623 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -177809,6 +177809,99 @@
        {}
       ]
      ],
+     "replaced-elements": {
+      "block-level-canvas-margins-affected-by-block-step-size.html": [
+       "e51a01353532f74dd51d1f47d3cec2c326c66019",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square-only.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "block-level-embed-margins-affected-by-block-step-size.html": [
+       "d82f466d08620ffb9852fcd1db36808e878c9774",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square-only.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "block-level-iframe-margins-affected-by-block-step-size.html": [
+       "b591b896ab2dfb42c626d5e1145f070ec192547a",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square-only.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "block-level-img-margins-affected-by-block-step-size.html": [
+       "d6177987cc97a4697ba1a52a98ca9b44094e97a9",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square-only.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "block-level-object-margins-affected-by-block-step-size.html": [
+       "b9a0f0ef4a33df186cc6e3e450d622d90d09b5c8",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square-only.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "block-level-svg-margins-affected-by-block-step-size.html": [
+       "cbdabeaff543375bc3d884d67a478201f2ab9892",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square-only.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "block-level-video-margins-affected-by-block-step-size.html": [
+       "8d822cfcd5ccac1c86a5bfed9b82f329e90fa06b",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square-only.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ]
+     },
      "zero-outer-size-rounded-up-to-block-step-size.html": [
       "20433b25afd763e9f9ec3b3badc328dd033e0cb2",
       [
@@ -347021,6 +347114,12 @@
       "5e354710d3b40f776065d9eadb2feb229fb8a225",
       []
      ],
+     "computedstyle": {
+      "block-level-replaced-elements-affected-by-block-step-size-expected.txt": [
+       "0032fc263cb2028625624662d4288458cb206469",
+       []
+      ]
+     },
      "parsing": {
       "block-step-align-computed-expected.txt": [
        "72be57e520da1a4fa3cf6c09b8b9031f05afffbf",
@@ -471861,6 +471960,13 @@
         {}
        ]
       ],
+      "container-units-auto.html": [
+       "e2d054d7cca019e800e3f301ac4806e985db2ce8",
+       [
+        null,
+        {}
+       ]
+      ],
       "container-units-basic.html": [
        "2cf5e5c6b1a5f9eff0b5217e4959755394fc7e7f",
        [
@@ -472523,6 +472629,13 @@
         {}
        ]
       ],
+      "size-container-auto-height.html": [
+       "123b3ead2a9121fd4987a7e8fb0766b75eb6a9f3",
+       [
+        null,
+        {}
+       ]
+      ],
       "size-container-no-principal-box.html": [
        "cca59a434cd1f7b81828888d300c281d5944053f",
        [
@@ -486453,6 +486566,22 @@
      ]
     },
     "css-rhythm": {
+     "computedstyle": {
+      "block-level-replaced-elements-affected-by-block-step-size.html": [
+       "fdbd0da120833efd53afccd34d76e83690e9af32",
+       [
+        null,
+        {}
+       ]
+      ],
+      "inline-level-replaced-elements-not-affected-by-block-step-size.html": [
+       "0531c7edbdcb7b4999b8e23f38ed2575c0dd72e7",
+       [
+        null,
+        {}
+       ]
+      ]
+     },
      "parsing": {
       "block-step-align-computed.html": [
        "f56309bad6645c823436b5b13915d68e65bf5a3c",
diff --git a/third_party/blink/web_tests/external/wpt/css/css-gaps/tentative/parsing/gap-decorations-style-computed.html b/third_party/blink/web_tests/external/wpt/css/css-gaps/tentative/parsing/gap-decorations-style-computed.html
index 379fb89c..60600bd 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-gaps/tentative/parsing/gap-decorations-style-computed.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-gaps/tentative/parsing/gap-decorations-style-computed.html
@@ -23,7 +23,18 @@
 test_computed_value("column-rule-style", "ridge");
 test_computed_value("column-rule-style", "inset");
 
-// TODO(crbug.com/357648037): Add tests for multiple values when parsing is implemented.
+test_computed_value("column-rule-style", "dotted dashed solid");
+test_computed_value("column-rule-style", "repeat(10, double)");
+test_computed_value("column-rule-style", "repeat(3, groove) repeat(4, ridge)");
+test_computed_value("column-rule-style", "repeat(auto, solid)");
+test_computed_value("column-rule-style", "repeat(auto, dotted solid inset)");
+test_computed_value("column-rule-style", "repeat(4, none ridge solid) repeat(auto, hidden)");
+test_computed_value("column-rule-style", "inset repeat(auto, solid ridge) repeat(4, none groove hidden)");
+test_computed_value("column-rule-style", "repeat(calc(5 + 3), ridge)", "repeat(8, ridge)");
+test_computed_value("column-rule-style", "repeat(4, dotted double dashed) repeat(auto, solid) ridge");
+test_computed_value("column-rule-style", "repeat(4, dotted double dashed) repeat(auto, solid) repeat(4, none groove hidden)");
+test_computed_value("column-rule-style", "ridge repeat(auto, solid)");
+test_computed_value("column-rule-style", "ridge repeat(auto, solid) ridge");
 
 </script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-gaps/tentative/parsing/gap-decorations-style-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-gaps/tentative/parsing/gap-decorations-style-invalid.html
new file mode 100644
index 0000000..d2a11f6c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-gaps/tentative/parsing/gap-decorations-style-invalid.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Gap Decorations: column-rule-style parsing</title>
+<link rel="help" href="https://kbabbitt.github.io/css-gap-decorations/pr-11115/Overview.html#column-row-rule-style">
+<link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com">
+<meta name="assert" content="column-rule-style supports only the grammar '[ <line-style-list> | <auto-line-style-list> ]'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_invalid_value("column-rule-style", "auto");
+
+test_invalid_value("column-rule-style", "dashed, dotted, solid");
+test_invalid_value("column-rule-style", "repeat(auto, groove, dotted, ridge)");
+test_invalid_value("column-rule-style", "repeat(0, dotted, solid, double)");
+test_invalid_value("column-rule-style", "repeat(-1, dotted, dashed, double)");
+test_invalid_value("column-rule-style", "repeat(auto, dotted) red repeat(auto, ridge)");
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-gaps/tentative/parsing/gap-decorations-style-valid.html b/third_party/blink/web_tests/external/wpt/css/css-gaps/tentative/parsing/gap-decorations-style-valid.html
new file mode 100644
index 0000000..74d243b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-gaps/tentative/parsing/gap-decorations-style-valid.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Gap Decorations: parsing column-rule-style with valid values</title>
+<link rel="help" href="https://kbabbitt.github.io/css-gap-decorations/pr-11115/Overview.html#column-row-rule-style">
+<link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com">
+<meta name="assert" content="column-rule-style supports the full grammar '[ <line-style-list> | <auto-line-style-list> ]'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+// <repeat-line-style>  = repeat( [ <integer [1,∞]> ] , [ <style> ]+ )
+test_valid_value("column-rule-style", "repeat(4, dotted)");
+test_valid_value("column-rule-style", "repeat(3, dashed double dotted)");
+test_valid_value("column-rule-style", "repeat(1, dashed double dotted solid)");
+
+// <line-style-or-repeat> = [ <style> | <repeat-line-style> ]
+test_valid_value("column-rule-style", "dashed");
+test_valid_value("column-rule-style", "repeat(4, double)");
+
+// <line-style-list> = [ <line-style-or-repeat> ]+
+test_valid_value("column-rule-style", "dotted ridge");
+test_valid_value("column-rule-style", "dotted dashed solid groove ridge");
+test_valid_value("column-rule-style", "repeat(3, groove) repeat(4, ridge)");
+test_valid_value("column-rule-style", "inset repeat(3, ridge) none repeat(4, groove hidden dashed)");
+test_valid_value("column-rule-style", "repeat(4, none ridge solid) repeat(5, hidden) double");
+
+// <auto-repeat-line-style>   = repeat( auto , [ <style> ]+ )
+test_valid_value("column-rule-style", "repeat(auto, solid)");
+test_valid_value("column-rule-style", "repeat(auto, dotted solid inset)");
+
+// <auto-line-style-list>    = [ <line-style-or-repeat> ]*
+//                              <auto-repeat-line-style>
+//                              [ <line-style-or-repeat> ]*
+test_valid_value("column-rule-style", "repeat(auto, dashed groove) ridge");
+test_valid_value("column-rule-style", "repeat(4, dotted double dashed) repeat(auto, solid)");
+test_valid_value("column-rule-style", "inset repeat(auto, solid ridge) repeat(4, none groove hidden)");
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-rhythm/computedstyle/block-level-replaced-elements-affected-by-block-step-size-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-rhythm/computedstyle/block-level-replaced-elements-affected-by-block-step-size-expected.txt
new file mode 100644
index 0000000..0032fc26
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-rhythm/computedstyle/block-level-replaced-elements-affected-by-block-step-size-expected.txt
@@ -0,0 +1,30 @@
+This is a testharness.js-based test.
+[FAIL] .test 1
+  assert_equals: \n<div class="container test" data-expected-height="100">\n  <img class="block-step test" src="../../support/60x60-green.png" data-expected-margin-top="20" data-expected-margin-bottom="20">\n</div>\nheight expected 100 but got 60
+[FAIL] .test 2
+  assert_equals: \n<img class="block-step test" src="../../support/60x60-green.png" data-expected-margin-top="20" data-expected-margin-bottom="20">\nheight expected 100 but got 60
+[FAIL] .test 3
+  assert_equals: \n<div class="container test" data-expected-height="100">\n  <canvas width="20" height="20" class="block-step test" data-expected-margin-top="40" data-expected-margin-bottom="40"></canvas>\n</div>\nheight expected 100 but got 20
+[FAIL] .test 4
+  assert_equals: \n<canvas width="20" height="20" class="block-step test" data-expected-margin-top="40" data-expected-margin-bottom="40"></canvas>\nheight expected 100 but got 20
+[FAIL] .test 5
+  assert_equals: \n<div class="container test" data-expected-height="100">\n  <svg class="block-step test" viewBox="0 0 100 50" data-expected-margin-top="25" data-expected-margin-bottom="25"></svg>\n</div>\nheight expected 100 but got 50
+[FAIL] .test 6: undefined
+  assert_equals: \n<svg class="block-step test" viewBox="0 0 100 50" data-expected-margin-top="25" data-expected-margin-bottom="25"></svg>\nheight expected 100 but got 50
+[FAIL] .test 7
+  assert_equals: \n<div class="container test" data-expected-height="100">\n  <embed type="text/xml" width="20" height="20" class="block-step test" data-expected-margin-top="40" data-expected-margin-bottom="40">\n</div>\nheight expected 100 but got 20
+[FAIL] .test 8
+  assert_equals: \n<embed type="text/xml" width="20" height="20" class="block-step test" data-expected-margin-top="40" data-expected-margin-bottom="40">\nheight expected 100 but got 20
+[FAIL] .test 9
+  assert_equals: \n<div class="container test" data-expected-height="100">\n  <iframe src="" width="20" height="20" class="block-step test" data-expected-margin-top="40" data-expected-margin-bottom="40"></iframe>\n</div>\nheight expected 100 but got 20
+[FAIL] .test 10
+  assert_equals: \n<iframe src="" width="20" height="20" class="block-step test" data-expected-margin-top="40" data-expected-margin-bottom="40"></iframe>\nheight expected 100 but got 20
+[FAIL] .test 11
+  assert_equals: \n<div class="container test" data-expected-height="100">\n  <object width="20" height="20" class="block-step test" data-expected-margin-top="40" data-expected-margin-bottom="40"></object>\n</div>\nheight expected 100 but got 20
+[FAIL] .test 12
+  assert_equals: \n<object width="20" height="20" class="block-step test" data-expected-margin-top="40" data-expected-margin-bottom="40"></object>\nheight expected 100 but got 20
+[FAIL] .test 13
+  assert_equals: \n<div class="container test" data-expected-height="100">\n  <video width="20" height="20" class="block-step test" data-expected-margin-top="40" data-expected-margin-bottom="40"></video>\n</div>\nheight expected 100 but got 20
+[FAIL] .test 14
+  assert_equals: \n<video width="20" height="20" class="block-step test" data-expected-margin-top="40" data-expected-margin-bottom="40"></video>\nheight expected 100 but got 20
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-rhythm/computedstyle/block-level-replaced-elements-affected-by-block-step-size.html b/third_party/blink/web_tests/external/wpt/css/css-rhythm/computedstyle/block-level-replaced-elements-affected-by-block-step-size.html
new file mode 100644
index 0000000..fdbd0da
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-rhythm/computedstyle/block-level-replaced-elements-affected-by-block-step-size.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="author" title="Sammy Gill" href="mailto:sammy.gill@apple.com">
+<link rel="help" href="https://drafts.csswg.org/css-rhythm/#block-step-size">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<meta name="assert" content="Checks getComputedStyle for block level replaced margins affected by block-step-size and height of their containers">
+<style>
+.container {
+  display: inline flow-root;
+  width: 100px;
+}
+.block-step {
+  display: block;
+  block-step-size: 100px;
+  visibility: hidden;
+}
+
+iframe {
+  border: 0;
+}
+
+</style>
+</head>
+<body onload="checkLayout('.test')">
+
+<div class="container test" data-expected-height="100">
+  <img class="block-step test" src="../../support/60x60-green.png" data-expected-margin-top="20" data-expected-margin-bottom="20"></img>
+</div>
+
+<div class="container test" data-expected-height="100">
+  <canvas width="20" height="20" class="block-step test" data-expected-margin-top="40" data-expected-margin-bottom="40"></canvas>
+</div>
+
+<div class="container test" data-expected-height="100">
+  <svg class="block-step test" viewBox="0 0 100 50" data-expected-margin-top="25" data-expected-margin-bottom="25"></svg>
+</div>
+
+<div class="container test" data-expected-height="100">
+  <embed type="text/xml" width="20" height="20" class="block-step test" data-expected-margin-top="40" data-expected-margin-bottom="40"></embed>
+</div>
+<div class="container test" data-expected-height="100">
+  <iframe src="" width="20" height="20" class="block-step test" data-expected-margin-top="40" data-expected-margin-bottom="40"></iframe>
+</div>
+
+<div class="container test" data-expected-height="100">
+  <object width="20" height="20" class="block-step test" data-expected-margin-top="40" data-expected-margin-bottom="40"></object>
+</div>
+
+<div class="container test" data-expected-height="100">
+  <video width="20" height="20" class="block-step test" data-expected-margin-top="40" data-expected-margin-bottom="40"></video>
+</div>
+
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-rhythm/computedstyle/inline-level-replaced-elements-not-affected-by-block-step-size.html b/third_party/blink/web_tests/external/wpt/css/css-rhythm/computedstyle/inline-level-replaced-elements-not-affected-by-block-step-size.html
new file mode 100644
index 0000000..0531c7e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-rhythm/computedstyle/inline-level-replaced-elements-not-affected-by-block-step-size.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="author" title="Sammy Gill" href="mailto:sammy.gill@apple.com">
+<link rel="help" href="https://drafts.csswg.org/css-rhythm/#block-step-size">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<meta name="assert" content="Check inline level replaced elements are not affected by block-step-size via getComputedStyle">
+<style>
+.container {
+  display: inline flow-root;
+  width: 100px;
+  font-size: 0px;
+}
+.block-step {
+  block-step-size: 100px;
+  visibility: hidden;
+}
+
+iframe {
+  border: 0;
+}
+
+</style>
+</head>
+<body onload="checkLayout('.test')">
+
+<div class="container test" data-expected-height="60">
+  <img class="block-step test" src="../../support/60x60-green.png" data-expected-margin-top="0" data-expected-margin-bottom="0"></img>
+</div>
+
+<div class="container test" data-expected-height="20">
+  <canvas width="20" height="20" class="block-step test" data-expected-margin-top="0" data-expected-margin-bottom="0"></canvas>
+</div>
+
+<div class="container test" data-expected-height="20">
+  <svg class="block-step test" viewBox="0 0 100 20" data-expected-margin-top="0" data-expected-margin-bottom="0"></svg>
+</div>
+
+<div class="container test" data-expected-height="20">
+  <embed type="text/xml" width="20" height="20" class="block-step test" data-expected-margin-top="0" data-expected-margin-bottom="0"></embed>
+</div>
+<div class="container test" data-expected-height="20">
+  <iframe src="" width="20" height="20" class="block-step test" data-expected-margin-top="0" data-expected-margin-bottom="0"></iframe>
+</div>
+
+<div class="container test" data-expected-height="20">
+  <object width="20" height="20" class="block-step test" data-expected-margin-top="0" data-expected-margin-bottom="0"></object>
+</div>
+
+<div class="container test" data-expected-height="20">
+  <video width="20" height="20" class="block-step test" data-expected-margin-top="0" data-expected-margin-bottom="0"></video>
+</div>
+
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-canvas-margins-affected-by-block-step-size.html b/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-canvas-margins-affected-by-block-step-size.html
new file mode 100644
index 0000000..e51a0135
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-canvas-margins-affected-by-block-step-size.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="author" title="Sammy Gill" href="mailto:sammy.gill@apple.com">
+<link rel="help" href="https://drafts.csswg.org/css-rhythm/#block-step-size">
+<link rel="match" href="../../reference/ref-filled-green-100px-square-only.html">
+<meta name="assert" content="Block level canvas is affected by block-step-size">
+<style>
+.container {
+  display: flow-root;
+  width: 100px;
+  background-color: green;
+}
+.block-step {
+  display: block;
+  block-step-size: 100px;
+}
+</style>
+</head>
+<body>
+<p>Test passes if there is a filled green square.</p>
+<div class="container">
+  <canvas width="20" height="20" class="block-step"></canvas>
+</div>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-embed-margins-affected-by-block-step-size.html b/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-embed-margins-affected-by-block-step-size.html
new file mode 100644
index 0000000..d82f466d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-embed-margins-affected-by-block-step-size.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="author" title="Sammy Gill" href="mailto:sammy.gill@apple.com">
+<link rel="help" href="https://drafts.csswg.org/css-rhythm/#block-step-size">
+<link rel="match" href="../../reference/ref-filled-green-100px-square-only.html">
+<meta name="assert" content="Block level embed is affected by block-step-size">
+<style>
+.container {
+  display: flow-root;
+  width: 100px;
+  background-color: green;
+}
+.block-step {
+  display: block;
+  block-step-size: 100px;
+}
+</style>
+</head>
+<body>
+<p>Test passes if there is a filled green square.</p>
+<div class="container">
+  <embed type="text/xml" width="20" height="20" class="block-step"></embed>
+</div>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-iframe-margins-affected-by-block-step-size.html b/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-iframe-margins-affected-by-block-step-size.html
new file mode 100644
index 0000000..b591b896
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-iframe-margins-affected-by-block-step-size.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="author" title="Sammy Gill" href="mailto:sammy.gill@apple.com">
+<link rel="help" href="https://drafts.csswg.org/css-rhythm/#block-step-size">
+<link rel="match" href="../../reference/ref-filled-green-100px-square-only.html">
+<meta name="assert" content="Block level iframe is affected by block-step-size">
+<style>
+.container {
+  display: flow-root;
+  width: 100px;
+  background-color: green;
+}
+.block-step {
+  display: block;
+  block-step-size: 100px;
+  visibility: hidden;
+}
+</style>
+</head>
+<body>
+<p>Test passes if there is a filled green square.</p>
+<div class="container">
+  <iframe src="" width="20" height="20" class="block-step"></iframe>
+</div>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-img-margins-affected-by-block-step-size.html b/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-img-margins-affected-by-block-step-size.html
new file mode 100644
index 0000000..d6177987
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-img-margins-affected-by-block-step-size.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="author" title="Sammy Gill" href="mailto:sammy.gill@apple.com">
+<link rel="help" href="https://drafts.csswg.org/css-rhythm/#block-step-size">
+<link rel="match" href="../../reference/ref-filled-green-100px-square-only.html">
+<meta name="assert" content="Block level img is affected by block-step-size">
+<style>
+.container {
+  display: flow-root;
+  width: 100px;
+  background-color: green;
+}
+.block-step {
+  block-step-size: 100px;
+  display: block;
+}
+</style>
+</head>
+<body>
+<p>Test passes if there is a filled green square.</p>
+<div class="container">
+  <img class="block-step" src="../../support/60x60-green.png"></img>
+</div>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-object-margins-affected-by-block-step-size.html b/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-object-margins-affected-by-block-step-size.html
new file mode 100644
index 0000000..b9a0f0e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-object-margins-affected-by-block-step-size.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="author" title="Sammy Gill" href="mailto:sammy.gill@apple.com">
+<link rel="help" href="https://drafts.csswg.org/css-rhythm/#block-step-size">
+<link rel="match" href="../../reference/ref-filled-green-100px-square-only.html">
+<meta name="assert" content="Block level object is affected by block-step-size">
+<style>
+.container {
+  display: flow-root;
+  width: 100px;
+  background-color: green;
+}
+.block-step {
+  display: block;
+  block-step-size: 100px;
+}
+</style>
+</head>
+<body>
+<p>Test passes if there is a filled green square.</p>
+<div class="container">
+  <object width="20" height="20" class="block-step"></object>
+</div>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-svg-margins-affected-by-block-step-size.html b/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-svg-margins-affected-by-block-step-size.html
new file mode 100644
index 0000000..cbdabeaf
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-svg-margins-affected-by-block-step-size.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="author" title="Sammy Gill" href="mailto:sammy.gill@apple.com">
+<link rel="help" href="https://drafts.csswg.org/css-rhythm/#block-step-size">
+<link rel="match" href="../../reference/ref-filled-green-100px-square-only.html">
+<meta name="assert" content="Block level SVG is affected by block-step-size">
+<style>
+.container {
+  display: flow-root;
+  background-color: green;
+  width: 100px;
+}
+.block-step {
+  display: block;
+  block-step-size: 100px;
+}
+</style>
+</head>
+<body>
+<p>Test passes if there is a filled green square.</p>
+<div class="container">
+  <svg class="block-step" viewBox="0 0 100 50"></svg>
+</div>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-video-margins-affected-by-block-step-size.html b/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-video-margins-affected-by-block-step-size.html
new file mode 100644
index 0000000..8d822cf
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-rhythm/replaced-elements/block-level-video-margins-affected-by-block-step-size.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="author" title="Sammy Gill" href="mailto:sammy.gill@apple.com">
+<link rel="help" href="https://drafts.csswg.org/css-rhythm/#block-step-size">
+<link rel="match" href="../../reference/ref-filled-green-100px-square-only.html">
+<meta name="assert" content="Block level video is affected by block-step-size">
+<style>
+.container {
+  display: flow-root;
+  width: 100px;
+  background-color: green;
+}
+.block-step {
+  display: block;
+  block-step-size: 100px;
+}
+</style>
+</head>
+<body>
+<p>Test passes if there is a filled green square.</p>
+<div class="container">
+  <video width="20" height="20" class="block-step"></video>
+</div>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/dimension-attributes-expected.txt b/third_party/blink/web_tests/external/wpt/html/rendering/dimension-attributes-expected.txt
deleted file mode 100644
index 291e645..0000000
--- a/third_party/blink/web_tests/external/wpt/html/rendering/dimension-attributes-expected.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-This is a testharness.js-based test.
-Found 7 FAIL, 0 TIMEOUT, 0 NOTRUN.
-[FAIL] <hr width="0"> mapping to <hr> width property
-  assert_equals: expected "0px" but got "1px"
-[FAIL] <hr width="0%"> mapping to <hr> width property
-  assert_equals: expected "0%" but got "1px"
-[FAIL] <hr width="0px"> mapping to <hr> width property
-  assert_equals: expected "0px" but got "1px"
-[FAIL] <hr width="-0"> mapping to <hr> width property
-  assert_equals: expected "auto" but got "1px"
-[FAIL] <hr width="-0%"> mapping to <hr> width property
-  assert_equals: expected "auto" but got "1px"
-[FAIL] <hr width="+0"> mapping to <hr> width property
-  assert_equals: expected "auto" but got "1px"
-[FAIL] <hr width="+0%"> mapping to <hr> width property
-  assert_equals: expected "auto" but got "1px"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-click-resets-with-commandfor.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-click-resets-with-commandfor.tentative.html
new file mode 100644
index 0000000..a1e3669
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-click-resets-with-commandfor.tentative.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<meta charset="utf-8" />
+<title>Clicking a button should submit the form</title>
+<meta name="author" title="Keith Cirkel" href="mailto:wpt@keithcirkel.co.uk" />
+<link
+  rel="help"
+  href="https://html.spec.whatwg.org/multipage/#attr-button-type-submit-state"
+/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<form id="form">
+  <button id="button" type="reset"></button>
+</form>
+
+<script>
+  const form = document.getElementById("form");
+  const button = document.getElementById("button");
+
+  function resetState() {
+    button.removeAttribute("commandfor");
+    button.removeAttribute("command");
+    button.removeAttribute("disabled");
+    button.removeAttribute("form");
+    button.setAttribute("type", "reset");
+  }
+
+  test((t) => {
+    t.add_cleanup(resetState);
+    button.setAttribute("command", "--foo");
+
+    let called = false;
+    form.addEventListener("reset", (e) => {
+      called = true;
+    });
+    button.click();
+    assert_true(called, "reset should have been dispatched");
+  }, "clicking a reset button should trigger a reset (with command attribute)");
+
+  test((t) => {
+    t.add_cleanup(resetState);
+    button.setAttribute("commandfor", "whatever");
+
+    let called = false;
+    form.addEventListener("reset", (e) => {
+      called = true;
+    });
+    button.click();
+    assert_true(called, "reset should have been dispatched");
+  }, "clicking a button should trigger a reset (with commandfor attribute)");
+
+  test((t) => {
+    t.add_cleanup(resetState);
+    button.setAttribute("command", "--foo");
+    button.setAttribute("commandfor", "whatever");
+
+    let called = false;
+    form.addEventListener("reset", (e) => {
+      called = true;
+    });
+    button.click();
+    assert_true(called, "reset should have been dispatched");
+  }, "clicking a button should trigger a reset (with command and commandfor attribute)");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-click-submits-with-commandfor.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-click-submits-with-commandfor.tentative.html
new file mode 100644
index 0000000..ced0d9ef
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-click-submits-with-commandfor.tentative.html
@@ -0,0 +1,110 @@
+<!doctype html>
+<meta charset="utf-8" />
+<title>Clicking a button should submit the form</title>
+<meta name="author" title="Keith Cirkel" href="mailto:wpt@keithcirkel.co.uk" />
+<link
+  rel="help"
+  href="https://html.spec.whatwg.org/multipage/#attr-button-type-submit-state"
+/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<form id="form">
+  <button id="button"></button>
+</form>
+
+<script>
+  const form = document.getElementById("form");
+  const button = document.getElementById("button");
+
+  function resetState() {
+    button.removeAttribute("commandfor");
+    button.removeAttribute("command");
+    button.removeAttribute("disabled");
+    button.removeAttribute("form");
+    button.removeAttribute("type");
+  }
+
+  test((t) => {
+    t.add_cleanup(resetState);
+    button.setAttribute("command", "--foo");
+
+    let called = false;
+    form.addEventListener("submit", (e) => {
+      e.preventDefault();
+      called = true;
+    }, { once: true });
+    button.click();
+    assert_false(called, "submit should not have been dispatched");
+  }, "clicking a button (implicit type) should NOT trigger a submit (with command attribute)");
+
+  test((t) => {
+    t.add_cleanup(resetState);
+    button.setAttribute("commandfor", "whatever");
+
+    let called = false;
+    form.addEventListener("submit", (e) => {
+      e.preventDefault();
+      called = true;
+    }, { once: true });
+    button.click();
+    assert_false(called, "submit should not have been dispatched");
+  }, "clicking a button (implicit type) should NOT trigger a submit (with commandfor attribute)");
+
+  test((t) => {
+    t.add_cleanup(resetState);
+    button.setAttribute("command", "--foo");
+    button.setAttribute("commandfor", "whatever");
+
+    let called = false;
+    form.addEventListener("submit", (e) => {
+      e.preventDefault();
+      called = true;
+    }, { once: true });
+    button.click();
+    assert_false(called, "submit should not have been dispatched");
+  }, "clicking a button (implicit type) should NOT trigger a submit (with command and commandfor attribute)");
+
+  test((t) => {
+    t.add_cleanup(resetState);
+    button.setAttribute("command", "--foo");
+    button.setAttribute("type", "submit");
+
+    let called = false;
+    form.addEventListener("submit", (e) => {
+      e.preventDefault();
+      called = true;
+    }, { once: true });
+    button.click();
+    assert_true(called, "submit should have been dispatched");
+  }, "clicking a button (explicit type=submit) SHOULD trigger a submit (with command attribute)");
+
+  test((t) => {
+    t.add_cleanup(resetState);
+    button.setAttribute("commandfor", "whatever");
+    button.setAttribute("type", "submit");
+
+    let called = false;
+    form.addEventListener("submit", (e) => {
+      e.preventDefault();
+      called = true;
+    }, { once: true });
+    button.click();
+    assert_true(called, "submit should have been dispatched");
+  }, "clicking a button (explicit type=submit) SHOULD trigger a submit (with commandfor attribute)");
+
+  test((t) => {
+    t.add_cleanup(resetState);
+    button.setAttribute("command", "--foo");
+    button.setAttribute("commandfor", "whatever");
+    button.setAttribute("type", "submit");
+
+    let called = false;
+    form.addEventListener("submit", (e) => {
+      e.preventDefault();
+      called = true;
+    }, { once: true });
+    button.click();
+    assert_true(called, "submit should have been dispatched");
+  }, "clicking a button (explicit type=submit) SHOULD trigger a submit (with command and commandfor attribute)");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-requestclose.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-requestclose.tentative.html
index eb2270b8..18486f7 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-requestclose.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-requestclose.tentative.html
@@ -62,13 +62,8 @@
     promise_test(async (t) => {
       await setup(t,closedby);
       openDialog(modal);
-      if (dialog.closedBy != "none") {
-        dialog.requestClose();
-        assert_false(dialog.open);
-      } else {
-        assert_throws_dom('InvalidStateError',() => dialog.requestClose());
-        assert_true(dialog.open);
-      }
+      dialog.requestClose();
+      assert_false(dialog.open);
     },`requestClose basic behavior ${testDescription}`);
 
     promise_test(async (t) => {
@@ -78,15 +73,11 @@
       dialog.addEventListener('close',() => events.push('close'),{signal});
       openDialog(modal);
       assert_array_equals(events,[]);
-      if (dialog.closedBy != "none") {
-        dialog.requestClose();
-        assert_false(dialog.open);
-        assert_array_equals(events,['cancel'],'close is scheduled');
-        await new Promise(resolve => requestAnimationFrame(resolve));
-        assert_array_equals(events,['cancel','close']);
-      } else {
-        assert_throws_dom('InvalidStateError',() => dialog.requestClose());
-      }
+      dialog.requestClose();
+      assert_false(dialog.open);
+      assert_array_equals(events,['cancel'],'close is scheduled');
+      await new Promise(resolve => requestAnimationFrame(resolve));
+      assert_array_equals(events,['cancel','close']);
     },`requestClose fires both cancel and close ${testDescription}`);
 
     promise_test(async (t) => {
@@ -97,12 +88,8 @@
       openDialog(modal);
       dialog.setAttribute('closedby',closedby);
       assert_array_equals(events,[]);
-      if (dialog.closedBy != "none") {
-        dialog.requestClose();
-        assert_false(dialog.open);
-      } else {
-        assert_throws_dom('InvalidStateError',() => dialog.requestClose());
-      }
+      dialog.requestClose();
+      assert_false(dialog.open);
     },`changing closedby from 'none' to '${closedby}' for ${modal ? "modal" : "modeless"} dialog`);
 
     promise_test(async (t) => {
@@ -113,12 +100,8 @@
       openDialog(modal);
       dialog.removeAttribute('closedby');
       assert_array_equals(events,[]);
-      if (dialog.closedBy != "none") {
-        dialog.requestClose();
-        assert_false(dialog.open);
-      } else {
-        assert_throws_dom('InvalidStateError',() => dialog.requestClose());
-      }
+      dialog.requestClose();
+      assert_false(dialog.open);
     },`Removing closedby when closedby='${closedby}' for ${modal ? "modal" : "modeless"} dialog`);
 
     if (dialog.closedBy != "none") {
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/invokers/invoketarget-button-event-dispatch.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/invokers/invoketarget-button-event-dispatch.tentative.html
index ef87062..74148ca 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/invokers/invoketarget-button-event-dispatch.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/invokers/invoketarget-button-event-dispatch.tentative.html
@@ -37,7 +37,7 @@
     assert_equals(event.isTrusted, true, "isTrusted");
     assert_equals(event.command, "--custom-command", "command");
     assert_equals(event.target, invokee, "target");
-    assert_equals(event.source, invokerbutton, "invoker");
+    assert_equals(event.source, invokerbutton, "source");
   }, "event dispatches on click");
 
   // valid custom invokeactions
@@ -56,7 +56,7 @@
         assert_equals(event.isTrusted, true, "isTrusted");
         assert_equals(event.command, command, "command");
         assert_equals(event.target, invokee, "target");
-        assert_equals(event.source, invokerbutton, "invoker");
+        assert_equals(event.source, invokerbutton, "source");
       }, `setting custom command property to ${command} (must include dash) sets event command`);
 
       promise_test(async function (t) {
@@ -72,7 +72,7 @@
         assert_equals(event.isTrusted, true, "isTrusted");
         assert_equals(event.command, command, "command");
         assert_equals(event.target, invokee, "target");
-        assert_equals(event.source, invokerbutton, "invoker");
+        assert_equals(event.source, invokerbutton, "source");
       }, `setting custom command attribute to ${command} (must include dash) sets event command`);
     },
   );
@@ -139,19 +139,47 @@
     let called = false;
     invokee.addEventListener("command", (e) => (called = true), { once: true });
     invokerbutton.setAttribute("form", "aform");
+    invokerbutton.removeAttribute("type");
     await clickOn(invokerbutton);
     assert_false(called, "event was not called");
-  }, "event does not dispatch if invoker is form associated without `type`");
+  }, "event does NOT dispatch if button is form associated, with implicit type");
+
+  promise_test(async function (t) {
+    t.add_cleanup(resetState);
+    let event;
+    invokee.addEventListener("command", (e) => (event = e), { once: true });
+    invokerbutton.setAttribute("form", "aform");
+    invokerbutton.setAttribute("type", "button");
+    await clickOn(invokerbutton);
+    assert_true(event instanceof CommandEvent, "event is CommandEvent");
+    assert_equals(event.type, "command", "type");
+    assert_equals(event.bubbles, false, "bubbles");
+    assert_equals(event.composed, true, "composed");
+    assert_equals(event.isTrusted, true, "isTrusted");
+    assert_equals(event.command, "--custom-command", "command");
+    assert_equals(event.target, invokee, "target");
+    assert_equals(event.source, invokerbutton, "source");
+  }, "event dispatches if button is form associated, with explicit type=button");
 
   promise_test(async function (t) {
     t.add_cleanup(resetState);
     let called = false;
     invokee.addEventListener("command", (e) => (called = true), { once: true });
     invokerbutton.setAttribute("form", "aform");
-    invokerbutton.setAttribute("type", "button");
+    invokerbutton.setAttribute("type", "submit");
     await clickOn(invokerbutton);
-    assert_true(called, "event was not called");
-  }, "event dispatches if invoker is form associated with `type=button`");
+    assert_false(called, "event was not called");
+  }, "event does NOT dispatch if button is form associated, with explicit type=submit");
+
+  promise_test(async function (t) {
+    t.add_cleanup(resetState);
+    let called = false;
+    invokee.addEventListener("command", (e) => (called = true), { once: true });
+    invokerbutton.setAttribute("form", "aform");
+    invokerbutton.setAttribute("type", "reset");
+    await clickOn(invokerbutton);
+    assert_false(called, "event was not called");
+  }, "event does NOT dispatch if button is form associated, with explicit type=reset");
 
   promise_test(async function (t) {
     svgInvokee = document.createElementNS("http://www.w3.org/2000/svg", "svg");
diff --git a/third_party/blink/web_tests/fast/events/touch/gesture/gesture-tap-hover-clear-expected.txt b/third_party/blink/web_tests/fast/events/touch/gesture/gesture-tap-hover-clear-expected.txt
deleted file mode 100644
index c5aed17..0000000
--- a/third_party/blink/web_tests/fast/events/touch/gesture/gesture-tap-hover-clear-expected.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-Hover over me
-Click me
-
-Tests that hover effects from a gesture tap down can be cleared by a gesture tap or mousemove outside of the hovered element.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-See https://bugs.webkit.org/show_bug.cgi?id=103283 for details.
-
-The Don't Click Me div should not be visible.
-PASS dontClickMe.offsetTop is 0
-The Don't Click Me div should be visible after a GestureShowPress on the Hover Over Me div.
-PASS hoverme is hoverme
-PASS dontClickMe.offsetTop is 100
-The Don't Click Me div should not be visible after a GestureTap on the Click Me div.
-PASS clickme is clickme
-PASS dontClickMe.offsetTop is 0
-The Don't Click Me div should be visible after a GestureShowPress on the Hover Over Me div.
-PASS hoverme is hoverme
-PASS dontClickMe.offsetTop is 100
-The Don't Click Me div should not be visible after a mouse move to below the Click Me div.
-PASS dontClickMe.offsetTop is 0
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/blink/web_tests/fast/events/touch/gesture/gesture-tap-hover-clear.html b/third_party/blink/web_tests/fast/events/touch/gesture/gesture-tap-hover-clear.html
index dd3ef9c..0e01fd4d 100644
--- a/third_party/blink/web_tests/fast/events/touch/gesture/gesture-tap-hover-clear.html
+++ b/third_party/blink/web_tests/fast/events/touch/gesture/gesture-tap-hover-clear.html
@@ -1,6 +1,11 @@
 <!DOCTYPE html>
 <html>
-<script src="../../../../resources/js-test.js"></script>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="../../../../resources/gesture-util.js"></script>
+<script src="../../../../resources/testdriver.js"></script>
+<script src="../../../../resources/testdriver-actions.js"></script>
+<script src="../../../..//resources/testdriver-vendor.js"></script>
 
 <style type="text/css">
 ::-webkit-scrollbar {
@@ -8,24 +13,24 @@
     height: 0px;
 }
 
-div { 
+div {
     line-height: 100px;
 }
 
-#hoverme { 
+#hoverme {
     background-color: lightblue;
 }
 
-#clickme { 
+#clickme {
     background-color: lightgreen;
 }
 
 #dontclickme {
     background-color: yellow;
-    display: none; 
+    display: none;
 }
 
-#hoverme:hover #dontclickme { 
+#hoverme:hover #dontclickme {
     display: block;
 }
 </style>
@@ -37,69 +42,33 @@
 </div>
 <div id='clickme'>Click me</div>
 
-<p id="description"></p>
 <p>See https://bugs.webkit.org/show_bug.cgi?id=103283 for details.</p>
 
-<div id="console"></div>
-
 <script>
-description("Tests that hover effects from a gesture tap down can be cleared by a gesture tap or mousemove outside of the hovered element.");
+const hovered = document.getElementById('hoverme');
+const clickMe = document.getElementById('clickme');
+const dontClickMe = document.getElementById('dontclickme');
+promise_test(async t => {
+  assert_equals(dontClickMe.offsetTop, 0, "The Don't Click Me div should not be visible.");
+  const hoveredPos = elementCenter(hovered);
+  await touchTap(hoveredPos.x, hoveredPos.y);
+  assert_equals(dontClickMe.offsetTop, 100, "The Don't Click Me div should be visible after a touchTap on the Hover Over Me div.");
 
-var clickMe = document.getElementById('clickme');
-var dontClickMe = document.getElementById('dontclickme');
+  assert_equals(document.elementFromPoint(250, 250).id, "clickme");
+  const clickMePos = elementCenter(clickMe);
+  await touchTap(clickMePos.x, clickMePos.y);
+  assert_equals(dontClickMe.offsetTop, 0, "The Don't Click Me div should not be visible after a touchTap on the Click Me div.");
+}, 'Hover effects from a gesture tap down can be cleared by a gesture tap outside of the hovered element.');
 
-function runTests()
-{
-    if (!window.eventSender) {
-        debug('This test requires DRT.');
-        return;
-    }
+promise_test(async t => {
+  assert_equals(dontClickMe.offsetTop, 0, "The Don't Click Me div should not be visible.");
+  const hoveredPos = elementCenter(hovered);
+  await touchTap(hoveredPos.x, hoveredPos.y);
+  assert_equals(dontClickMe.offsetTop, 100, "The Don't Click Me div should be visible after a touchTap on the Hover Over Me div.");
 
-    if (!eventSender.gestureShowPress || !eventSender.gestureTap || !eventSender.mouseMoveTo) {
-        debug('GestureShowPress, GestureTap, or MouseMoveTo is not supported by this platform');
-        return;
-    }
-
-    debug("The Don't Click Me div should not be visible.");
-    shouldBe("dontClickMe.offsetTop", "0");
-
-    debug("The Don't Click Me div should be visible after a GestureShowPress on the Hover Over Me div.");
-    shouldBe(document.elementFromPoint(50, 50).id, "hoverme");
-    eventSender.gestureShowPress(50, 50);
-    shouldBe("dontClickMe.offsetTop", "100");
-
-    debug("The Don't Click Me div should not be visible after a GestureTap on the Click Me div.");
-    shouldBe(document.elementFromPoint(250, 250).id, "clickme");
-    eventSender.gestureTap(250, 250);
-    waitUntilActiveCleared();
-}
-
-function waitUntilActiveCleared()
-{
-    if (dontClickMe.offsetTop != 0) {
-        return setTimeout(waitUntilActiveCleared, 10);
-    }
-
-    shouldBe("dontClickMe.offsetTop", "0");
-
-    debug("The Don't Click Me div should be visible after a GestureShowPress on the Hover Over Me div.");
-    shouldBe(document.elementFromPoint(50, 50).id, "hoverme");
-    eventSender.gestureShowPress(50, 50);
-    shouldBe("dontClickMe.offsetTop", "100");
-
-    debug("The Don't Click Me div should not be visible after a mouse move to below the Click Me div.");
-    eventSender.mouseMoveTo(350, 350);
-    shouldBe("dontClickMe.offsetTop", "0");
-
-    finishJSTest();
-}
-
-if (window.testRunner) {
-    window.jsTestIsAsync = true;
-    testRunner.waitUntilDone();
-}
-
-runTests();
+  await mouseMoveTo(350, 350);
+  assert_equals(dontClickMe.offsetTop, 0, "The Don't Click Me div should not be visible after a mouse move to below the Click Me div.");
+}, 'Hover effects from a gesture tap down can be cleared by a mousemove outside of the hovered element.');
 </script>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/platform/linux/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/pinch-zoom-expected.png b/third_party/blink/web_tests/platform/linux/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/pinch-zoom-expected.png
deleted file mode 100644
index c65dbe6f..0000000
--- a/third_party/blink/web_tests/platform/linux/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/pinch-zoom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png b/third_party/blink/web_tests/platform/linux/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png
deleted file mode 100644
index 4c596df9..0000000
--- a/third_party/blink/web_tests/platform/linux/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/scrollbars-scaled-twice-size-expected.png b/third_party/blink/web_tests/platform/linux/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/scrollbars-scaled-twice-size-expected.png
deleted file mode 100644
index 3d85646..0000000
--- a/third_party/blink/web_tests/platform/linux/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/scrollbars-scaled-twice-size-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/scrollbars/scaled-rendering/pinch-zoom-expected.png b/third_party/blink/web_tests/platform/mac/scrollbars/scaled-rendering/pinch-zoom-expected.png
deleted file mode 100644
index 7c4b5c2..0000000
--- a/third_party/blink/web_tests/platform/mac/scrollbars/scaled-rendering/pinch-zoom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png b/third_party/blink/web_tests/platform/mac/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png
deleted file mode 100644
index c9064e3..0000000
--- a/third_party/blink/web_tests/platform/mac/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/scrollbars/scaled-rendering/scrollbars-scaled-twice-size-expected.png b/third_party/blink/web_tests/platform/mac/scrollbars/scaled-rendering/scrollbars-scaled-twice-size-expected.png
deleted file mode 100644
index 1d117db..0000000
--- a/third_party/blink/web_tests/platform/mac/scrollbars/scaled-rendering/scrollbars-scaled-twice-size-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/disable-raster-inducing-scroll/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png b/third_party/blink/web_tests/platform/mac/virtual/disable-raster-inducing-scroll/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png
deleted file mode 100644
index c9064e3..0000000
--- a/third_party/blink/web_tests/platform/mac/virtual/disable-raster-inducing-scroll/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/prefer_compositing_to_lcd_text/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png b/third_party/blink/web_tests/platform/mac/virtual/prefer_compositing_to_lcd_text/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png
deleted file mode 100644
index c9064e3..0000000
--- a/third_party/blink/web_tests/platform/mac/virtual/prefer_compositing_to_lcd_text/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win10/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/pinch-zoom-expected.png b/third_party/blink/web_tests/platform/win10/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/pinch-zoom-expected.png
deleted file mode 100644
index c65dbe6f..0000000
--- a/third_party/blink/web_tests/platform/win10/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/pinch-zoom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win10/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png b/third_party/blink/web_tests/platform/win10/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png
deleted file mode 100644
index 4c596df9..0000000
--- a/third_party/blink/web_tests/platform/win10/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win10/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/scrollbars-scaled-twice-size-expected.png b/third_party/blink/web_tests/platform/win10/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/scrollbars-scaled-twice-size-expected.png
deleted file mode 100644
index 3d85646..0000000
--- a/third_party/blink/web_tests/platform/win10/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/scrollbars-scaled-twice-size-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/scrollbars/scaled-rendering/pinch-zoom-expected.png b/third_party/blink/web_tests/scrollbars/scaled-rendering/pinch-zoom-expected.png
deleted file mode 100644
index 2233e990..0000000
--- a/third_party/blink/web_tests/scrollbars/scaled-rendering/pinch-zoom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/scrollbars/scaled-rendering/pinch-zoom.html b/third_party/blink/web_tests/scrollbars/scaled-rendering/pinch-zoom.html
deleted file mode 100644
index 8d890e7..0000000
--- a/third_party/blink/web_tests/scrollbars/scaled-rendering/pinch-zoom.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!DOCTYPE html>
-<!-- Tests that pinch-zooming on a subscroller renders properly. -->
-<meta name="fuzzy" content="0-10;0-10" />
-<meta charset="utf-8" />
-<script src="../../resources/gesture-util.js"></script>
-<script src="../../resources/testharness.js"></script>
-
-<style>
-  .scrollable {
-    height: 200px;
-    overflow: scroll;
-    position: fixed;
-    width: 200px;
-  }
-
-  .content {
-    height: 400px;
-    width: 400px;
-  }
-</style>
-
-<div class="scrollable" id="subscroller">
-  <div class="content"></div>
-</div>
-
-<script>
-  window.onload = async () => {
-    if (window.testRunner) {
-      testRunner.waitUntilDone();
-      const subscrollerRect = document
-        .getElementById("subscroller")
-        .getBoundingClientRect();
-      await pinchBy(2, subscrollerRect.left, subscrollerRect.top,
-                    SPEED_INSTANT, GestureSourceType.MOUSE_INPUT);
-      testRunner.notifyDone();
-    }
-  };
-</script>
diff --git a/third_party/blink/web_tests/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png b/third_party/blink/web_tests/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png
deleted file mode 100644
index 5b9c13c..0000000
--- a/third_party/blink/web_tests/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/scrollbars/scaled-rendering/scrollbars-scaled-half-size.html b/third_party/blink/web_tests/scrollbars/scaled-rendering/scrollbars-scaled-half-size.html
deleted file mode 100644
index c1d7030..0000000
--- a/third_party/blink/web_tests/scrollbars/scaled-rendering/scrollbars-scaled-half-size.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!doctype html>
-<!-- Tests that scaled scrollbars in subscrollers render properly. -->
-<meta charset="utf-8">
-<script src="../../resources/testharness.js"></script>
-
-<style>
-  .scrollable {
-    height: 200px;
-    overflow: scroll;
-    position: fixed;
-    width: 200px;
-    transform: scale(0.5);
-    transform-origin: 0 0;
-  }
-
-  .content {
-    height: 400px;
-    width: 400px;
-  }
-  </style>
-
-<div class="scrollable" id="subscroller">
-  <div class="content"></div>
-</div>
diff --git a/third_party/blink/web_tests/scrollbars/scaled-rendering/scrollbars-scaled-twice-size-expected.png b/third_party/blink/web_tests/scrollbars/scaled-rendering/scrollbars-scaled-twice-size-expected.png
deleted file mode 100644
index 0ddc1da..0000000
--- a/third_party/blink/web_tests/scrollbars/scaled-rendering/scrollbars-scaled-twice-size-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/scrollbars/scaled-rendering/scrollbars-scaled-twice-size.html b/third_party/blink/web_tests/scrollbars/scaled-rendering/scrollbars-scaled-twice-size.html
deleted file mode 100644
index ca867cab..0000000
--- a/third_party/blink/web_tests/scrollbars/scaled-rendering/scrollbars-scaled-twice-size.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!doctype html>
-<!-- Tests that scaled scrollbars in subscrollers render properly. -->
-<meta charset="utf-8">
-<script src="../../resources/testharness.js"></script>
-
-<style>
-  .scrollable {
-    height: 200px;
-    overflow: scroll;
-    position: fixed;
-    width: 200px;
-    transform: scale(2);
-    transform-origin: 0 0;
-  }
-
-  .content {
-    height: 400px;
-    width: 400px;
-  }
-  </style>
-
-<div class="scrollable" id="subscroller">
-  <div class="content"></div>
-</div>
diff --git a/third_party/blink/web_tests/virtual/css-gap-decorations/external/wpt/css/css-multicol/parsing/column-rule-style-invalid-expected.txt b/third_party/blink/web_tests/virtual/css-gap-decorations/external/wpt/css/css-multicol/parsing/column-rule-style-invalid-expected.txt
new file mode 100644
index 0000000..ea9dace
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/css-gap-decorations/external/wpt/css/css-multicol/parsing/column-rule-style-invalid-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] e.style['column-rule-style'] = "double dashed" should not set the property value
+  assert_equals: expected "" but got "double dashed"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/disable-raster-inducing-scroll/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png b/third_party/blink/web_tests/virtual/disable-raster-inducing-scroll/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png
deleted file mode 100644
index 9ceea86..0000000
--- a/third_party/blink/web_tests/virtual/disable-raster-inducing-scroll/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/pinch-zoom-expected.png b/third_party/blink/web_tests/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/pinch-zoom-expected.png
deleted file mode 100644
index 1e662fe..0000000
--- a/third_party/blink/web_tests/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/pinch-zoom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png b/third_party/blink/web_tests/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png
deleted file mode 100644
index 391b2cc4..0000000
--- a/third_party/blink/web_tests/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/scrollbars-scaled-twice-size-expected.png b/third_party/blink/web_tests/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/scrollbars-scaled-twice-size-expected.png
deleted file mode 100644
index a99614de..0000000
--- a/third_party/blink/web_tests/virtual/fluent-non-overlay-scrollbar/scrollbars/scaled-rendering/scrollbars-scaled-twice-size-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png
deleted file mode 100644
index 112286ed..0000000
--- a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/scrollbars/scaled-rendering/scrollbars-scaled-half-size-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-overflow/chrome-382966150-crash.html b/third_party/blink/web_tests/wpt_internal/css/css-overflow/chrome-382966150-crash.html
new file mode 100644
index 0000000..8b7eacd8
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/css/css-overflow/chrome-382966150-crash.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>Chrome crash when removing ::scroll-marker-group from size query container</title>
+<link rel="help" href="https://crbug.com/382966150">
+<style>
+  #scroller {
+    container-type: inline-size;
+    overflow: hidden;
+    width: 400px;
+    height: 100px;
+  }
+  #scroller.group { scroll-marker-group: before; }
+  #scroller::scroll-marker-group { height: 100px; }
+</style>
+<div>
+  <div id="scroller" class="group">
+    PASS if no crash
+  </div>
+</div>
+<script>
+  scroller.offsetTop;
+  scroller.className = "";
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/private-aggregation/fenced-frame-disallowed-fields.sub.https.html b/third_party/blink/web_tests/wpt_internal/private-aggregation/fenced-frame-disallowed-fields.sub.https.html
index 93a08a6..556a7c4e 100644
--- a/third_party/blink/web_tests/wpt_internal/private-aggregation/fenced-frame-disallowed-fields.sub.https.html
+++ b/third_party/blink/web_tests/wpt_internal/private-aggregation/fenced-frame-disallowed-fields.sub.https.html
@@ -15,7 +15,7 @@
 const reportPoller = new ReportPoller(
     '/.well-known/private-aggregation/report-shared-storage',
     '/.well-known/private-aggregation/debug/report-shared-storage',
-    /*fullTimeoutMs=*/ 500,
+    /*fullTimeoutMs=*/ 2000,
 );
 
 promise_test(async t => {
diff --git a/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-aggregation-coordinator.https.window.js b/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-aggregation-coordinator.https.window.js
index af26042..1b78fce 100644
--- a/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-aggregation-coordinator.https.window.js
+++ b/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-aggregation-coordinator.https.window.js
@@ -9,7 +9,7 @@
 const reportPoller = new ReportPoller(
     '/.well-known/private-aggregation/report-shared-storage',
     '/.well-known/private-aggregation/debug/report-shared-storage',
-    /*fullTimeoutMs=*/ 500,
+    /*fullTimeoutMs=*/ 2000,
 );
 
 private_aggregation_promise_test(async () => {
diff --git a/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-context-id-sends-report.https.window.js b/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-context-id-sends-report.https.window.js
index 01fed143..84b3fa4 100644
--- a/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-context-id-sends-report.https.window.js
+++ b/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-context-id-sends-report.https.window.js
@@ -9,7 +9,7 @@
 const reportPoller = new ReportPoller(
     '/.well-known/private-aggregation/report-shared-storage',
     '/.well-known/private-aggregation/debug/report-shared-storage',
-    /*fullTimeoutMs=*/ 500,
+    /*fullTimeoutMs=*/ 2000,
 );
 
 private_aggregation_promise_test(async () => {
diff --git a/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-filtering-id-sends-null-report.https.window.js b/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-filtering-id-sends-null-report.https.window.js
index 9265d66..3b42342 100644
--- a/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-filtering-id-sends-null-report.https.window.js
+++ b/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-filtering-id-sends-null-report.https.window.js
@@ -9,7 +9,7 @@
 const reportPoller = new ReportPoller(
     '/.well-known/private-aggregation/report-shared-storage',
     '/.well-known/private-aggregation/debug/report-shared-storage',
-    /*fullTimeoutMs=*/ 500,
+    /*fullTimeoutMs=*/ 2000,
 );
 
 
diff --git a/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-filtering-id-sends-report.https.window.js b/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-filtering-id-sends-report.https.window.js
index b5ee42ae..f16bbc7d 100644
--- a/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-filtering-id-sends-report.https.window.js
+++ b/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-filtering-id-sends-report.https.window.js
@@ -9,7 +9,7 @@
 const reportPoller = new ReportPoller(
     '/.well-known/private-aggregation/report-shared-storage',
     '/.well-known/private-aggregation/debug/report-shared-storage',
-    /*fullTimeoutMs=*/ 500,
+    /*fullTimeoutMs=*/ 2000,
 );
 
 private_aggregation_promise_test(async () => {
diff --git a/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-sends-report.https.window.js b/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-sends-report.https.window.js
index 8ceb2f6..9272998 100644
--- a/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-sends-report.https.window.js
+++ b/third_party/blink/web_tests/wpt_internal/private-aggregation/shared-storage-sends-report.https.window.js
@@ -9,7 +9,7 @@
 const reportPoller = new ReportPoller(
     '/.well-known/private-aggregation/report-shared-storage',
     '/.well-known/private-aggregation/debug/report-shared-storage',
-    /*fullTimeoutMs=*/ 1500,
+    /*fullTimeoutMs=*/ 2000,
 );
 
 private_aggregation_promise_test(async () => {
diff --git a/third_party/boringssl/src b/third_party/boringssl/src
index 9559c45..b6eec48 160000
--- a/third_party/boringssl/src
+++ b/third_party/boringssl/src
@@ -1 +1 @@
-Subproject commit 9559c4566a6d12194c42db5f3dbbcb5de35cfec2
+Subproject commit b6eec48a579eff1abe70ce6d480a017d6ca3a32c
diff --git a/third_party/catapult b/third_party/catapult
index 4899cc8..350ba7c 160000
--- a/third_party/catapult
+++ b/third_party/catapult
@@ -1 +1 @@
-Subproject commit 4899cc831cb18f58428eca4e2467c40e5f452dee
+Subproject commit 350ba7c712c9e1af86954eea7db34d2a6fad294c
diff --git a/third_party/crabbyavif/src b/third_party/crabbyavif/src
index c354828..879ca87 160000
--- a/third_party/crabbyavif/src
+++ b/third_party/crabbyavif/src
@@ -1 +1 @@
-Subproject commit c3548280e0a516ed7cad7ff1591b5807cef64aa4
+Subproject commit 879ca873d6648a01de65e4cb0b86336b581aa513
diff --git a/third_party/crossbench b/third_party/crossbench
index 64db7a1..93a7369 160000
--- a/third_party/crossbench
+++ b/third_party/crossbench
@@ -1 +1 @@
-Subproject commit 64db7a195af090ae97ef2803b1a76c5741b10e4b
+Subproject commit 93a7369e66a419ceede2a0124d95d42243533832
diff --git a/third_party/dawn b/third_party/dawn
index 22a8762..bb1dbd8 160000
--- a/third_party/dawn
+++ b/third_party/dawn
@@ -1 +1 @@
-Subproject commit 22a8762fea90d2d9fbfc592d2bf2a438b66f22f4
+Subproject commit bb1dbd8ad562999d1e142b519d49075ae9bc0253
diff --git a/third_party/devtools-frontend-internal b/third_party/devtools-frontend-internal
index 428d340..d568021 160000
--- a/third_party/devtools-frontend-internal
+++ b/third_party/devtools-frontend-internal
@@ -1 +1 @@
-Subproject commit 428d340fc49509e0ce9bf58048c6f258ace6b260
+Subproject commit d568021d39553f3923662cb2e7badb114fea980b
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src
index 426f32c..3c18d9b 160000
--- a/third_party/devtools-frontend/src
+++ b/third_party/devtools-frontend/src
@@ -1 +1 @@
-Subproject commit 426f32c6fba501cb47b7086c3574ab69402c0995
+Subproject commit 3c18d9b9ab9158565e4378e9899f66b020030b63
diff --git a/third_party/jdk/README.chromium b/third_party/jdk/README.chromium
index 8683063..87cf777 100644
--- a/third_party/jdk/README.chromium
+++ b/third_party/jdk/README.chromium
@@ -1,7 +1,7 @@
 Name: Java Development Kit
 Short Name: JDK
 URL: https://openjdk.java.net/
-Version: 21
+Version: 23
 License: GPL v2
 Security Critical: no
 Shipped: no
diff --git a/third_party/libaddressinput/chromium/resources/address_input_strings_el.xtb b/third_party/libaddressinput/chromium/resources/address_input_strings_el.xtb
index 959de74..1663971 100644
--- a/third_party/libaddressinput/chromium/resources/address_input_strings_el.xtb
+++ b/third_party/libaddressinput/chromium/resources/address_input_strings_el.xtb
@@ -14,7 +14,7 @@
 <translation id="4376888869070172068">Αυτή η μορφή ταχυδρομικού κώδικα δεν αναγνωρίζεται.</translation>
 <translation id="4518701284698680367">Θα πρέπει να εισαγάγετε έναν ταχυδρομικό κώδικα, για παράδειγμα <ph name="EXAMPLE" />. Δεν γνωρίζετε τον ταχυδρομικό σας κώδικα; Βρείτε τον <ph name="BEGIN_LINK" />εδώ<ph name="END_LINK" />.</translation>
 <translation id="5089810972385038852">Πολιτεία</translation>
-<translation id="5095208057601539847">Επαρχία</translation>
+<translation id="5095208057601539847">Διαμέρισμα</translation>
 <translation id="5327248766486351172">Όνομα</translation>
 <translation id="5937097533660449554">Περιφέρεια</translation>
 <translation id="6132429659673988671">Προάστιο</translation>
diff --git a/third_party/libc++/src b/third_party/libc++/src
index 619ccf0..60a3e18 160000
--- a/third_party/libc++/src
+++ b/third_party/libc++/src
@@ -1 +1 @@
-Subproject commit 619ccf05152d4612fac76ba5899094704f3661dd
+Subproject commit 60a3e1838767d557822e90f2671135a79a62c5d0
diff --git a/third_party/libc++abi/src b/third_party/libc++abi/src
index 1bf8357..61ad6ef 160000
--- a/third_party/libc++abi/src
+++ b/third_party/libc++abi/src
@@ -1 +1 @@
-Subproject commit 1bf83572723e3cb921345f9f80d1e462c4b9745b
+Subproject commit 61ad6ef5b6c7ac8328370742323f171dd42ae7c8
diff --git a/third_party/llvm-libc/src b/third_party/llvm-libc/src
index ab4e0ad..4d75039 160000
--- a/third_party/llvm-libc/src
+++ b/third_party/llvm-libc/src
@@ -1 +1 @@
-Subproject commit ab4e0ad95354c43a8afbcb3f19b4bee6066a90c5
+Subproject commit 4d75039545cf1c121eddfb9636e4d19dfbb7fe29
diff --git a/third_party/openscreen/src b/third_party/openscreen/src
index 36b3244..6b69ff0 160000
--- a/third_party/openscreen/src
+++ b/third_party/openscreen/src
@@ -1 +1 @@
-Subproject commit 36b3244c4fa36166c3f165a79826a2dcc8011c2e
+Subproject commit 6b69ff0c0eb4ac177ea2971088e756b6be3391b2
diff --git a/third_party/perfetto b/third_party/perfetto
index d3990a1..1a0d053 160000
--- a/third_party/perfetto
+++ b/third_party/perfetto
@@ -1 +1 @@
-Subproject commit d3990a1c9d27761d8de4290aeadb879a60ecbc90
+Subproject commit 1a0d053d2f0d440bd8cfd1fc6421bccd63dd4041
diff --git a/third_party/rust/chromium_crates_io/Cargo.lock b/third_party/rust/chromium_crates_io/Cargo.lock
index 468a957..f7e90d98 100644
--- a/third_party/rust/chromium_crates_io/Cargo.lock
+++ b/third_party/rust/chromium_crates_io/Cargo.lock
@@ -227,7 +227,7 @@
 
 [[package]]
 name = "fdeflate"
-version = "0.3.6"
+version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "simd-adler32",
@@ -356,7 +356,7 @@
 
 [[package]]
 name = "png"
-version = "0.17.14"
+version = "0.17.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.3.2",
diff --git a/third_party/rust/chromium_crates_io/patches/png/0101-Add-test-coverage-for-PolledAfterEndOfImage-error.patch b/third_party/rust/chromium_crates_io/patches/png/0101-Add-test-coverage-for-PolledAfterEndOfImage-error.patch
deleted file mode 100644
index df2981ea..0000000
--- a/third_party/rust/chromium_crates_io/patches/png/0101-Add-test-coverage-for-PolledAfterEndOfImage-error.patch
+++ /dev/null
@@ -1,242 +0,0 @@
-From 581892db5735dedaafe0a616e4987803c7658c6f Mon Sep 17 00:00:00 2001
-From: Lukasz Anforowicz <lukasza@chromium.org>
-Date: Thu, 3 Oct 2024 19:32:51 +0000
-Subject: [PATCH 101/113] Add test coverage for `PolledAfterEndOfImage` error.
-
-AFAICT before this commit `cargo test` didn't cover the code path in
-`Reader.next_frame` that results in `PolledAfterEndOfImage` error.  This
-commit adds unit tests that provide such coverage.
----
- src/decoder/stream.rs | 191 +++++++++++++++++++++++++++++++++++++++++-
- src/test_utils.rs     |   1 -
- 2 files changed, 190 insertions(+), 2 deletions(-)
-
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-index ac6e6c0..1cd5ff6 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-@@ -1574,6 +1574,7 @@ mod tests {
-     use crate::{Decoder, DecodingError, Reader};
-     use byteorder::WriteBytesExt;
-     use std::cell::RefCell;
-+    use std::collections::VecDeque;
-     use std::fs::File;
-     use std::io::{ErrorKind, Read, Write};
-     use std::rc::Rc;
-@@ -2040,7 +2041,7 @@ mod tests {
-         assert_eq!(3093270825, crc32fast::hash(&buf));
-     }
- 
--    /// `StremingInput` can be used by tests to simulate a streaming input
-+    /// `StreamingInput` can be used by tests to simulate a streaming input
-     /// (e.g. a slow http response, where all bytes are not immediately available).
-     #[derive(Clone)]
-     struct StreamingInput(Rc<RefCell<StreamingInputState>>);
-@@ -2209,4 +2210,192 @@ mod tests {
-             info_from_streaming_input.interlaced
-         );
-     }
-+
-+    /// Creates a ready-to-test [`Reader`] which decodes a PNG that contains:
-+    /// IHDR, IDAT, IEND.
-+    fn create_reader_of_ihdr_idat() -> Reader<VecDeque<u8>> {
-+        let mut png = VecDeque::new();
-+        write_noncompressed_png(&mut png, /* width = */ 16, /* idat_size = */ 1024);
-+        Decoder::new(png).read_info().unwrap()
-+    }
-+
-+    /// Creates a ready-to-test [`Reader`] which decodes an animated PNG that contains:
-+    /// IHDR, acTL, fcTL, IDAT, fcTL, fdAT, IEND.  (i.e. IDAT is part of the animation)
-+    fn create_reader_of_ihdr_actl_fctl_idat_fctl_fdat() -> Reader<VecDeque<u8>> {
-+        let width = 16;
-+        let frame_data = generate_rgba8_with_width_and_height(width, width);
-+        let mut fctl = crate::FrameControl {
-+            width,
-+            height: width,
-+            ..Default::default()
-+        };
-+
-+        let mut png = VecDeque::new();
-+        write_png_sig(&mut png);
-+        write_rgba8_ihdr_with_width(&mut png, width);
-+        write_actl(
-+            &mut png,
-+            &crate::AnimationControl {
-+                num_frames: 2,
-+                num_plays: 0,
-+            },
-+        );
-+        fctl.sequence_number = 0;
-+        write_fctl(&mut png, &fctl);
-+        write_chunk(&mut png, b"IDAT", &frame_data);
-+        fctl.sequence_number = 1;
-+        write_fctl(&mut png, &fctl);
-+        write_fdat(&mut png, 2, &frame_data);
-+        write_iend(&mut png);
-+
-+        Decoder::new(png).read_info().unwrap()
-+    }
-+
-+    /// Creates a ready-to-test [`Reader`] which decodes an animated PNG that contains: IHDR, acTL,
-+    /// IDAT, fcTL, fdAT, fcTL, fdAT, IEND.  (i.e. IDAT is *not* part of the animation)
-+    fn create_reader_of_ihdr_actl_idat_fctl_fdat_fctl_fdat() -> Reader<VecDeque<u8>> {
-+        let width = 16;
-+        let frame_data = generate_rgba8_with_width_and_height(width, width);
-+        let mut fctl = crate::FrameControl {
-+            width,
-+            height: width,
-+            ..Default::default()
-+        };
-+
-+        let mut png = VecDeque::new();
-+        write_png_sig(&mut png);
-+        write_rgba8_ihdr_with_width(&mut png, width);
-+        write_actl(
-+            &mut png,
-+            &crate::AnimationControl {
-+                num_frames: 2,
-+                num_plays: 0,
-+            },
-+        );
-+        write_chunk(&mut png, b"IDAT", &frame_data);
-+        fctl.sequence_number = 0;
-+        write_fctl(&mut png, &fctl);
-+        write_fdat(&mut png, 1, &frame_data);
-+        fctl.sequence_number = 2;
-+        write_fctl(&mut png, &fctl);
-+        write_fdat(&mut png, 3, &frame_data);
-+        write_iend(&mut png);
-+
-+        Decoder::new(png).read_info().unwrap()
-+    }
-+
-+    /// Tests that [`Reader.next_frame`] will report a `PolledAfterEndOfImage` error when called
-+    /// after already decoding a single frame in a non-animated PNG.
-+    #[test]
-+    fn test_next_frame_polling_after_end_non_animated() {
-+        let mut reader = create_reader_of_ihdr_idat();
-+        let mut buf = vec![0; reader.output_buffer_size()];
-+        reader
-+            .next_frame(&mut buf)
-+            .expect("Expecting no error for IDAT frame");
-+
-+        let err = reader
-+            .next_frame(&mut buf)
-+            .expect_err("Main test - expecting error");
-+        assert!(matches!(err, DecodingError::Parameter(_)));
-+    }
-+
-+    /// Tests that [`Reader.next_frame`] will report a `PolledAfterEndOfImage` error when called
-+    /// after already decoding a single frame in an animated PNG where IDAT is part of the
-+    /// animation.
-+    #[test]
-+    fn test_next_frame_polling_after_end_idat_part_of_animation() {
-+        let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat();
-+        let mut buf = vec![0; reader.output_buffer_size()];
-+
-+        assert_eq!(
-+            reader
-+                .info()
-+                .frame_control
-+                .as_ref()
-+                .unwrap()
-+                .sequence_number,
-+            0
-+        );
-+        reader
-+            .next_frame(&mut buf)
-+            .expect("Expecting no error for IDAT frame");
-+
-+        // `next_frame` doesn't advance to the next `fcTL`.
-+        assert_eq!(
-+            reader
-+                .info()
-+                .frame_control
-+                .as_ref()
-+                .unwrap()
-+                .sequence_number,
-+            0
-+        );
-+
-+        reader
-+            .next_frame(&mut buf)
-+            .expect("Expecting no error for fdAT frame");
-+        assert_eq!(
-+            reader
-+                .info()
-+                .frame_control
-+                .as_ref()
-+                .unwrap()
-+                .sequence_number,
-+            1
-+        );
-+
-+        let err = reader
-+            .next_frame(&mut buf)
-+            .expect_err("Main test - expecting error");
-+        assert!(matches!(err, DecodingError::Parameter(_)));
-+    }
-+
-+    /// Tests that [`Reader.next_frame`] will report a `PolledAfterEndOfImage` error when called
-+    /// after already decoding a single frame in an animated PNG where IDAT is *not* part of the
-+    /// animation.
-+    #[test]
-+    fn test_next_frame_polling_after_end_idat_not_part_of_animation() {
-+        let mut reader = create_reader_of_ihdr_actl_idat_fctl_fdat_fctl_fdat();
-+        let mut buf = vec![0; reader.output_buffer_size()];
-+
-+        assert!(reader.info().frame_control.is_none());
-+        reader
-+            .next_frame(&mut buf)
-+            .expect("Expecting no error for IDAT frame");
-+
-+        // `next_frame` doesn't advance to the next `fcTL`.
-+        assert!(reader.info().frame_control.is_none());
-+
-+        reader
-+            .next_frame(&mut buf)
-+            .expect("Expecting no error for 1st fdAT frame");
-+        assert_eq!(
-+            reader
-+                .info()
-+                .frame_control
-+                .as_ref()
-+                .unwrap()
-+                .sequence_number,
-+            0
-+        );
-+
-+        reader
-+            .next_frame(&mut buf)
-+            .expect("Expecting no error for 2nd fdAT frame");
-+        assert_eq!(
-+            reader
-+                .info()
-+                .frame_control
-+                .as_ref()
-+                .unwrap()
-+                .sequence_number,
-+            2
-+        );
-+
-+        let err = reader
-+            .next_frame(&mut buf)
-+            .expect_err("Main test - expecting error");
-+        assert!(matches!(err, DecodingError::Parameter(_)));
-+    }
- }
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/test_utils.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/test_utils.rs
-index bad3036..4db0765 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/test_utils.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/test_utils.rs
-@@ -26,7 +26,6 @@ use std::io::Write;
- /// [this
- /// discussion](https://github.com/image-rs/image-png/discussions/416#discussioncomment-7436871)
- /// for more details).
--#[allow(dead_code)] // Used from `benches/decoder.rs`
- pub fn write_noncompressed_png(w: &mut impl Write, size: u32, idat_bytes: usize) {
-     write_png_sig(w);
-     write_rgba8_ihdr_with_width(w, size);
--- 
-2.47.0.rc0.187.ge670bccf7e-goog
-
diff --git a/third_party/rust/chromium_crates_io/patches/png/0102-Add-test-showing-next_frame-after-next_row-is-tempor.patch b/third_party/rust/chromium_crates_io/patches/png/0102-Add-test-showing-next_frame-after-next_row-is-tempor.patch
deleted file mode 100644
index 0c650c61..0000000
--- a/third_party/rust/chromium_crates_io/patches/png/0102-Add-test-showing-next_frame-after-next_row-is-tempor.patch
+++ /dev/null
@@ -1,61 +0,0 @@
-From f5dd12f4db62efc5db23307784f386c8a7440b71 Mon Sep 17 00:00:00 2001
-From: Lukasz Anforowicz <lukasza@chromium.org>
-Date: Thu, 3 Oct 2024 19:34:53 +0000
-Subject: [PATCH 102/113] Add test showing `next_frame` after `next_row` is
- temporarily stuck.
-
-This commit adds a test with the main assertions commented out
-(because they would fail as-is).  A fix comes in the follow-up commit.
----
- src/decoder/stream.rs | 37 +++++++++++++++++++++++++++++++++++++
- 1 file changed, 37 insertions(+)
-
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-index 1cd5ff6..9c7e1b6 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-@@ -2398,4 +2398,41 @@ mod tests {
-             .expect_err("Main test - expecting error");
-         assert!(matches!(err, DecodingError::Parameter(_)));
-     }
-+
-+    /// Tests that after decoding a whole frame via [`Reader.next_row`] the call to
-+    /// [`Reader.next_frame`] will decode the **next** frame.
-+    #[test]
-+    fn test_row_by_row_then_next_frame() {
-+        let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat();
-+        let mut buf = vec![0; reader.output_buffer_size()];
-+
-+        assert_eq!(
-+            reader
-+                .info()
-+                .frame_control
-+                .as_ref()
-+                .unwrap()
-+                .sequence_number,
-+            0
-+        );
-+        while let Some(_) = reader.next_row().unwrap() {}
-+        assert_eq!(
-+            reader
-+                .info()
-+                .frame_control
-+                .as_ref()
-+                .unwrap()
-+                .sequence_number,
-+            0
-+        );
-+
-+        buf.fill(0x0f);
-+        reader
-+            .next_frame(&mut buf)
-+            .expect("Expecting no error from next_frame call");
-+
-+        // TODO: Verify if we have read the next `fcTL` chunk + repopulated `buf`:
-+        //assert_eq!(reader.info().frame_control.as_ref().unwrap().sequence_number, 1);
-+        //assert!(buf.iter().any(|byte| *byte != 0x0f));
-+    }
- }
--- 
-2.47.0.rc0.187.ge670bccf7e-goog
-
diff --git a/third_party/rust/chromium_crates_io/patches/png/0103-Call-finish_decoding-after-last-next_row.patch b/third_party/rust/chromium_crates_io/patches/png/0103-Call-finish_decoding-after-last-next_row.patch
deleted file mode 100644
index e245b93..0000000
--- a/third_party/rust/chromium_crates_io/patches/png/0103-Call-finish_decoding-after-last-next_row.patch
+++ /dev/null
@@ -1,101 +0,0 @@
-From 3ef723bdb6f816e0d467aa6cf7739d525857f669 Mon Sep 17 00:00:00 2001
-From: Lukasz Anforowicz <lukasza@chromium.org>
-Date: Thu, 3 Oct 2024 19:38:26 +0000
-Subject: [PATCH 103/113] Call `finish_decoding` after last `next_row`.
-
-Before this commit, `next_frame` would take care to read till the end of
-an `IDAT`/`fdAT` chunks sequence, by calling
-`self.decoder.finish_decoding` when
-`!self.subframe.consumed_and_flushed`.  `next_row` wouldn't do this and
-therefore the next call to `next_frame` would be temporarily stuck on
-the previous frame (i.e. finishing decoding after the previous frame
-rather than advancing to the next frame).
-
-After this commit, the `finish_decoding` code is extracted to a separate
-helper function that is called by *both* `next_frame` and
-`next_interlaced_row` (once they detect that all rows of a frame have
-been already decoded).
-
-This commit fixes the `test_row_by_row_then_next_frame` unit test.
----
- src/decoder/mod.rs    | 25 ++++++++++++++++++++-----
- src/decoder/stream.rs | 14 +++++++++++---
- 2 files changed, 31 insertions(+), 8 deletions(-)
-
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs
-index 8a76200..56570b3 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs
-@@ -532,10 +532,7 @@ impl<R: Read> Reader<R> {
-         }
- 
-         // Advance over the rest of data for this (sub-)frame.
--        if !self.subframe.consumed_and_flushed {
--            self.decoder.finish_decoding()?;
--            self.subframe.consumed_and_flushed = true;
--        }
-+        self.finish_decoding()?;
- 
-         // Advance our state to expect the next frame.
-         let past_end_subframe = self
-@@ -558,6 +555,21 @@ impl<R: Read> Reader<R> {
-         Ok(output_info)
-     }
- 
-+    /// Advance over the rest of data for this (sub-)frame.
-+    /// Called after decoding the last row of a frame.
-+    fn finish_decoding(&mut self) -> Result<(), DecodingError> {
-+        // Double-check that all rows of this frame have been decoded.
-+        assert!(self.subframe.current_interlace_info.is_none());
-+
-+        // Discard the remaining data in the current sequence of `IDAT` or `fdAT` chunks.
-+        if !self.subframe.consumed_and_flushed {
-+            self.decoder.finish_decoding()?;
-+            self.subframe.consumed_and_flushed = true;
-+        }
-+
-+        Ok(())
-+    }
-+
-     /// Returns the next processed row of the image
-     pub fn next_row(&mut self) -> Result<Option<Row>, DecodingError> {
-         self.next_interlaced_row()
-@@ -567,7 +579,10 @@ impl<R: Read> Reader<R> {
-     /// Returns the next processed row of the image
-     pub fn next_interlaced_row(&mut self) -> Result<Option<InterlacedRow>, DecodingError> {
-         let interlace = match self.subframe.current_interlace_info.as_ref() {
--            None => return Ok(None),
-+            None => {
-+                self.finish_decoding()?;
-+                return Ok(None);
-+            }
-             Some(interlace) => *interlace,
-         };
-         if interlace.line_number() == 0 {
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-index 9c7e1b6..2607078 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-@@ -2431,8 +2431,16 @@ mod tests {
-             .next_frame(&mut buf)
-             .expect("Expecting no error from next_frame call");
- 
--        // TODO: Verify if we have read the next `fcTL` chunk + repopulated `buf`:
--        //assert_eq!(reader.info().frame_control.as_ref().unwrap().sequence_number, 1);
--        //assert!(buf.iter().any(|byte| *byte != 0x0f));
-+        // Verify if we have read the next `fcTL` chunk + repopulated `buf`:
-+        assert_eq!(
-+            reader
-+                .info()
-+                .frame_control
-+                .as_ref()
-+                .unwrap()
-+                .sequence_number,
-+            1
-+        );
-+        assert!(buf.iter().any(|byte| *byte != 0x0f));
-     }
- }
--- 
-2.47.0.rc0.187.ge670bccf7e-goog
-
diff --git a/third_party/rust/chromium_crates_io/patches/png/0104-Simplify-how-Reader-tracks-how-many-frames-remain-to.patch b/third_party/rust/chromium_crates_io/patches/png/0104-Simplify-how-Reader-tracks-how-many-frames-remain-to.patch
deleted file mode 100644
index 1d69039..0000000
--- a/third_party/rust/chromium_crates_io/patches/png/0104-Simplify-how-Reader-tracks-how-many-frames-remain-to.patch
+++ /dev/null
@@ -1,186 +0,0 @@
-From 657f75b63a9c1d05a6d8dd2307c371ab304f968a Mon Sep 17 00:00:00 2001
-From: Lukasz Anforowicz <lukasza@chromium.org>
-Date: Thu, 3 Oct 2024 19:52:22 +0000
-Subject: [PATCH 104/113] Simplify how `Reader` tracks how many frames remain
- to be decoded.
-
-In an earlier commit 278b1d4fc1da9cebdeb511d8b106d239155c35cc we
-stopped using `Reader.next_frame` for deciding whether to call
-`read_until_image_data` from `next_frame`.  This commit goes one
-step further and removes the `next_frame` field entirely.
-
-There are no known cases where the previous code would result
-in incorrect behavior, but this commit still seems desirable:
-
-* It simplifies the code
-* It ensures that a single "end-of-IDAT/fdAT-sequence" event kind
-  controls both 1) `consumed_and_flushed` state, and 2) counting
-  remaining frames.  (Before this commit `next_frame` would also be
-  mutated after a separate "fcTL-encountered"  event.  And also after
-  "end-of-IDAT/fdAT-sequence" but only from `next_frame` and not from
-  `next_row`.)
----
- src/decoder/mod.rs | 80 +++++++++++++++++-----------------------------
- 1 file changed, 29 insertions(+), 51 deletions(-)
-
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs
-index 56570b3..d0a88e8 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs
-@@ -205,8 +205,7 @@ impl<R: Read> Decoder<R> {
-             decoder: self.read_decoder,
-             bpp: BytesPerPixel::One,
-             subframe: SubframeInfo::not_yet_init(),
--            fctl_read: 0,
--            next_frame: SubframeIdx::Initial,
-+            remaining_frames: 0, // Temporary value - fixed below after reading `acTL` and `fcTL`.
-             data_stream: Vec::new(),
-             prev_start: 0,
-             current_start: 0,
-@@ -234,6 +233,19 @@ impl<R: Read> Decoder<R> {
-         }
- 
-         reader.read_until_image_data()?;
-+
-+        reader.remaining_frames = match reader.info().animation_control.as_ref() {
-+            None => 1, // No `acTL` => only expecting `IDAT` frame.
-+            Some(animation) => {
-+                let mut num_frames = animation.num_frames as usize;
-+                if reader.info().frame_control.is_none() {
-+                    // No `fcTL` before `IDAT` => `IDAT` is not part of the animation, but
-+                    // represents an *extra*, default frame for non-APNG-aware decoders.
-+                    num_frames += 1;
-+                }
-+                num_frames
-+            }
-+        };
-         Ok(reader)
-     }
- 
-@@ -349,11 +361,8 @@ pub struct Reader<R: Read> {
-     decoder: ReadDecoder<R>,
-     bpp: BytesPerPixel,
-     subframe: SubframeInfo,
--    /// Number of frame control chunks read.
--    /// By the APNG specification the total number must equal the count specified in the animation
--    /// control chunk. The IDAT image _may_ have such a chunk applying to it.
--    fctl_read: u32,
--    next_frame: SubframeIdx,
-+    /// How many frames remain to be decoded.  Decremented after each `IDAT` or `fdAT` sequence.
-+    remaining_frames: usize,
-     /// Vec containing the uncompressed image data currently being processed.
-     data_stream: Vec<u8>,
-     /// Index in `data_stream` where the previous row starts.
-@@ -386,19 +395,6 @@ struct SubframeInfo {
-     consumed_and_flushed: bool,
- }
- 
--/// Denote a frame as given by sequence numbers.
--#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
--enum SubframeIdx {
--    /// The initial frame in an IDAT chunk without fcTL chunk applying to it.
--    /// Note that this variant precedes `Some` as IDAT frames precede fdAT frames and all fdAT
--    /// frames must have a fcTL applying to it.
--    Initial,
--    /// An IDAT frame with fcTL or an fdAT frame.
--    Some(u32),
--    /// The past-the-end index.
--    End,
--}
--
- impl<R: Read> Reader<R> {
-     /// Reads all meta data until the next frame data starts.
-     /// Requires IHDR before the IDAT and fcTL before fdAT.
-@@ -414,14 +410,6 @@ impl<R: Read> Reader<R> {
-             match state {
-                 Some(Decoded::ChunkBegin(_, chunk::IDAT))
-                 | Some(Decoded::ChunkBegin(_, chunk::fdAT)) => break,
--                Some(Decoded::FrameControl(_)) => {
--                    // The next frame is the one to which this chunk applies.
--                    self.next_frame = SubframeIdx::Some(self.fctl_read);
--                    // TODO: what about overflow here? That would imply there are more fctl chunks
--                    // than can be specified in the animation control but also that we have read
--                    // several gigabytes of data.
--                    self.fctl_read += 1;
--                }
-                 None => {
-                     return Err(DecodingError::Format(
-                         FormatErrorInner::MissingImageData.into(),
-@@ -473,7 +461,7 @@ impl<R: Read> Reader<R> {
-     /// Output lines will be written in row-major, packed matrix with width and height of the read
-     /// frame (or subframe), all samples are in big endian byte order where this matters.
-     pub fn next_frame(&mut self, buf: &mut [u8]) -> Result<OutputInfo, DecodingError> {
--        if self.next_frame == SubframeIdx::End {
-+        if self.remaining_frames == 0 {
-             return Err(DecodingError::Parameter(
-                 ParameterErrorKind::PolledAfterEndOfImage.into(),
-             ));
-@@ -534,37 +522,27 @@ impl<R: Read> Reader<R> {
-         // Advance over the rest of data for this (sub-)frame.
-         self.finish_decoding()?;
- 
--        // Advance our state to expect the next frame.
--        let past_end_subframe = self
--            .info()
--            .animation_control()
--            .map(|ac| ac.num_frames)
--            .unwrap_or(0);
--        self.next_frame = match self.next_frame {
--            SubframeIdx::End => unreachable!("Next frame called when already at image end"),
--            // Reached the end of non-animated image.
--            SubframeIdx::Initial if past_end_subframe == 0 => SubframeIdx::End,
--            // An animated image, expecting first subframe.
--            SubframeIdx::Initial => SubframeIdx::Some(0),
--            // This was the last subframe, slightly fuzzy condition in case of programmer error.
--            SubframeIdx::Some(idx) if past_end_subframe <= idx + 1 => SubframeIdx::End,
--            // Expecting next subframe.
--            SubframeIdx::Some(idx) => SubframeIdx::Some(idx + 1),
--        };
--
-         Ok(output_info)
-     }
- 
-+    fn mark_subframe_as_consumed_and_flushed(&mut self) {
-+        assert!(self.remaining_frames > 0);
-+        self.remaining_frames -= 1;
-+
-+        self.subframe.consumed_and_flushed = true;
-+    }
-+
-     /// Advance over the rest of data for this (sub-)frame.
-     /// Called after decoding the last row of a frame.
-     fn finish_decoding(&mut self) -> Result<(), DecodingError> {
--        // Double-check that all rows of this frame have been decoded.
-+        // Double-check that all rows of this frame have been decoded (i.e. that the potential
-+        // `finish_decoding` call below won't be discarding any data).
-         assert!(self.subframe.current_interlace_info.is_none());
- 
-         // Discard the remaining data in the current sequence of `IDAT` or `fdAT` chunks.
-         if !self.subframe.consumed_and_flushed {
-             self.decoder.finish_decoding()?;
--            self.subframe.consumed_and_flushed = true;
-+            self.mark_subframe_as_consumed_and_flushed();
-         }
- 
-         Ok(())
-@@ -617,7 +595,7 @@ impl<R: Read> Reader<R> {
-     /// Read the rest of the image and chunks and finish up, including text chunks or others
-     /// This will discard the rest of the image if the image is not read already with [`Reader::next_frame`], [`Reader::next_row`] or [`Reader::next_interlaced_row`]
-     pub fn finish(&mut self) -> Result<(), DecodingError> {
--        self.next_frame = SubframeIdx::End;
-+        self.remaining_frames = 0;
-         self.data_stream.clear();
-         self.current_start = 0;
-         self.prev_start = 0;
-@@ -729,7 +707,7 @@ impl<R: Read> Reader<R> {
- 
-             match self.decoder.decode_next(&mut self.data_stream)? {
-                 Some(Decoded::ImageData) => (),
--                Some(Decoded::ImageDataFlushed) => self.subframe.consumed_and_flushed = true,
-+                Some(Decoded::ImageDataFlushed) => self.mark_subframe_as_consumed_and_flushed(),
-                 _ => (),
-             }
-         }
--- 
-2.47.0.rc0.187.ge670bccf7e-goog
-
diff --git a/third_party/rust/chromium_crates_io/patches/png/0105-Fix-a-subset-of-issues-identified-by-cargo-clippy.patch b/third_party/rust/chromium_crates_io/patches/png/0105-Fix-a-subset-of-issues-identified-by-cargo-clippy.patch
deleted file mode 100644
index 84d483c..0000000
--- a/third_party/rust/chromium_crates_io/patches/png/0105-Fix-a-subset-of-issues-identified-by-cargo-clippy.patch
+++ /dev/null
@@ -1,100 +0,0 @@
-From 1764d169bd1e05354336a4b1f07b6345a760a556 Mon Sep 17 00:00:00 2001
-From: Lukasz Anforowicz <lukasza@chromium.org>
-Date: Thu, 3 Oct 2024 20:07:16 +0000
-Subject: [PATCH 105/113] Fix a subset of issues identified by `cargo clippy`.
-
----
- src/decoder/stream.rs            | 6 ++----
- src/decoder/transform.rs         | 8 ++++----
- src/decoder/transform/palette.rs | 4 ++--
- src/encoder.rs                   | 1 -
- 4 files changed, 8 insertions(+), 11 deletions(-)
-
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-index 2607078..f52523a 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-@@ -958,7 +958,7 @@ impl StreamingDecoder {
-             _ => Ok(Decoded::PartialChunk(type_str)),
-         };
- 
--        let parse_result = parse_result.map_err(|e| {
-+        parse_result.map_err(|e| {
-             self.state = None;
-             match e {
-                 // `parse_chunk` is invoked after gathering **all** bytes of a chunk, so
-@@ -972,9 +972,7 @@ impl StreamingDecoder {
-                 }
-                 e => e,
-             }
--        });
--
--        parse_result
-+        })
-     }
- 
-     fn parse_fctl(&mut self) -> Result<Decoded, DecodingError> {
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/transform.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/transform.rs
-index e7de03e..f2b6654 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/transform.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/transform.rs
-@@ -30,18 +30,18 @@ pub fn create_transform_fn(
-     match color_type {
-         ColorType::Indexed if expand => {
-             if info.palette.is_none() {
--                return Err(DecodingError::Format(
-+                Err(DecodingError::Format(
-                     FormatErrorInner::PaletteRequired.into(),
--                ));
-+                ))
-             } else if let BitDepth::Sixteen = info.bit_depth {
-                 // This should have been caught earlier but let's check again. Can't hurt.
--                return Err(DecodingError::Format(
-+                Err(DecodingError::Format(
-                     FormatErrorInner::InvalidColorBitDepth {
-                         color_type: ColorType::Indexed,
-                         bit_depth: BitDepth::Sixteen,
-                     }
-                     .into(),
--                ));
-+                ))
-             } else {
-                 Ok(if trns {
-                     palette::create_expansion_into_rgba8(info)
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/transform/palette.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/transform/palette.rs
-index 329c7bd..7508913 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/transform/palette.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/transform/palette.rs
-@@ -70,7 +70,7 @@ fn create_rgba_palette(info: &Info) -> [[u8; 4]; 256] {
-             palette_iter = &palette_iter[3..];
-             rgba_iter = &mut rgba_iter[1..];
-         }
--        if palette_iter.len() > 0 {
-+        if !palette_iter.is_empty() {
-             rgba_iter[0][0..3].copy_from_slice(&palette_iter[0..3]);
-         }
-     }
-@@ -99,7 +99,7 @@ fn expand_8bit_into_rgb8(mut input: &[u8], mut output: &mut [u8], rgba_palette:
-         input = &input[1..];
-         output = &mut output[3..];
-     }
--    if output.len() > 0 {
-+    if !output.is_empty() {
-         let rgba = &rgba_palette[input[0] as usize];
-         output[0..3].copy_from_slice(&rgba[0..3]);
-     }
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/encoder.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/encoder.rs
-index 73e0f1e..d694f76 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/encoder.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/encoder.rs
-@@ -317,7 +317,6 @@ impl<'a, W: Write> Encoder<'a, W> {
-     /// based on heuristics which minimize the file size for compression rather
-     /// than use a single filter for the entire image. The default method is
-     /// [`AdaptiveFilterType::NonAdaptive`].
--
-     pub fn set_adaptive_filter(&mut self, adaptive_filter: AdaptiveFilterType) {
-         self.options.adaptive_filter = adaptive_filter;
-     }
--- 
-2.47.0.rc0.187.ge670bccf7e-goog
-
diff --git a/third_party/rust/chromium_crates_io/patches/png/0106-Avoid-infinite-loop-when-retrying-after-earlier-fata.patch b/third_party/rust/chromium_crates_io/patches/png/0106-Avoid-infinite-loop-when-retrying-after-earlier-fata.patch
deleted file mode 100644
index 2af32ff..0000000
--- a/third_party/rust/chromium_crates_io/patches/png/0106-Avoid-infinite-loop-when-retrying-after-earlier-fata.patch
+++ /dev/null
@@ -1,123 +0,0 @@
-From 1ec761327e59f712374068e63a44f705b9162e0f Mon Sep 17 00:00:00 2001
-From: Lukasz Anforowicz <lukasza@chromium.org>
-Date: Fri, 4 Oct 2024 22:51:09 +0000
-Subject: [PATCH 106/113] Avoid infinite loop when retrying after earlier fatal
- error.
-
-When `StreamingDecoder` reports an error, it leaves `state` set to
-`None`.  Before this commit, calling `next_frame` in this state would
-have led to an infinite loop:
-
-* `ReadDecoder::decode_next` would loop forever (`!self.at_eof` is true
-  after an error) and would fail to make progress, because
-* When `StreamingDecoder::update` sees `state` saw set to `None` then
-  before this commit it wouldn't enter the `next_state` loop and would
-  immediately return no progress
-  (`Ok((/* consumer bytes = */ 0, Decoded::Nothing))`).
-
-After this commit, `StreamingDecoder::update` checks if the `state` is
-`None` and treats this as an error.
----
- src/common.rs         |  7 +++++++
- src/decoder/stream.rs | 32 +++++++++++++++++++++++++-------
- 2 files changed, 32 insertions(+), 7 deletions(-)
-
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
-index 4475153..a3b6c27 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
-@@ -791,6 +791,10 @@ pub(crate) enum ParameterErrorKind {
-     /// library will perform the checks necessary to ensure that data was accurate or error with a
-     /// format error otherwise.
-     PolledAfterEndOfImage,
-+    /// Attempt to continue decoding after a fatal, non-resumable error was reported (e.g. after
-+    /// [`DecodingError::Format`]).  The only case when it is possible to resume after an error
-+    /// is an `UnexpectedEof` scenario - see [`DecodingError::IoError`].
-+    PolledAfterFatalError,
- }
- 
- impl From<ParameterErrorKind> for ParameterError {
-@@ -807,6 +811,9 @@ impl fmt::Display for ParameterError {
-                 write!(fmt, "wrong data size, expected {} got {}", expected, actual)
-             }
-             PolledAfterEndOfImage => write!(fmt, "End of image has been reached"),
-+            PolledAfterFatalError => {
-+                write!(fmt, "A fatal decoding error has been encounted earlier")
-+            }
-         }
-     }
- }
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-index f52523a..e8412f3 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-@@ -10,7 +10,7 @@ use super::zlib::ZlibStream;
- use crate::chunk::{self, ChunkType, IDAT, IEND, IHDR};
- use crate::common::{
-     AnimationControl, BitDepth, BlendOp, ColorType, DisposeOp, FrameControl, Info, ParameterError,
--    PixelDimensions, ScaledFloat, SourceChromaticities, Unit,
-+    ParameterErrorKind, PixelDimensions, ScaledFloat, SourceChromaticities, Unit,
- };
- use crate::text_metadata::{ITXtChunk, TEXtChunk, TextDecodingError, ZTXtChunk};
- use crate::traits::ReadBytesExt;
-@@ -627,15 +627,24 @@ impl StreamingDecoder {
-         mut buf: &[u8],
-         image_data: &mut Vec<u8>,
-     ) -> Result<(usize, Decoded), DecodingError> {
-+        if self.state.is_none() {
-+            return Err(DecodingError::Parameter(
-+                ParameterErrorKind::PolledAfterFatalError.into(),
-+            ));
-+        }
-+
-         let len = buf.len();
--        while !buf.is_empty() && self.state.is_some() {
-+        while !buf.is_empty() {
-             match self.next_state(buf, image_data) {
-                 Ok((bytes, Decoded::Nothing)) => buf = &buf[bytes..],
-                 Ok((bytes, result)) => {
-                     buf = &buf[bytes..];
-                     return Ok((len - buf.len(), result));
-                 }
--                Err(err) => return Err(err),
-+                Err(err) => {
-+                    debug_assert!(self.state.is_none());
-+                    return Err(err);
-+                }
-             }
-         }
-         Ok((len - buf.len(), Decoded::Nothing))
-@@ -1917,8 +1926,18 @@ mod tests {
-         // 0-length fdAT should result in an error.
-         let err = reader.next_frame(&mut buf).unwrap_err();
-         assert!(matches!(&err, DecodingError::Format(_)));
--        let msg = format!("{err}");
--        assert_eq!("fdAT chunk shorter than 4 bytes", msg);
-+        assert_eq!("fdAT chunk shorter than 4 bytes", format!("{err}"));
-+
-+        // Calling `next_frame` again should return an error.  Same error as above would be nice,
-+        // but it is probably unnecessary and infeasible (`DecodingError` can't derive `Clone`
-+        // because `std::io::Error` doesn't implement `Clone`)..  But it definitely shouldn't enter
-+        // an infinite loop.
-+        let err2 = reader.next_frame(&mut buf).unwrap_err();
-+        assert!(matches!(&err2, DecodingError::Parameter(_)));
-+        assert_eq!(
-+            "A fatal decoding error has been encounted earlier",
-+            format!("{err2}")
-+        );
-     }
- 
-     #[test]
-@@ -1935,8 +1954,7 @@ mod tests {
-         // 3-bytes-long fdAT should result in an error.
-         let err = reader.next_frame(&mut buf).unwrap_err();
-         assert!(matches!(&err, DecodingError::Format(_)));
--        let msg = format!("{err}");
--        assert_eq!("fdAT chunk shorter than 4 bytes", msg);
-+        assert_eq!("fdAT chunk shorter than 4 bytes", format!("{err}"));
-     }
- 
-     #[test]
--- 
-2.47.0.rc0.187.ge670bccf7e-goog
-
diff --git a/third_party/rust/chromium_crates_io/patches/png/0107-New-API-Reader.next_frame_control-for-advancing-to-t.patch b/third_party/rust/chromium_crates_io/patches/png/0107-New-API-Reader.next_frame_control-for-advancing-to-t.patch
deleted file mode 100644
index fba1dc8..0000000
--- a/third_party/rust/chromium_crates_io/patches/png/0107-New-API-Reader.next_frame_control-for-advancing-to-t.patch
+++ /dev/null
@@ -1,364 +0,0 @@
-From ffed4ded8e8a7e41d4dabcf6201218dc51cd4821 Mon Sep 17 00:00:00 2001
-From: Lukasz Anforowicz <lukasza@chromium.org>
-Date: Thu, 3 Oct 2024 23:08:29 +0000
-Subject: [PATCH 107/113] New API: `Reader.next_frame_control` (for advancing
- to the next frame).
-
----
- src/decoder/mod.rs    |  33 ++++++
- src/decoder/stream.rs | 231 ++++++++++++++++++++++++++++--------------
- 2 files changed, 189 insertions(+), 75 deletions(-)
-
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs
-index d0a88e8..9127252 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs
-@@ -16,6 +16,7 @@ use crate::common::{
-     BitDepth, BytesPerPixel, ColorType, Info, ParameterErrorKind, Transformations,
- };
- use crate::filter::{unfilter, FilterType};
-+use crate::FrameControl;
- 
- pub use interlace_info::InterlaceInfo;
- use interlace_info::InterlaceInfoIter;
-@@ -396,6 +397,38 @@ struct SubframeInfo {
- }
- 
- impl<R: Read> Reader<R> {
-+    /// Advances to the start of the next animation frame and
-+    /// returns a reference to the `FrameControl` info that describes it.
-+    /// Skips and discards the image data of the previous frame if necessary.
-+    ///
-+    /// Returns a [`ParameterError`] when there are no more animation frames.
-+    /// To avoid this the caller can check if [`Info::animation_control`] exists
-+    /// and consult [`AnimationControl::num_frames`].
-+    pub fn next_frame_info(&mut self) -> Result<&FrameControl, DecodingError> {
-+        let remaining_frames = if self.subframe.consumed_and_flushed {
-+            self.remaining_frames
-+        } else {
-+            // One remaining frame will be consumed by the `finish_decoding` call below.
-+            self.remaining_frames - 1
-+        };
-+        if remaining_frames == 0 {
-+            return Err(DecodingError::Parameter(
-+                ParameterErrorKind::PolledAfterEndOfImage.into(),
-+            ));
-+        }
-+
-+        if !self.subframe.consumed_and_flushed {
-+            self.subframe.current_interlace_info = None;
-+            self.finish_decoding()?;
-+        }
-+        self.read_until_image_data()?;
-+
-+        // The PNG standard (and `StreamingDecoder `) guarantes that there is an `fcTL` chunk
-+        // before the start of image data in a sequence of `fdAT` chunks.  Therefore `unwrap`
-+        // below is guaranteed to not panic.
-+        Ok(self.info().frame_control.as_ref().unwrap())
-+    }
-+
-     /// Reads all meta data until the next frame data starts.
-     /// Requires IHDR before the IDAT and fcTL before fdAT.
-     fn read_until_image_data(&mut self) -> Result<(), DecodingError> {
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-index e8412f3..eb906d6 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-@@ -2300,6 +2300,15 @@ mod tests {
-         Decoder::new(png).read_info().unwrap()
-     }
- 
-+    fn get_fctl_sequence_number(reader: &Reader<impl Read>) -> u32 {
-+        reader
-+            .info()
-+            .frame_control
-+            .as_ref()
-+            .unwrap()
-+            .sequence_number
-+    }
-+
-     /// Tests that [`Reader.next_frame`] will report a `PolledAfterEndOfImage` error when called
-     /// after already decoding a single frame in a non-animated PNG.
-     #[test]
-@@ -2313,7 +2322,27 @@ mod tests {
-         let err = reader
-             .next_frame(&mut buf)
-             .expect_err("Main test - expecting error");
--        assert!(matches!(err, DecodingError::Parameter(_)));
-+        assert!(
-+            matches!(&err, DecodingError::Parameter(_)),
-+            "Unexpected kind of error: {:?}",
-+            &err,
-+        );
-+    }
-+
-+    /// Tests that [`Reader.next_frame_info`] will report a `PolledAfterEndOfImage` error when
-+    /// called when decoding a PNG that only contains a single frame.
-+    #[test]
-+    fn test_next_frame_info_polling_after_end_non_animated() {
-+        let mut reader = create_reader_of_ihdr_idat();
-+
-+        let err = reader
-+            .next_frame_info()
-+            .expect_err("Main test - expecting error");
-+        assert!(
-+            matches!(&err, DecodingError::Parameter(_)),
-+            "Unexpected kind of error: {:?}",
-+            &err,
-+        );
-     }
- 
-     /// Tests that [`Reader.next_frame`] will report a `PolledAfterEndOfImage` error when called
-@@ -2324,47 +2353,27 @@ mod tests {
-         let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat();
-         let mut buf = vec![0; reader.output_buffer_size()];
- 
--        assert_eq!(
--            reader
--                .info()
--                .frame_control
--                .as_ref()
--                .unwrap()
--                .sequence_number,
--            0
--        );
-+        assert_eq!(get_fctl_sequence_number(&reader), 0);
-         reader
-             .next_frame(&mut buf)
-             .expect("Expecting no error for IDAT frame");
- 
-         // `next_frame` doesn't advance to the next `fcTL`.
--        assert_eq!(
--            reader
--                .info()
--                .frame_control
--                .as_ref()
--                .unwrap()
--                .sequence_number,
--            0
--        );
-+        assert_eq!(get_fctl_sequence_number(&reader), 0);
- 
-         reader
-             .next_frame(&mut buf)
-             .expect("Expecting no error for fdAT frame");
--        assert_eq!(
--            reader
--                .info()
--                .frame_control
--                .as_ref()
--                .unwrap()
--                .sequence_number,
--            1
--        );
-+        assert_eq!(get_fctl_sequence_number(&reader), 1);
- 
-         let err = reader
-             .next_frame(&mut buf)
-             .expect_err("Main test - expecting error");
--        assert!(matches!(err, DecodingError::Parameter(_)));
-+        assert!(
-+            matches!(&err, DecodingError::Parameter(_)),
-+            "Unexpected kind of error: {:?}",
-+            &err,
-+        );
-     }
- 
-     /// Tests that [`Reader.next_frame`] will report a `PolledAfterEndOfImage` error when called
-@@ -2386,33 +2395,21 @@ mod tests {
-         reader
-             .next_frame(&mut buf)
-             .expect("Expecting no error for 1st fdAT frame");
--        assert_eq!(
--            reader
--                .info()
--                .frame_control
--                .as_ref()
--                .unwrap()
--                .sequence_number,
--            0
--        );
-+        assert_eq!(get_fctl_sequence_number(&reader), 0);
- 
-         reader
-             .next_frame(&mut buf)
-             .expect("Expecting no error for 2nd fdAT frame");
--        assert_eq!(
--            reader
--                .info()
--                .frame_control
--                .as_ref()
--                .unwrap()
--                .sequence_number,
--            2
--        );
-+        assert_eq!(get_fctl_sequence_number(&reader), 2);
- 
-         let err = reader
-             .next_frame(&mut buf)
-             .expect_err("Main test - expecting error");
--        assert!(matches!(err, DecodingError::Parameter(_)));
-+        assert!(
-+            matches!(&err, DecodingError::Parameter(_)),
-+            "Unexpected kind of error: {:?}",
-+            &err,
-+        );
-     }
- 
-     /// Tests that after decoding a whole frame via [`Reader.next_row`] the call to
-@@ -2422,25 +2419,9 @@ mod tests {
-         let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat();
-         let mut buf = vec![0; reader.output_buffer_size()];
- 
--        assert_eq!(
--            reader
--                .info()
--                .frame_control
--                .as_ref()
--                .unwrap()
--                .sequence_number,
--            0
--        );
-+        assert_eq!(get_fctl_sequence_number(&reader), 0);
-         while let Some(_) = reader.next_row().unwrap() {}
--        assert_eq!(
--            reader
--                .info()
--                .frame_control
--                .as_ref()
--                .unwrap()
--                .sequence_number,
--            0
--        );
-+        assert_eq!(get_fctl_sequence_number(&reader), 0);
- 
-         buf.fill(0x0f);
-         reader
-@@ -2448,15 +2429,115 @@ mod tests {
-             .expect("Expecting no error from next_frame call");
- 
-         // Verify if we have read the next `fcTL` chunk + repopulated `buf`:
--        assert_eq!(
--            reader
--                .info()
--                .frame_control
--                .as_ref()
--                .unwrap()
--                .sequence_number,
--            1
--        );
-+        assert_eq!(get_fctl_sequence_number(&reader), 1);
-         assert!(buf.iter().any(|byte| *byte != 0x0f));
-     }
-+
-+    /// Tests that after decoding a whole frame via [`Reader.next_row`] it is possible
-+    /// to use [`Reader.next_row`] to decode the next frame (by using the `next_frame_info` API to
-+    /// advance to the next frame when `next_row` returns `None`).
-+    #[test]
-+    fn test_row_by_row_of_two_frames() {
-+        let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat();
-+
-+        let mut rows_of_frame1 = 0;
-+        assert_eq!(get_fctl_sequence_number(&reader), 0);
-+        while let Some(_) = reader.next_row().unwrap() {
-+            rows_of_frame1 += 1;
-+        }
-+        assert_eq!(rows_of_frame1, 16);
-+        assert_eq!(get_fctl_sequence_number(&reader), 0);
-+
-+        let mut rows_of_frame2 = 0;
-+        assert_eq!(reader.next_frame_info().unwrap().sequence_number, 1);
-+        assert_eq!(get_fctl_sequence_number(&reader), 1);
-+        while let Some(_) = reader.next_row().unwrap() {
-+            rows_of_frame2 += 1;
-+        }
-+        assert_eq!(rows_of_frame2, 16);
-+        assert_eq!(get_fctl_sequence_number(&reader), 1);
-+
-+        let err = reader
-+            .next_frame_info()
-+            .expect_err("No more frames - expecting error");
-+        assert!(
-+            matches!(&err, DecodingError::Parameter(_)),
-+            "Unexpected kind of error: {:?}",
-+            &err,
-+        );
-+    }
-+
-+    /// This test is similar to `test_next_frame_polling_after_end_idat_part_of_animation`, but it
-+    /// uses `next_frame_info` calls to read to the next `fcTL` earlier - before the next call to
-+    /// `next_frame` (knowing `fcTL` before calling `next_frame` may be helpful to determine the
-+    /// size of the output buffer and/or to prepare the buffer based on the `DisposeOp` of the
-+    /// previous frames).
-+    #[test]
-+    fn test_next_frame_info_after_next_frame() {
-+        let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat();
-+        let mut buf = vec![0; reader.output_buffer_size()];
-+
-+        assert_eq!(get_fctl_sequence_number(&reader), 0);
-+        reader
-+            .next_frame(&mut buf)
-+            .expect("Expecting no error for IDAT frame");
-+
-+        // `next_frame` doesn't advance to the next `fcTL`.
-+        assert_eq!(get_fctl_sequence_number(&reader), 0);
-+
-+        // But `next_frame_info` can be used to go to the next `fcTL`.
-+        assert_eq!(reader.next_frame_info().unwrap().sequence_number, 1);
-+        assert_eq!(get_fctl_sequence_number(&reader), 1);
-+
-+        reader
-+            .next_frame(&mut buf)
-+            .expect("Expecting no error for fdAT frame");
-+        assert_eq!(get_fctl_sequence_number(&reader), 1);
-+
-+        let err = reader
-+            .next_frame_info()
-+            .expect_err("Main test - expecting error");
-+        assert!(
-+            matches!(&err, DecodingError::Parameter(_)),
-+            "Unexpected kind of error: {:?}",
-+            &err,
-+        );
-+    }
-+
-+    /// This test is similar to `test_next_frame_polling_after_end_idat_not_part_of_animation`, but
-+    /// it uses `next_frame_info` to skip the `IDAT` frame entirely + to move between frames.
-+    #[test]
-+    fn test_next_frame_info_to_skip_first_frame() {
-+        let mut reader = create_reader_of_ihdr_actl_idat_fctl_fdat_fctl_fdat();
-+        let mut buf = vec![0; reader.output_buffer_size()];
-+
-+        // First (IDAT) frame doesn't have frame control info, which means
-+        // that it is not part of the animation.
-+        assert!(reader.info().frame_control.is_none());
-+
-+        // `next_frame_info` can be used to skip the IDAT frame (without first having to separately
-+        // discard the image data - e.g. by also calling `next_frame` first).
-+        assert_eq!(reader.next_frame_info().unwrap().sequence_number, 0);
-+        assert_eq!(get_fctl_sequence_number(&reader), 0);
-+        reader
-+            .next_frame(&mut buf)
-+            .expect("Expecting no error for 1st fdAT frame");
-+        assert_eq!(get_fctl_sequence_number(&reader), 0);
-+
-+        // Get the `fcTL` for the 2nd frame.
-+        assert_eq!(reader.next_frame_info().unwrap().sequence_number, 2);
-+        reader
-+            .next_frame(&mut buf)
-+            .expect("Expecting no error for 2nd fdAT frame");
-+        assert_eq!(get_fctl_sequence_number(&reader), 2);
-+
-+        let err = reader
-+            .next_frame_info()
-+            .expect_err("Main test - expecting error");
-+        assert!(
-+            matches!(&err, DecodingError::Parameter(_)),
-+            "Unexpected kind of error: {:?}",
-+            &err,
-+        );
-+    }
- }
--- 
-2.47.0.rc0.187.ge670bccf7e-goog
-
diff --git a/third_party/rust/chromium_crates_io/patches/png/0201-Add-EXIF-and-ICC-encoding-and-fix-chunk-order.patch b/third_party/rust/chromium_crates_io/patches/png/0201-Add-EXIF-and-ICC-encoding-and-fix-chunk-order.patch
deleted file mode 100644
index 40aaf5b..0000000
--- a/third_party/rust/chromium_crates_io/patches/png/0201-Add-EXIF-and-ICC-encoding-and-fix-chunk-order.patch
+++ /dev/null
@@ -1,100 +0,0 @@
-From 6bbdb506da254033aaa60975851e5fae2a7b4c42 Mon Sep 17 00:00:00 2001
-From: Jonathan Behrens <fintelia@gmail.com>
-Date: Sun, 20 Oct 2024 12:03:53 -0700
-Subject: [PATCH] Add EXIF and ICC encoding and fix chunk order
-
----
- src/chunk.rs  |  2 ++
- src/common.rs | 30 ++++++++++++++++++++++--------
- 2 files changed, 24 insertions(+), 8 deletions(-)
-
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs
-index 39578a4..3908313 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs
-@@ -35,6 +35,8 @@ pub const gAMA: ChunkType = ChunkType(*b"gAMA");
- pub const sRGB: ChunkType = ChunkType(*b"sRGB");
- /// ICC profile chunk
- pub const iCCP: ChunkType = ChunkType(*b"iCCP");
-+/// EXIF metadata chunk
-+pub const eXIf: ChunkType = ChunkType(*b"eXIf");
- /// Latin-1 uncompressed textual data
- pub const tEXt: ChunkType = ChunkType(*b"tEXt");
- /// Latin-1 compressed textual data
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
-index a3b6c27..259a2b1 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
-@@ -507,6 +507,8 @@ pub struct Info<'a> {
-     pub srgb: Option<SrgbRenderingIntent>,
-     /// The ICC profile for the image.
-     pub icc_profile: Option<Cow<'a, [u8]>>,
-+    /// The EXIF metadata for the image.
-+    pub exif_metadata: Option<Cow<'a, [u8]>>,
-     /// tEXt field
-     pub uncompressed_latin1_text: Vec<TEXtChunk>,
-     /// zTXt field
-@@ -537,6 +539,7 @@ impl Default for Info<'_> {
-             source_chromaticities: None,
-             srgb: None,
-             icc_profile: None,
-+            exif_metadata: None,
-             uncompressed_latin1_text: Vec::new(),
-             compressed_latin1_text: Vec::new(),
-             utf8_text: Vec::new(),
-@@ -631,6 +634,7 @@ impl Info<'_> {
-         data[9] = self.color_type as u8;
-         data[12] = self.interlaced as u8;
-         encoder::write_chunk(&mut w, chunk::IHDR, &data)?;
-+
-         // Encode the pHYs chunk
-         if let Some(pd) = self.pixel_dims {
-             let mut phys_data = [0; 9];
-@@ -643,14 +647,6 @@ impl Info<'_> {
-             encoder::write_chunk(&mut w, chunk::pHYs, &phys_data)?;
-         }
- 
--        if let Some(p) = &self.palette {
--            encoder::write_chunk(&mut w, chunk::PLTE, p)?;
--        };
--
--        if let Some(t) = &self.trns {
--            encoder::write_chunk(&mut w, chunk::tRNS, t)?;
--        }
--
-         // If specified, the sRGB information overrides the source gamma and chromaticities.
-         if let Some(srgb) = &self.srgb {
-             let gamma = crate::srgb::substitute_gamma();
-@@ -665,11 +661,29 @@ impl Info<'_> {
-             if let Some(chrms) = self.source_chromaticities {
-                 chrms.encode(&mut w)?;
-             }
-+            if let Some(iccp) = &self.icc_profile {
-+                encoder::write_chunk(&mut w, chunk::iCCP, iccp)?;
-+            }
-         }
-+
-+        if let Some(exif) = &self.exif_metadata {
-+            encoder::write_chunk(&mut w, chunk::eXIf, exif)?;
-+        }
-+
-         if let Some(actl) = self.animation_control {
-             actl.encode(&mut w)?;
-         }
- 
-+        // The position of the PLTE chunk is important, it must come before the tRNS chunk and after
-+        // many of the other metadata chunks.
-+        if let Some(p) = &self.palette {
-+            encoder::write_chunk(&mut w, chunk::PLTE, p)?;
-+        };
-+
-+        if let Some(t) = &self.trns {
-+            encoder::write_chunk(&mut w, chunk::tRNS, t)?;
-+        }
-+
-         for text_chunk in &self.uncompressed_latin1_text {
-             text_chunk.encode(&mut w)?;
-         }
--- 
-2.47.0.199.ga7371fff76-goog
-
diff --git a/third_party/rust/chromium_crates_io/patches/png/0301-Add-support-for-parsing-mDCv-and-cLLi-chunks.-528.patch b/third_party/rust/chromium_crates_io/patches/png/0301-Add-support-for-parsing-mDCv-and-cLLi-chunks.-528.patch
deleted file mode 100644
index 79c8c22..0000000
--- a/third_party/rust/chromium_crates_io/patches/png/0301-Add-support-for-parsing-mDCv-and-cLLi-chunks.-528.patch
+++ /dev/null
@@ -1,225 +0,0 @@
-From 6016c9bee0fbd6244ebe49ed19a25094898c8001 Mon Sep 17 00:00:00 2001
-From: Lukasz Anforowicz <anforowicz@users.noreply.github.com>
-Date: Wed, 30 Oct 2024 20:45:18 -0700
-Subject: [PATCH 301/302] Add support for parsing `mDCv` and `cLLi` chunks.
- (#528)
-
----
- Cargo.toml                 |   1 +
- src/chunk.rs               |   4 ++
- src/common.rs              |  56 +++++++++++++++++++
- src/decoder/stream.rs      | 108 ++++++++++++++++++++++++++++++++++++-
- tests/bugfixes/cicp_pq.png | Bin 0 -> 191 bytes
- tests/results.txt          |   1 +
- tests/results_alpha.txt    |   1 +
- tests/results_identity.txt |   1 +
- 8 files changed, 170 insertions(+), 2 deletions(-)
- create mode 100644 tests/bugfixes/cicp_pq.png
-
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs
-index 3908313..34a088f 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs
-@@ -35,6 +35,10 @@ pub const gAMA: ChunkType = ChunkType(*b"gAMA");
- pub const sRGB: ChunkType = ChunkType(*b"sRGB");
- /// ICC profile chunk
- pub const iCCP: ChunkType = ChunkType(*b"iCCP");
-+/// Mastering Display Color Volume chunk
-+pub const mDCv: ChunkType = ChunkType(*b"mDCv");
-+/// Content Light Level Information chunk
-+pub const cLLi: ChunkType = ChunkType(*b"cLLi");
- /// EXIF metadata chunk
- pub const eXIf: ChunkType = ChunkType(*b"eXIf");
- /// Latin-1 uncompressed textual data
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
-index 259a2b1..4c06e3b 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
-@@ -470,6 +470,56 @@ impl SrgbRenderingIntent {
-     }
- }
- 
-+/// Mastering Display Color Volume (mDCv) used at the point of content creation,
-+/// as specified in [SMPTE-ST-2086](https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=8353899).
-+///
-+/// See https://www.w3.org/TR/png-3/#mDCv-chunk for more details.
-+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-+pub struct MasteringDisplayColorVolume {
-+    /// Mastering display chromaticities.
-+    pub chromaticities: SourceChromaticities,
-+
-+    /// Mastering display maximum luminance.
-+    ///
-+    /// The value is expressed in units of 0.0001 cd/m^2 - for example if this field
-+    /// is set to `10000000` then it indicates 1000 cd/m^2.
-+    pub max_luminance: u32,
-+
-+    /// Mastering display minimum luminance.
-+    ///
-+    /// The value is expressed in units of 0.0001 cd/m^2 - for example if this field
-+    /// is set to `10000000` then it indicates 1000 cd/m^2.
-+    pub min_luminance: u32,
-+}
-+
-+/// Content light level information of HDR content.
-+///
-+/// See https://www.w3.org/TR/png-3/#cLLi-chunk for more details.
-+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-+pub struct ContentLightLevelInfo {
-+    /// Maximum Content Light Level indicates the maximum light level of any
-+    /// single pixel (in cd/m^2, also known as nits) of the entire playback
-+    /// sequence.
-+    ///
-+    /// The value is expressed in units of 0.0001 cd/m^2 - for example if this field
-+    /// is set to `10000000` then it indicates 1000 cd/m^2.
-+    ///
-+    /// A value of zero means that the value is unknown or not currently calculable.
-+    pub max_content_light_level: u32,
-+
-+    /// Maximum Frame Average Light Level indicates the maximum value of the
-+    /// frame average light level (in cd/m^2, also known as nits) of the entire
-+    /// playback sequence. It is calculated by first averaging the decoded
-+    /// luminance values of all the pixels in each frame, and then using the
-+    /// value for the frame with the highest value.
-+    ///
-+    /// The value is expressed in units of 0.0001 cd/m^2 - for example if this field
-+    /// is set to `10000000` then it indicates 1000 cd/m^2.
-+    ///
-+    /// A value of zero means that the value is unknown or not currently calculable.
-+    pub max_frame_average_light_level: u32,
-+}
-+
- /// PNG info struct
- #[derive(Clone, Debug)]
- #[non_exhaustive]
-@@ -507,6 +557,10 @@ pub struct Info<'a> {
-     pub srgb: Option<SrgbRenderingIntent>,
-     /// The ICC profile for the image.
-     pub icc_profile: Option<Cow<'a, [u8]>>,
-+    /// The mastering display color volume for the image.
-+    pub mastering_display_color_volume: Option<MasteringDisplayColorVolume>,
-+    /// The content light information for the image.
-+    pub content_light_level: Option<ContentLightLevelInfo>,
-     /// The EXIF metadata for the image.
-     pub exif_metadata: Option<Cow<'a, [u8]>>,
-     /// tEXt field
-@@ -539,6 +593,8 @@ impl Default for Info<'_> {
-             source_chromaticities: None,
-             srgb: None,
-             icc_profile: None,
-+            mastering_display_color_volume: None,
-+            content_light_level: None,
-             exif_metadata: None,
-             uncompressed_latin1_text: Vec::new(),
-             compressed_latin1_text: Vec::new(),
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-index 5c21a5a..68de12d 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-@@ -9,8 +9,9 @@ use crc32fast::Hasher as Crc32;
- use super::zlib::ZlibStream;
- use crate::chunk::{self, ChunkType, IDAT, IEND, IHDR};
- use crate::common::{
--    AnimationControl, BitDepth, BlendOp, ColorType, DisposeOp, FrameControl, Info, ParameterError,
--    ParameterErrorKind, PixelDimensions, ScaledFloat, SourceChromaticities, Unit,
-+    AnimationControl, BitDepth, BlendOp, ColorType, ContentLightLevelInfo, DisposeOp, FrameControl,
-+    Info, MasteringDisplayColorVolume, ParameterError, ParameterErrorKind, PixelDimensions,
-+    ScaledFloat, SourceChromaticities, Unit,
- };
- use crate::text_metadata::{ITXtChunk, TEXtChunk, TextDecodingError, ZTXtChunk};
- use crate::traits::ReadBytesExt;
-@@ -958,6 +959,8 @@ impl StreamingDecoder {
-             chunk::fcTL => self.parse_fctl(),
-             chunk::cHRM => self.parse_chrm(),
-             chunk::sRGB => self.parse_srgb(),
-+            chunk::mDCv => Ok(self.parse_mdcv()),
-+            chunk::cLLi => Ok(self.parse_clli()),
-             chunk::iCCP if !self.decode_options.ignore_iccp_chunk => self.parse_iccp(),
-             chunk::tEXt if !self.decode_options.ignore_text_chunk => self.parse_text(),
-             chunk::zTXt if !self.decode_options.ignore_text_chunk => self.parse_ztxt(),
-@@ -1271,6 +1274,82 @@ impl StreamingDecoder {
-         }
-     }
- 
-+    // NOTE: This function cannot return `DecodingError` and handles parsing
-+    // errors or spec violations as-if the chunk was missing.  See
-+    // https://github.com/image-rs/image-png/issues/525 for more discussion.
-+    fn parse_mdcv(&mut self) -> Decoded {
-+        fn parse(mut buf: &[u8]) -> Result<MasteringDisplayColorVolume, std::io::Error> {
-+            let red_x: u16 = buf.read_be()?;
-+            let red_y: u16 = buf.read_be()?;
-+            let green_x: u16 = buf.read_be()?;
-+            let green_y: u16 = buf.read_be()?;
-+            let blue_x: u16 = buf.read_be()?;
-+            let blue_y: u16 = buf.read_be()?;
-+            let white_x: u16 = buf.read_be()?;
-+            let white_y: u16 = buf.read_be()?;
-+            fn scale(chunk: u16) -> ScaledFloat {
-+                // `ScaledFloat::SCALING` is hardcoded to 100_000, which works
-+                // well for the `cHRM` chunk where the spec says that "a value
-+                // of 0.3127 would be stored as the integer 31270".  In the
-+                // `mDCv` chunk the spec says that "0.708, 0.292)" is stored as
-+                // "{ 35400, 14600 }", using a scaling factor of 50_000, so we
-+                // multiply by 2 before converting.
-+                ScaledFloat::from_scaled((chunk as u32) * 2)
-+            }
-+            let chromaticities = SourceChromaticities {
-+                white: (scale(white_x), scale(white_y)),
-+                red: (scale(red_x), scale(red_y)),
-+                green: (scale(green_x), scale(green_y)),
-+                blue: (scale(blue_x), scale(blue_y)),
-+            };
-+            let max_luminance: u32 = buf.read_be()?;
-+            let min_luminance: u32 = buf.read_be()?;
-+            if !buf.is_empty() {
-+                return Err(std::io::ErrorKind::InvalidData.into());
-+            }
-+            Ok(MasteringDisplayColorVolume {
-+                chromaticities,
-+                max_luminance,
-+                min_luminance,
-+            })
-+        }
-+
-+        // The spec requires that the mDCv chunk MUST come before the PLTE and IDAT chunks.
-+        // Additionally, we ignore a second, duplicated mDCv chunk (if any).
-+        let info = self.info.as_mut().unwrap();
-+        let is_before_plte_and_idat = !self.have_idat && info.palette.is_none();
-+        if is_before_plte_and_idat && info.mastering_display_color_volume.is_none() {
-+            info.mastering_display_color_volume = parse(&self.current_chunk.raw_bytes[..]).ok();
-+        }
-+
-+        Decoded::Nothing
-+    }
-+
-+    // NOTE: This function cannot return `DecodingError` and handles parsing
-+    // errors or spec violations as-if the chunk was missing.  See
-+    // https://github.com/image-rs/image-png/issues/525 for more discussion.
-+    fn parse_clli(&mut self) -> Decoded {
-+        fn parse(mut buf: &[u8]) -> Result<ContentLightLevelInfo, std::io::Error> {
-+            let max_content_light_level: u32 = buf.read_be()?;
-+            let max_frame_average_light_level: u32 = buf.read_be()?;
-+            if !buf.is_empty() {
-+                return Err(std::io::ErrorKind::InvalidData.into());
-+            }
-+            Ok(ContentLightLevelInfo {
-+                max_content_light_level,
-+                max_frame_average_light_level,
-+            })
-+        }
-+
-+        // We ignore a second, duplicated cLLi chunk (if any).
-+        let info = self.info.as_mut().unwrap();
-+        if info.content_light_level.is_none() {
-+            info.content_light_level = parse(&self.current_chunk.raw_bytes[..]).ok();
-+        }
-+
-+        Decoded::Nothing
-+    }
-+
-     fn parse_iccp(&mut self) -> Result<Decoded, DecodingError> {
-         if self.have_idat {
-             Err(DecodingError::Format(
--- 
-2.47.0.199.ga7371fff76-goog
-
diff --git a/third_party/rust/chromium_crates_io/patches/png/0302-Add-support-for-parsing-cICP-chunks.-529.patch b/third_party/rust/chromium_crates_io/patches/png/0302-Add-support-for-parsing-cICP-chunks.-529.patch
deleted file mode 100644
index 55aad167..0000000
--- a/third_party/rust/chromium_crates_io/patches/png/0302-Add-support-for-parsing-cICP-chunks.-529.patch
+++ /dev/null
@@ -1,170 +0,0 @@
-From e912074417f5dd3eb9f4bc2dac41f22deae889b9 Mon Sep 17 00:00:00 2001
-From: Lukasz Anforowicz <anforowicz@users.noreply.github.com>
-Date: Fri, 1 Nov 2024 11:22:09 -0700
-Subject: [PATCH 302/302] Add support for parsing `cICP` chunks. (#529)
-
----
- src/chunk.rs          |  2 ++
- src/common.rs         | 42 +++++++++++++++++++++++++++++++
- src/decoder/stream.rs | 57 ++++++++++++++++++++++++++++++++++++++++++-
- 3 files changed, 100 insertions(+), 1 deletion(-)
-
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs
-index 34a088f..b83ce54 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs
-@@ -35,6 +35,8 @@ pub const gAMA: ChunkType = ChunkType(*b"gAMA");
- pub const sRGB: ChunkType = ChunkType(*b"sRGB");
- /// ICC profile chunk
- pub const iCCP: ChunkType = ChunkType(*b"iCCP");
-+/// Coding-independent code points for video signal type identification chunk
-+pub const cICP: ChunkType = ChunkType(*b"cICP");
- /// Mastering Display Color Volume chunk
- pub const mDCv: ChunkType = ChunkType(*b"mDCv");
- /// Content Light Level Information chunk
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
-index 4c06e3b..3d9dc13 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
-@@ -470,6 +470,45 @@ impl SrgbRenderingIntent {
-     }
- }
- 
-+/// Coding-independent code points (cICP) specify the color space (primaries),
-+/// transfer function, matrix coefficients and scaling factor of the image using
-+/// the code points specified in [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273).
-+///
-+/// See https://www.w3.org/TR/png-3/#cICP-chunk for more details.
-+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-+pub struct CodingIndependentCodePoints {
-+    /// Id number of the color primaries defined in
-+    /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) in "Table 2 -
-+    /// Interpretation of colour primaries (ColourPrimaries) value".
-+    pub color_primaries: u8,
-+
-+    /// Id number of the transfer characteristics defined in
-+    /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) in "Table 3 -
-+    /// Interpretation of transfer characteristics (TransferCharacteristics)
-+    /// value".
-+    pub transfer_function: u8,
-+
-+    /// Id number of the matrix coefficients defined in
-+    /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) in "Table 4 -
-+    /// Interpretation of matrix coefficients (MatrixCoefficients) value".
-+    ///
-+    /// This field is included to faithfully replicate the base
-+    /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) specification, but matrix coefficients
-+    /// will always be set to 0, because RGB is currently the only supported color mode in PNG.
-+    pub matrix_coefficients: u8,
-+
-+    /// Whether the image is
-+    /// [a full range image](https://www.w3.org/TR/png-3/#dfn-full-range-image)
-+    /// or
-+    /// [a narrow range image](https://www.w3.org/TR/png-3/#dfn-narrow-range-image).
-+    ///
-+    /// This field is included to faithfully replicate the base
-+    /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) specification, but it has limited
-+    /// practical application to PNG images, because narrow-range images are [quite
-+    /// rare](https://github.com/w3c/png/issues/312#issuecomment-2327349614) in practice.
-+    pub is_video_full_range_image: bool,
-+}
-+
- /// Mastering Display Color Volume (mDCv) used at the point of content creation,
- /// as specified in [SMPTE-ST-2086](https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=8353899).
- ///
-@@ -557,6 +596,8 @@ pub struct Info<'a> {
-     pub srgb: Option<SrgbRenderingIntent>,
-     /// The ICC profile for the image.
-     pub icc_profile: Option<Cow<'a, [u8]>>,
-+    /// The coding-independent code points for video signal type identification of the image.
-+    pub coding_independent_code_points: Option<CodingIndependentCodePoints>,
-     /// The mastering display color volume for the image.
-     pub mastering_display_color_volume: Option<MasteringDisplayColorVolume>,
-     /// The content light information for the image.
-@@ -593,6 +634,7 @@ impl Default for Info<'_> {
-             source_chromaticities: None,
-             srgb: None,
-             icc_profile: None,
-+            coding_independent_code_points: None,
-             mastering_display_color_volume: None,
-             content_light_level: None,
-             exif_metadata: None,
-diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-index 68de12d..760d5fd 100644
---- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
-@@ -15,7 +15,7 @@ use crate::common::{
- };
- use crate::text_metadata::{ITXtChunk, TEXtChunk, TextDecodingError, ZTXtChunk};
- use crate::traits::ReadBytesExt;
--use crate::Limits;
-+use crate::{CodingIndependentCodePoints, Limits};
- 
- /// TODO check if these size are reasonable
- pub const CHUNK_BUFFER_SIZE: usize = 32 * 1024;
-@@ -959,6 +959,7 @@ impl StreamingDecoder {
-             chunk::fcTL => self.parse_fctl(),
-             chunk::cHRM => self.parse_chrm(),
-             chunk::sRGB => self.parse_srgb(),
-+            chunk::cICP => Ok(self.parse_cicp()),
-             chunk::mDCv => Ok(self.parse_mdcv()),
-             chunk::cLLi => Ok(self.parse_clli()),
-             chunk::iCCP if !self.decode_options.ignore_iccp_chunk => self.parse_iccp(),
-@@ -1274,6 +1275,54 @@ impl StreamingDecoder {
-         }
-     }
- 
-+    // NOTE: This function cannot return `DecodingError` and handles parsing
-+    // errors or spec violations as-if the chunk was missing.  See
-+    // https://github.com/image-rs/image-png/issues/525 for more discussion.
-+    fn parse_cicp(&mut self) -> Decoded {
-+        fn parse(mut buf: &[u8]) -> Result<CodingIndependentCodePoints, std::io::Error> {
-+            let color_primaries: u8 = buf.read_be()?;
-+            let transfer_function: u8 = buf.read_be()?;
-+            let matrix_coefficients: u8 = buf.read_be()?;
-+            let is_video_full_range_image = {
-+                let flag: u8 = buf.read_be()?;
-+                match flag {
-+                    0 => false,
-+                    1 => true,
-+                    _ => {
-+                        return Err(std::io::ErrorKind::InvalidData.into());
-+                    }
-+                }
-+            };
-+
-+            // RGB is currently the only supported color model in PNG, and as
-+            // such Matrix Coefficients shall be set to 0.
-+            if matrix_coefficients != 0 {
-+                return Err(std::io::ErrorKind::InvalidData.into());
-+            }
-+
-+            if !buf.is_empty() {
-+                return Err(std::io::ErrorKind::InvalidData.into());
-+            }
-+
-+            Ok(CodingIndependentCodePoints {
-+                color_primaries,
-+                transfer_function,
-+                matrix_coefficients,
-+                is_video_full_range_image,
-+            })
-+        }
-+
-+        // The spec requires that the cICP chunk MUST come before the PLTE and IDAT chunks.
-+        // Additionally, we ignore a second, duplicated cICP chunk (if any).
-+        let info = self.info.as_mut().unwrap();
-+        let is_before_plte_and_idat = !self.have_idat && info.palette.is_none();
-+        if is_before_plte_and_idat && info.coding_independent_code_points.is_none() {
-+            info.coding_independent_code_points = parse(&self.current_chunk.raw_bytes[..]).ok();
-+        }
-+
-+        Decoded::Nothing
-+    }
-+
-     // NOTE: This function cannot return `DecodingError` and handles parsing
-     // errors or spec violations as-if the chunk was missing.  See
-     // https://github.com/image-rs/image-png/issues/525 for more discussion.
--- 
-2.47.0.199.ga7371fff76-goog
-
diff --git a/third_party/rust/chromium_crates_io/supply-chain/audits.toml b/third_party/rust/chromium_crates_io/supply-chain/audits.toml
index 2b0fcb3d..6ab43db 100644
--- a/third_party/rust/chromium_crates_io/supply-chain/audits.toml
+++ b/third_party/rust/chromium_crates_io/supply-chain/audits.toml
@@ -1050,6 +1050,11 @@
 delta = "0.3.5 -> 0.3.6"
 notes = "No unsafe, no crypto, mysterious tables replaced with const expressions"
 
+[[audits.fdeflate]]
+who = "Lukasz Anforowicz <lukasza@chromium.org>"
+criteria = ["safe-to-deploy", "does-not-implement-crypto", "ub-risk-0"]
+delta = "0.3.6 -> 0.3.7"
+
 [[audits.fend-core]]
 who = "jiwan@chromium.org"
 criteria = ["safe-to-deploy", "does-not-implement-crypto", "ub-risk-0"]
@@ -1491,6 +1496,11 @@
 criteria = ["safe-to-deploy", "does-not-implement-crypto", "ub-risk-0"]
 delta = "0.17.13 -> 0.17.14"
 
+[[audits.png]]
+who = "Lukasz Anforowicz <lukasza@chromium.org>"
+criteria = ["safe-to-deploy", "does-not-implement-crypto", "ub-risk-0"]
+delta = "0.17.14 -> 0.17.15"
+
 [[audits.ppv-lite86]]
 who = "danakj@chromium.org"
 criteria = ["safe-to-run", "does-not-implement-crypto"]
diff --git a/third_party/rust/chromium_crates_io/supply-chain/config.toml b/third_party/rust/chromium_crates_io/supply-chain/config.toml
index b1b8438..be6d0f9 100644
--- a/third_party/rust/chromium_crates_io/supply-chain/config.toml
+++ b/third_party/rust/chromium_crates_io/supply-chain/config.toml
@@ -113,7 +113,7 @@
 [policy."either:1.13.0"]
 criteria = ["crypto-safe", "safe-to-run"]
 
-[policy."fdeflate:0.3.6"]
+[policy."fdeflate:0.3.7"]
 criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
 
 [policy."fend-core:1.5.5"]
@@ -173,7 +173,7 @@
 [policy."nom:7.1.3"]
 criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
 
-[policy."png:0.17.14"]
+[policy."png:0.17.15"]
 criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
 
 [policy."ppv-lite86:0.2.20"]
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/.cargo_vcs_info.json
deleted file mode 100644
index e42a4442..0000000
--- a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/.cargo_vcs_info.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "git": {
-    "sha1": "4610c916ae1000c9b5839059340598a7c55130e8"
-  },
-  "path_in_vcs": ""
-}
\ No newline at end of file
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/tables.rs b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/tables.rs
deleted file mode 100644
index 6892e7b..0000000
--- a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/tables.rs
+++ /dev/null
@@ -1,156 +0,0 @@
-use crate::decompress::{EXCEPTIONAL_ENTRY, LITERAL_ENTRY};
-
-/// Hard-coded Huffman codes used regardless of the input.
-///
-/// These values work well for PNGs with some form of filtering enabled, but will likely make most
-/// other inputs worse.
-pub(crate) const HUFFMAN_LENGTHS: [u8; 286] = [
-    2, 3, 4, 5, 5, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10,
-    10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11,
-    11, 11, 11, 10, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 8, 9, 8, 8, 8, 8, 8, 7,
-    7, 7, 6, 6, 6, 5, 4, 3, 12, 12, 12, 9, 9, 11, 10, 11, 11, 10, 11, 11, 11, 11, 11, 11, 12, 11,
-    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 9,
-];
-
-pub(crate) const HUFFMAN_CODES: [u16; 286] = match crate::compute_codes(&HUFFMAN_LENGTHS) {
-    Some(codes) => codes,
-    None => panic!("HUFFMAN_LENGTHS is invalid"),
-};
-
-/// Length code for length values (derived from deflate spec).
-pub(crate) const LENGTH_TO_SYMBOL: [u16; 256] = [
-    257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268, 269, 269, 269,
-    269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272, 273, 273, 273, 273, 273, 273,
-    273, 273, 274, 274, 274, 274, 274, 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276,
-    276, 276, 276, 276, 276, 276, 276, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
-    277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
-    278, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 280, 280,
-    280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 281, 281, 281, 281, 281,
-    281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
-    281, 281, 281, 281, 281, 281, 281, 281, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
-    282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
-    282, 282, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
-    283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 284, 284, 284, 284,
-    284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
-    284, 284, 284, 284, 284, 284, 284, 284, 285,
-];
-
-/// Number of extra bits for length values (derived from deflate spec).
-pub(crate) const LENGTH_TO_LEN_EXTRA: [u8; 256] = [
-    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0,
-];
-
-pub(crate) const BITMASKS: [u32; 17] = [
-    0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF,
-    0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF,
-];
-
-/// Order of the length code length alphabet (derived from deflate spec).
-pub(crate) const CLCL_ORDER: [usize; 19] = [
-    16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15,
-];
-
-/// Number of extra bits for each length code (derived from deflate spec).
-pub(crate) const LEN_SYM_TO_LEN_EXTRA: [u8; 29] = [
-    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0,
-];
-
-/// The base length for each length code (derived from deflate spec).
-pub(crate) const LEN_SYM_TO_LEN_BASE: [usize; 29] = [
-    3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131,
-    163, 195, 227, 258,
-];
-
-/// Number of extra bits for each distance code (derived from deflate spec.)
-pub(crate) const DIST_SYM_TO_DIST_EXTRA: [u8; 30] = [
-    0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13,
-    13,
-];
-
-/// The base distance for each distance code (derived from deflate spec).
-pub(crate) const DIST_SYM_TO_DIST_BASE: [u16; 30] = [
-    1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537,
-    2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577,
-];
-
-/// The main litlen_table uses a 12-bit input to lookup the meaning of the symbol. The table is
-/// split into 4 sections:
-///
-///   aaaaaaaa_bbbbbbbb_1000yyyy_0000xxxx  x = input_advance_bits, y = output_advance_bytes (literal)
-///   0000000z_zzzzzzzz_00000yyy_0000xxxx  x = input_advance_bits, y = extra_bits, z = distance_base (length)
-///   00000000_00000000_01000000_0000xxxx  x = input_advance_bits (EOF)
-///   0000xxxx_xxxxxxxx_01100000_00000000  x = secondary_table_index
-///   00000000_00000000_01000000_00000000  invalid code
-pub(crate) const LITLEN_TABLE_ENTRIES: [u32; 288] = {
-    let mut entries = [EXCEPTIONAL_ENTRY; 288];
-    let mut i = 0;
-    while i < 256 {
-        entries[i] = (i as u32) << 16 | LITERAL_ENTRY | (1 << 8);
-        i += 1;
-    }
-
-    let mut i = 257;
-    while i < 286 {
-        entries[i] = (LEN_SYM_TO_LEN_BASE[i - 257] as u32) << 16
-            | (LEN_SYM_TO_LEN_EXTRA[i - 257] as u32) << 8;
-        i += 1;
-    }
-    entries
-};
-
-/// The distance table is a 512-entry table that maps 9 bits of distance symbols to their meaning.
-///
-///   00000000_00000000_00000000_00000000     symbol is more than 9 bits
-///   zzzzzzzz_zzzzzzzz_0000yyyy_0000xxxx     x = input_advance_bits, y = extra_bits, z = distance_base
-pub(crate) const DISTANCE_TABLE_ENTRIES: [u32; 32] = {
-    let mut entries = [0; 32];
-    let mut i = 0;
-    while i < 30 {
-        entries[i] = (DIST_SYM_TO_DIST_BASE[i] as u32) << 16
-            | (DIST_SYM_TO_DIST_EXTRA[i] as u32) << 8
-            | LITERAL_ENTRY;
-        i += 1;
-    }
-    entries
-};
-
-pub(crate) const FIXED_CODE_LENGTHS: [u8; 320] = make_fixed_code_lengths();
-const fn make_fixed_code_lengths() -> [u8; 320] {
-    let mut i = 0;
-    let mut lengths = [0; 320];
-    while i < 144 {
-        lengths[i] = 8;
-        i += 1;
-    }
-    while i < 256 {
-        lengths[i] = 9;
-        i += 1;
-    }
-    while i < 280 {
-        lengths[i] = 7;
-        i += 1;
-    }
-    while i < 288 {
-        lengths[i] = 8;
-        i += 1;
-    }
-    while i < 320 {
-        lengths[i] = 5;
-        i += 1;
-    }
-    lengths
-}
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/.cargo-checksum.json b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/.cargo-checksum.json
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/.cargo-checksum.json
rename to third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/.cargo-checksum.json
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/.cargo_vcs_info.json
new file mode 100644
index 0000000..fdba6e88
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/.cargo_vcs_info.json
@@ -0,0 +1,6 @@
+{
+  "git": {
+    "sha1": "c365c7e6ffa81feb2e1fb762eed7299f05c9b0ca"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/Cargo.lock b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/Cargo.lock
new file mode 100644
index 0000000..c6aeb0c
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/Cargo.lock
@@ -0,0 +1,163 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "byteorder"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "fdeflate"
+version = "0.3.7"
+dependencies = [
+ "miniz_oxide",
+ "rand",
+ "simd-adler32",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.161"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "simd-adler32"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
+
+[[package]]
+name = "syn"
+version = "2.0.85"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "zerocopy"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+dependencies = [
+ "byteorder",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/Cargo.toml
similarity index 98%
rename from third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/Cargo.toml
rename to third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/Cargo.toml
index 49a730b..0c3bc81 100644
--- a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/Cargo.toml
@@ -13,7 +13,7 @@
 edition = "2021"
 rust-version = "1.67.0"
 name = "fdeflate"
-version = "0.3.6"
+version = "0.3.7"
 authors = ["The image-rs Developers"]
 build = false
 include = [
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/Cargo.toml.orig b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/Cargo.toml.orig
similarity index 97%
rename from third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/Cargo.toml.orig
rename to third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/Cargo.toml.orig
index 1aec49f8..ba27b2e5 100644
--- a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/Cargo.toml.orig
+++ b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "fdeflate"
-version = "0.3.6"
+version = "0.3.7"
 edition = "2021"
 
 # note: when changed, also update test runner in `.github/workflows/rust.yml`
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/LICENSE-APACHE b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/LICENSE-APACHE
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/LICENSE-APACHE
rename to third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/LICENSE-APACHE
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/LICENSE-MIT b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/LICENSE-MIT
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/LICENSE-MIT
rename to third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/LICENSE-MIT
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/README.md b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/README.md
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/README.md
rename to third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/README.md
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/compress.rs b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/compress.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/compress.rs
rename to third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/compress.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/decompress.rs b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/decompress.rs
similarity index 93%
rename from third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/decompress.rs
rename to third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/decompress.rs
index 43f50f3..baba376 100644
--- a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/decompress.rs
+++ b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/decompress.rs
@@ -3,8 +3,8 @@
 use crate::{
     huffman::{self, build_table},
     tables::{
-        self, CLCL_ORDER, DIST_SYM_TO_DIST_BASE, DIST_SYM_TO_DIST_EXTRA, FIXED_CODE_LENGTHS,
-        LEN_SYM_TO_LEN_BASE, LEN_SYM_TO_LEN_EXTRA, LITLEN_TABLE_ENTRIES,
+        self, CLCL_ORDER, DIST_SYM_TO_DIST_BASE, DIST_SYM_TO_DIST_EXTRA, FIXED_DIST_TABLE,
+        FIXED_LITLEN_TABLE, LEN_SYM_TO_LEN_BASE, LEN_SYM_TO_LEN_EXTRA, LITLEN_TABLE_ENTRIES,
     },
 };
 
@@ -62,13 +62,12 @@
 pub const SECONDARY_TABLE_ENTRY: u32 = 0x2000;
 
 /// The Decompressor state for a compressed block.
-#[repr(align(64))]
 #[derive(Eq, PartialEq, Debug)]
 struct CompressedBlock {
-    litlen_table: [u32; 4096],
+    litlen_table: Box<[u32; 4096]>,
     secondary_table: Vec<u16>,
 
-    dist_table: [u32; 512],
+    dist_table: Box<[u32; 512]>,
     dist_secondary_table: Vec<u16>,
 
     eof_code: u16,
@@ -103,6 +102,7 @@
     queued_rle: Option<(u8, usize)>,
     queued_backref: Option<(usize, usize)>,
     last_block: bool,
+    fixed_table: bool,
 
     state: State,
     checksum: Adler32,
@@ -122,8 +122,8 @@
             buffer: 0,
             nbits: 0,
             compression: CompressedBlock {
-                litlen_table: [0; 4096],
-                dist_table: [0; 512],
+                litlen_table: Box::new([0; 4096]),
+                dist_table: Box::new([0; 512]),
                 secondary_table: Vec::new(),
                 dist_secondary_table: Vec::new(),
                 eof_code: 0,
@@ -145,6 +145,7 @@
             state: State::ZlibHeader,
             last_block: false,
             ignore_adler32: false,
+            fixed_table: false,
         }
     }
 
@@ -182,7 +183,7 @@
 
     fn read_block_header(&mut self, remaining_input: &mut &[u8]) -> Result<(), DecompressionError> {
         self.fill_buffer(remaining_input);
-        if self.nbits < 3 {
+        if self.nbits < 10 {
             return Ok(());
         }
 
@@ -209,8 +210,43 @@
             }
             0b01 => {
                 self.consume_bits(3);
-                // TODO: Do this statically rather than every time.
-                Self::build_tables(288, &FIXED_CODE_LENGTHS, &mut self.compression)?;
+
+                // Check for an entirely empty blocks which can happen if there are "partial
+                // flushes" in the deflate stream. With fixed huffman codes, the EOF symbol is
+                // 7-bits of zeros so we peak ahead and see if the next 7-bits are all zero.
+                if self.peak_bits(7) == 0 {
+                    self.consume_bits(7);
+                    if self.last_block {
+                        self.state = State::Checksum;
+                        return Ok(());
+                    }
+
+                    // At this point we've consumed the entire block and need to read the next block
+                    // header. If tail call optimization were guaranteed, we could just recurse
+                    // here. But without it, a long sequence of empty fixed-blocks might cause a
+                    // stack overflow. Instead, we consume all empty blocks in a loop and then
+                    // recurse. This is the only recursive call this function, and thus is safe.
+                    while self.nbits >= 10 && self.peak_bits(10) == 0b010 {
+                        self.consume_bits(10);
+                        self.fill_buffer(remaining_input);
+                    }
+                    return self.read_block_header(remaining_input);
+                }
+
+                // Build decoding tables if the previous block wasn't also a fixed block.
+                if !self.fixed_table {
+                    self.fixed_table = true;
+                    for chunk in self.compression.litlen_table.chunks_exact_mut(512) {
+                        chunk.copy_from_slice(&FIXED_LITLEN_TABLE);
+                    }
+                    for chunk in self.compression.dist_table.chunks_exact_mut(32) {
+                        chunk.copy_from_slice(&FIXED_DIST_TABLE);
+                    }
+                    self.compression.eof_bits = 7;
+                    self.compression.eof_code = 0;
+                    self.compression.eof_mask = 0x7f;
+                }
+
                 self.state = State::CompressedData;
                 Ok(())
             }
@@ -231,6 +267,7 @@
 
                 self.consume_bits(17);
                 self.state = State::CodeLengthCodes;
+                self.fixed_table = false;
                 Ok(())
             }
             0b11 => Err(DecompressionError::InvalidBlockType),
@@ -375,7 +412,7 @@
             &code_lengths[..hlit],
             &LITLEN_TABLE_ENTRIES,
             &mut codes[..hlit],
-            &mut compression.litlen_table,
+            &mut *compression.litlen_table,
             &mut compression.secondary_table,
             false,
             true,
@@ -397,7 +434,7 @@
                 lengths,
                 &tables::DISTANCE_TABLE_ENTRIES,
                 &mut dist_codes,
-                &mut compression.dist_table,
+                &mut *compression.dist_table,
                 &mut compression.dist_secondary_table,
                 true,
                 false,
@@ -1125,6 +1162,23 @@
     }
 
     #[test]
+    fn fixed_tables() {
+        let mut compression = CompressedBlock {
+            litlen_table: Box::new([0; 4096]),
+            dist_table: Box::new([0; 512]),
+            secondary_table: Vec::new(),
+            dist_secondary_table: Vec::new(),
+            eof_code: 0,
+            eof_mask: 0,
+            eof_bits: 0,
+        };
+        Decompressor::build_tables(288, &FIXED_CODE_LENGTHS, &mut compression).unwrap();
+
+        assert_eq!(compression.litlen_table[..512], FIXED_LITLEN_TABLE);
+        assert_eq!(compression.dist_table[..32], FIXED_DIST_TABLE);
+    }
+
+    #[test]
     fn it_works() {
         roundtrip(b"Hello world!");
     }
@@ -1229,6 +1283,7 @@
     }
 
     mod test_utils;
+    use tables::FIXED_CODE_LENGTHS;
     use test_utils::{decompress_by_chunks, TestDecompressionError};
 
     fn verify_no_sensitivity_to_input_chunking(
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/decompress/tests/test_utils.rs b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/decompress/tests/test_utils.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/decompress/tests/test_utils.rs
rename to third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/decompress/tests/test_utils.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/huffman.rs b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/huffman.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/huffman.rs
rename to third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/huffman.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/lib.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/lib.rs
rename to third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/lib.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/tables.rs b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/tables.rs
new file mode 100644
index 0000000..2b4c257
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/tables.rs
@@ -0,0 +1,221 @@
+use crate::decompress::{EXCEPTIONAL_ENTRY, LITERAL_ENTRY};
+
+/// Hard-coded Huffman codes used regardless of the input.
+///
+/// These values work well for PNGs with some form of filtering enabled, but will likely make most
+/// other inputs worse.
+pub(crate) const HUFFMAN_LENGTHS: [u8; 286] = [
+    2, 3, 4, 5, 5, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 10, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 8, 9, 8, 8, 8, 8, 8, 7,
+    7, 7, 6, 6, 6, 5, 4, 3, 12, 12, 12, 9, 9, 11, 10, 11, 11, 10, 11, 11, 11, 11, 11, 11, 12, 11,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 9,
+];
+
+pub(crate) const HUFFMAN_CODES: [u16; 286] = match crate::compute_codes(&HUFFMAN_LENGTHS) {
+    Some(codes) => codes,
+    None => panic!("HUFFMAN_LENGTHS is invalid"),
+};
+
+/// Length code for length values (derived from deflate spec).
+pub(crate) const LENGTH_TO_SYMBOL: [u16; 256] = [
+    257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268, 269, 269, 269,
+    269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272, 273, 273, 273, 273, 273, 273,
+    273, 273, 274, 274, 274, 274, 274, 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276,
+    276, 276, 276, 276, 276, 276, 276, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+    277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
+    278, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 280, 280,
+    280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 281, 281, 281, 281, 281,
+    281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
+    281, 281, 281, 281, 281, 281, 281, 281, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
+    282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
+    282, 282, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
+    283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 284, 284, 284, 284,
+    284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+    284, 284, 284, 284, 284, 284, 284, 284, 285,
+];
+
+/// Number of extra bits for length values (derived from deflate spec).
+pub(crate) const LENGTH_TO_LEN_EXTRA: [u8; 256] = [
+    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0,
+];
+
+pub(crate) const BITMASKS: [u32; 17] = [
+    0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF,
+    0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF,
+];
+
+/// Order of the length code length alphabet (derived from deflate spec).
+pub(crate) const CLCL_ORDER: [usize; 19] = [
+    16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15,
+];
+
+/// Number of extra bits for each length code (derived from deflate spec).
+pub(crate) const LEN_SYM_TO_LEN_EXTRA: [u8; 29] = [
+    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0,
+];
+
+/// The base length for each length code (derived from deflate spec).
+pub(crate) const LEN_SYM_TO_LEN_BASE: [usize; 29] = [
+    3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131,
+    163, 195, 227, 258,
+];
+
+/// Number of extra bits for each distance code (derived from deflate spec.)
+pub(crate) const DIST_SYM_TO_DIST_EXTRA: [u8; 30] = [
+    0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13,
+    13,
+];
+
+/// The base distance for each distance code (derived from deflate spec).
+pub(crate) const DIST_SYM_TO_DIST_BASE: [u16; 30] = [
+    1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537,
+    2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577,
+];
+
+/// The main litlen_table uses a 12-bit input to lookup the meaning of the symbol. The table is
+/// split into 4 sections:
+///
+///   aaaaaaaa_bbbbbbbb_1000yyyy_0000xxxx  x = input_advance_bits, y = output_advance_bytes (literal)
+///   0000000z_zzzzzzzz_00000yyy_0000xxxx  x = input_advance_bits, y = extra_bits, z = distance_base (length)
+///   00000000_00000000_01000000_0000xxxx  x = input_advance_bits (EOF)
+///   0000xxxx_xxxxxxxx_01100000_00000000  x = secondary_table_index
+///   00000000_00000000_01000000_00000000  invalid code
+pub(crate) const LITLEN_TABLE_ENTRIES: [u32; 288] = {
+    let mut entries = [EXCEPTIONAL_ENTRY; 288];
+    let mut i = 0;
+    while i < 256 {
+        entries[i] = (i as u32) << 16 | LITERAL_ENTRY | (1 << 8);
+        i += 1;
+    }
+
+    let mut i = 257;
+    while i < 286 {
+        entries[i] = (LEN_SYM_TO_LEN_BASE[i - 257] as u32) << 16
+            | (LEN_SYM_TO_LEN_EXTRA[i - 257] as u32) << 8;
+        i += 1;
+    }
+    entries
+};
+
+/// The distance table is a 512-entry table that maps 9 bits of distance symbols to their meaning.
+///
+///   00000000_00000000_00000000_00000000     symbol is more than 9 bits
+///   zzzzzzzz_zzzzzzzz_0000yyyy_0000xxxx     x = input_advance_bits, y = extra_bits, z = distance_base
+pub(crate) const DISTANCE_TABLE_ENTRIES: [u32; 32] = {
+    let mut entries = [0; 32];
+    let mut i = 0;
+    while i < 30 {
+        entries[i] = (DIST_SYM_TO_DIST_BASE[i] as u32) << 16
+            | (DIST_SYM_TO_DIST_EXTRA[i] as u32) << 8
+            | LITERAL_ENTRY;
+        i += 1;
+    }
+    entries
+};
+
+pub(crate) const FIXED_LITLEN_TABLE: [u32; 512] = [
+    16391, 5275912, 1081608, 7537672, 2032135, 7373064, 3178760, 12615945, 655367, 6324488,
+    2130184, 10518793, 33032, 8421640, 4227336, 14713097, 393223, 5800200, 1605896, 9470217,
+    3867399, 7897352, 3703048, 13664521, 1114375, 6848776, 2654472, 11567369, 557320, 8945928,
+    4751624, 15761673, 262151, 5538056, 1343752, 14877960, 2818823, 7635208, 3440904, 13140233,
+    852231, 6586632, 2392328, 11043081, 295176, 8683784, 4489480, 15237385, 524295, 6062344,
+    1868040, 9994505, 5440519, 8159496, 3965192, 14188809, 1507847, 7110920, 2916616, 12091657,
+    819464, 9208072, 5013768, 16285961, 196615, 5406984, 1212680, 10683656, 2294535, 7504136,
+    3309832, 12878089, 721159, 6455560, 2261256, 10780937, 164104, 8552712, 4358408, 14975241,
+    458759, 5931272, 1736968, 9732361, 4391943, 8028424, 3834120, 13926665, 1245703, 6979848,
+    2785544, 11829513, 688392, 9077000, 4882696, 16023817, 327687, 5669128, 1474824, 16392,
+    3343111, 7766280, 3571976, 13402377, 983303, 6717704, 2523400, 11305225, 426248, 8814856,
+    4620552, 15499529, 589831, 6193416, 1999112, 10256649, 6489095, 8290568, 4096264, 14450953,
+    1769991, 7241992, 3047688, 12353801, 950536, 9339144, 5144840, 16548105, 16391, 5341448,
+    1147144, 8586504, 2032135, 7438600, 3244296, 12747017, 655367, 6390024, 2195720, 10649865,
+    98568, 8487176, 4292872, 14844169, 393223, 5865736, 1671432, 9601289, 3867399, 7962888,
+    3768584, 13795593, 1114375, 6914312, 2720008, 11698441, 622856, 9011464, 4817160, 15892745,
+    262151, 5603592, 1409288, 16908296, 2818823, 7700744, 3506440, 13271305, 852231, 6652168,
+    2457864, 11174153, 360712, 8749320, 4555016, 15368457, 524295, 6127880, 1933576, 10125577,
+    5440519, 8225032, 4030728, 14319881, 1507847, 7176456, 2982152, 12222729, 885000, 9273608,
+    5079304, 16417033, 196615, 5472520, 1278216, 12780808, 2294535, 7569672, 3375368, 13009161,
+    721159, 6521096, 2326792, 10912009, 229640, 8618248, 4423944, 15106313, 458759, 5996808,
+    1802504, 9863433, 4391943, 8093960, 3899656, 14057737, 1245703, 7045384, 2851080, 11960585,
+    753928, 9142536, 4948232, 16154889, 327687, 5734664, 1540360, 16392, 3343111, 7831816, 3637512,
+    13533449, 983303, 6783240, 2588936, 11436297, 491784, 8880392, 4686088, 15630601, 589831,
+    6258952, 2064648, 10387721, 6489095, 8356104, 4161800, 14582025, 1769991, 7307528, 3113224,
+    12484873, 1016072, 9404680, 5210376, 16679177, 16391, 5275912, 1081608, 7537672, 2032135,
+    7373064, 3178760, 12681481, 655367, 6324488, 2130184, 10584329, 33032, 8421640, 4227336,
+    14778633, 393223, 5800200, 1605896, 9535753, 3867399, 7897352, 3703048, 13730057, 1114375,
+    6848776, 2654472, 11632905, 557320, 8945928, 4751624, 15827209, 262151, 5538056, 1343752,
+    14877960, 2818823, 7635208, 3440904, 13205769, 852231, 6586632, 2392328, 11108617, 295176,
+    8683784, 4489480, 15302921, 524295, 6062344, 1868040, 10060041, 5440519, 8159496, 3965192,
+    14254345, 1507847, 7110920, 2916616, 12157193, 819464, 9208072, 5013768, 16351497, 196615,
+    5406984, 1212680, 10683656, 2294535, 7504136, 3309832, 12943625, 721159, 6455560, 2261256,
+    10846473, 164104, 8552712, 4358408, 15040777, 458759, 5931272, 1736968, 9797897, 4391943,
+    8028424, 3834120, 13992201, 1245703, 6979848, 2785544, 11895049, 688392, 9077000, 4882696,
+    16089353, 327687, 5669128, 1474824, 16392, 3343111, 7766280, 3571976, 13467913, 983303,
+    6717704, 2523400, 11370761, 426248, 8814856, 4620552, 15565065, 589831, 6193416, 1999112,
+    10322185, 6489095, 8290568, 4096264, 14516489, 1769991, 7241992, 3047688, 12419337, 950536,
+    9339144, 5144840, 16613641, 16391, 5341448, 1147144, 8586504, 2032135, 7438600, 3244296,
+    12812553, 655367, 6390024, 2195720, 10715401, 98568, 8487176, 4292872, 14909705, 393223,
+    5865736, 1671432, 9666825, 3867399, 7962888, 3768584, 13861129, 1114375, 6914312, 2720008,
+    11763977, 622856, 9011464, 4817160, 15958281, 262151, 5603592, 1409288, 16908296, 2818823,
+    7700744, 3506440, 13336841, 852231, 6652168, 2457864, 11239689, 360712, 8749320, 4555016,
+    15433993, 524295, 6127880, 1933576, 10191113, 5440519, 8225032, 4030728, 14385417, 1507847,
+    7176456, 2982152, 12288265, 885000, 9273608, 5079304, 16482569, 196615, 5472520, 1278216,
+    12780808, 2294535, 7569672, 3375368, 13074697, 721159, 6521096, 2326792, 10977545, 229640,
+    8618248, 4423944, 15171849, 458759, 5996808, 1802504, 9928969, 4391943, 8093960, 3899656,
+    14123273, 1245703, 7045384, 2851080, 12026121, 753928, 9142536, 4948232, 16220425, 327687,
+    5734664, 1540360, 16392, 3343111, 7831816, 3637512, 13598985, 983303, 6783240, 2588936,
+    11501833, 491784, 8880392, 4686088, 15696137, 589831, 6258952, 2064648, 10453257, 6489095,
+    8356104, 4161800, 14647561, 1769991, 7307528, 3113224, 12550409, 1016072, 9404680, 5210376,
+    16744713,
+];
+
+pub(crate) const FIXED_DIST_TABLE: [u32; 32] = [
+    98309, 16877317, 1147653, 268536581, 360709, 67209477, 4293893, 1073843461, 229381, 33654789,
+    2196485, 536972293, 623109, 134318597, 8488453, 5, 163845, 25265925, 1671941, 402754309,
+    491781, 100763909, 6391045, 1610714373, 294917, 50432005, 3245061, 805407749, 885253,
+    201427461, 12682757, 5,
+];
+
+#[cfg(test)]
+pub(crate) const FIXED_CODE_LENGTHS: [u8; 320] = make_fixed_code_lengths();
+
+#[cfg(test)]
+const fn make_fixed_code_lengths() -> [u8; 320] {
+    let mut i = 0;
+    let mut lengths = [0; 320];
+    while i < 144 {
+        lengths[i] = 8;
+        i += 1;
+    }
+    while i < 256 {
+        lengths[i] = 9;
+        i += 1;
+    }
+    while i < 280 {
+        lengths[i] = 7;
+        i += 1;
+    }
+    while i < 288 {
+        lengths[i] = 8;
+        i += 1;
+    }
+    while i < 320 {
+        lengths[i] = 5;
+        i += 1;
+    }
+    lengths
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/tests/input-chunking-sensitivity-example1.zz b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/tests/input-chunking-sensitivity-example1.zz
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/tests/input-chunking-sensitivity-example1.zz
rename to third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/tests/input-chunking-sensitivity-example1.zz
Binary files differ
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/tests/input-chunking-sensitivity-example2.zz b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/tests/input-chunking-sensitivity-example2.zz
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/tests/input-chunking-sensitivity-example2.zz
rename to third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/tests/input-chunking-sensitivity-example2.zz
Binary files differ
diff --git a/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/tests/input-chunking-sensitivity-example3.zz b/third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/tests/input-chunking-sensitivity-example3.zz
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/tests/input-chunking-sensitivity-example3.zz
rename to third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/tests/input-chunking-sensitivity-example3.zz
Binary files differ
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/.cargo_vcs_info.json
deleted file mode 100644
index d42731a..0000000
--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/.cargo_vcs_info.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "git": {
-    "sha1": "347dc5dd3ddee8d2d3ef77a2f03a7d59b6c6fe80"
-  },
-  "path_in_vcs": ""
-}
\ No newline at end of file
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/README.md b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/README.md
deleted file mode 100644
index 2b7bac5..0000000
--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/README.md
+++ /dev/null
@@ -1,37 +0,0 @@
-# PNG Decoder/Encoder
-[![Build Status](https://github.com/image-rs/image-png/workflows/Rust%20CI/badge.svg)](https://github.com/image-rs/image-png/actions)
-[![Documentation](https://docs.rs/png/badge.svg)](https://docs.rs/png)
-[![Crates.io](https://img.shields.io/crates/v/png.svg)](https://crates.io/crates/png)
-[![License](https://img.shields.io/crates/l/png.svg)](https://github.com/image-rs/image-png)
-
-PNG decoder/encoder in pure Rust.
-
-It contains all features required to handle the entirety of [the PngSuite by
-Willem van Schack][PngSuite].
-
-[PngSuite]: http://www.schaik.com/pngsuite2011/pngsuite.html
-
-## pngcheck
-
-The `pngcheck` utility is a small demonstration binary that checks and prints
-metadata on every `.png` image provided via parameter. You can run it (for
-example on the test directories) with
-
-```bash
-cargo run --release --example pngcheck ./tests/pngsuite/*
-```
-
-## License
-
-Licensed under either of
-
- * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
- * MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)
-
-at your option.
-
-### Contribution
-
-Unless you explicitly state otherwise, any contribution intentionally submitted
-for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
-additional terms or conditions.
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/.cargo-checksum.json b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/.cargo-checksum.json
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/.cargo-checksum.json
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/.cargo-checksum.json
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.15/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/.cargo_vcs_info.json
new file mode 100644
index 0000000..e357af3
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/.cargo_vcs_info.json
@@ -0,0 +1,6 @@
+{
+  "git": {
+    "sha1": "10644dbff4d5b5614199cbc81145838abdafd98c"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/CHANGES.md b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/CHANGES.md
similarity index 84%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/CHANGES.md
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/CHANGES.md
index d895e73..6d7a818 100644
--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/CHANGES.md
+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/CHANGES.md
@@ -1,3 +1,36 @@
+## 0.17.15
+
+### Added
+
+* Add a public API to advance to the next frame in APNG decoder ([#518])
+* Add APIs to write ICC and EXIF chunks ([#526])
+* Add support for parsing the sBIT chunk ([#524])
+* Add support for parsing the bKGD chunk ([#538])
+* Add support for parsing the cICP chunk ([#529])
+* Add support for parsing mDCv and cLLi chunks ([#528], ([#543]))
+
+### Changed
+
+* Improve performance of Paeth filter during decoding ([#512], [#539])
+
+### Fixed
+
+* Avoid an infinite loop when retrying after a fatal error using `StreamingDecoder` ([#520])
+* Fixed chunk order in encoded files ([#526])
+
+[#495]: https://github.com/image-rs/image-png/pull/495
+[#496]: https://github.com/image-rs/image-png/pull/496
+[#512]: https://github.com/image-rs/image-png/pull/512
+[#518]: https://github.com/image-rs/image-png/pull/518
+[#520]: https://github.com/image-rs/image-png/pull/520
+[#524]: https://github.com/image-rs/image-png/pull/524
+[#526]: https://github.com/image-rs/image-png/pull/526
+[#528]: https://github.com/image-rs/image-png/pull/528
+[#529]: https://github.com/image-rs/image-png/pull/529
+[#538]: https://github.com/image-rs/image-png/pull/538
+[#539]: https://github.com/image-rs/image-png/pull/539
+[#543]: https://github.com/image-rs/image-png/pull/543
+
 ## 0.17.14
 
 * Updated to miniz_oxide 0.8.0.
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/Cargo.lock b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/Cargo.lock
similarity index 74%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/Cargo.lock
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/Cargo.lock
index c71b175..7ac528d 100644
--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/Cargo.lock
+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/Cargo.lock
@@ -4,32 +4,44 @@
 
 [[package]]
 name = "addr2line"
-version = "0.17.0"
+version = "0.24.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
+checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
 dependencies = [
  "gimli",
 ]
 
 [[package]]
-name = "adler"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
-
-[[package]]
 name = "adler2"
 version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
 
 [[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
 name = "anes"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
 
 [[package]]
+name = "approx"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
 name = "arrayref"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -54,23 +66,23 @@
 
 [[package]]
 name = "autocfg"
-version = "1.1.0"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
 
 [[package]]
 name = "backtrace"
-version = "0.3.64"
+version = "0.3.74"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f"
+checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
 dependencies = [
  "addr2line",
- "cc",
  "cfg-if",
  "libc",
- "miniz_oxide 0.4.4",
+ "miniz_oxide",
  "object",
  "rustc-demangle",
+ "windows-targets 0.52.6",
 ]
 
 [[package]]
@@ -93,15 +105,15 @@
 
 [[package]]
 name = "bumpalo"
-version = "3.9.1"
+version = "3.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
+checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
 
 [[package]]
 name = "bytemuck"
-version = "1.18.0"
+version = "1.20.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae"
+checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a"
 
 [[package]]
 name = "byteorder"
@@ -131,9 +143,9 @@
 
 [[package]]
 name = "cc"
-version = "1.1.22"
+version = "1.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0"
+checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d"
 dependencies = [
  "shlex",
 ]
@@ -190,7 +202,7 @@
  "bitflags 1.3.2",
  "clap_derive",
  "clap_lex",
- "indexmap",
+ "indexmap 1.9.3",
  "once_cell",
  "strsim",
  "termcolor",
@@ -207,7 +219,7 @@
  "proc-macro-error",
  "proc-macro2",
  "quote",
- "syn 1.0.86",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -221,49 +233,64 @@
 
 [[package]]
 name = "cmake"
-version = "0.1.51"
+version = "0.1.52"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a"
+checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e"
 dependencies = [
  "cc",
 ]
 
 [[package]]
 name = "cocoa"
-version = "0.24.0"
+version = "0.24.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832"
+checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a"
 dependencies = [
  "bitflags 1.3.2",
  "block",
  "cocoa-foundation",
  "core-foundation",
- "core-graphics",
+ "core-graphics 0.22.3",
  "foreign-types 0.3.2",
  "libc",
  "objc",
 ]
 
 [[package]]
+name = "cocoa"
+version = "0.25.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c"
+dependencies = [
+ "bitflags 1.3.2",
+ "block",
+ "cocoa-foundation",
+ "core-foundation",
+ "core-graphics 0.23.2",
+ "foreign-types 0.5.0",
+ "libc",
+ "objc",
+]
+
+[[package]]
 name = "cocoa-foundation"
-version = "0.1.0"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318"
+checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7"
 dependencies = [
  "bitflags 1.3.2",
  "block",
  "core-foundation",
  "core-graphics-types",
- "foreign-types 0.3.2",
  "libc",
  "objc",
 ]
 
 [[package]]
 name = "core-foundation"
-version = "0.9.3"
+version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
+checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
 dependencies = [
  "core-foundation-sys",
  "libc",
@@ -271,9 +298,9 @@
 
 [[package]]
 name = "core-foundation-sys"
-version = "0.8.3"
+version = "0.8.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
 
 [[package]]
 name = "core-graphics"
@@ -289,34 +316,46 @@
 ]
 
 [[package]]
-name = "core-graphics-types"
-version = "0.1.1"
+name = "core-graphics"
+version = "0.23.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b"
+checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081"
 dependencies = [
  "bitflags 1.3.2",
  "core-foundation",
- "foreign-types 0.3.2",
+ "core-graphics-types",
+ "foreign-types 0.5.0",
+ "libc",
+]
+
+[[package]]
+name = "core-graphics-types"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf"
+dependencies = [
+ "bitflags 1.3.2",
+ "core-foundation",
  "libc",
 ]
 
 [[package]]
 name = "core-text"
-version = "19.2.0"
+version = "20.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25"
+checksum = "c9d2790b5c08465d49f8dc05c8bcae9fea467855947db39b0f8145c091aaced5"
 dependencies = [
  "core-foundation",
- "core-graphics",
- "foreign-types 0.3.2",
+ "core-graphics 0.23.2",
+ "foreign-types 0.5.0",
  "libc",
 ]
 
 [[package]]
 name = "crc32fast"
-version = "1.3.2"
+version = "1.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
+checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
 dependencies = [
  "cfg-if",
 ]
@@ -358,59 +397,40 @@
 ]
 
 [[package]]
-name = "crossbeam-channel"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa"
-dependencies = [
- "cfg-if",
- "crossbeam-utils",
-]
-
-[[package]]
 name = "crossbeam-deque"
-version = "0.8.1"
+version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
+checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
 dependencies = [
- "cfg-if",
  "crossbeam-epoch",
  "crossbeam-utils",
 ]
 
 [[package]]
 name = "crossbeam-epoch"
-version = "0.9.7"
+version = "0.9.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c00d6d2ea26e8b151d99093005cb442fb9a37aeaca582a03ec70946f49ab5ed9"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
 dependencies = [
- "cfg-if",
  "crossbeam-utils",
- "lazy_static",
- "memoffset",
- "scopeguard",
 ]
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.7"
+version = "0.8.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6"
-dependencies = [
- "cfg-if",
- "lazy_static",
-]
+checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
 
 [[package]]
 name = "crossfont"
-version = "0.5.1"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21fd3add36ea31aba1520aa5288714dd63be506106753226d0eb387a93bc9c45"
+checksum = "3eb5a3822b594afc99b503cc1859b94686d3c3efdd60507a28587dab80ee1071"
 dependencies = [
- "cocoa",
+ "cocoa 0.25.0",
  "core-foundation",
  "core-foundation-sys",
- "core-graphics",
+ "core-graphics 0.23.2",
  "core-text",
  "dwrote",
  "foreign-types 0.5.0",
@@ -438,9 +458,9 @@
 
 [[package]]
 name = "darling"
-version = "0.13.1"
+version = "0.13.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4"
+checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
 dependencies = [
  "darling_core",
  "darling_macro",
@@ -448,27 +468,27 @@
 
 [[package]]
 name = "darling_core"
-version = "0.13.1"
+version = "0.13.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324"
+checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
 dependencies = [
  "fnv",
  "ident_case",
  "proc-macro2",
  "quote",
  "strsim",
- "syn 1.0.86",
+ "syn 1.0.109",
 ]
 
 [[package]]
 name = "darling_macro"
-version = "0.13.1"
+version = "0.13.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b"
+checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
 dependencies = [
  "darling_core",
  "quote",
- "syn 1.0.86",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -500,24 +520,24 @@
 
 [[package]]
 name = "dlib"
-version = "0.5.0"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794"
+checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"
 dependencies = [
- "libloading",
+ "libloading 0.8.6",
 ]
 
 [[package]]
 name = "downcast-rs"
-version = "1.2.0"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
+checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
 
 [[package]]
 name = "dwrote"
-version = "0.11.1"
+version = "0.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2da3498378ed373237bdef1eddcc64e7be2d3ba4841f4c22a998e81cadeea83c"
+checksum = "70182709525a3632b2ba96b6569225467b18ecb4a77f46d255f713a6bebf05fd"
 dependencies = [
  "lazy_static",
  "libc",
@@ -529,9 +549,15 @@
 
 [[package]]
 name = "either"
-version = "1.6.1"
+version = "1.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
+checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
+
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
 
 [[package]]
 name = "expat-sys"
@@ -545,21 +571,21 @@
 
 [[package]]
 name = "fdeflate"
-version = "0.3.5"
+version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8090f921a24b04994d9929e204f50b498a33ea6ba559ffaa05e04f7ee7fb5ab"
+checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c"
 dependencies = [
  "simd-adler32",
 ]
 
 [[package]]
 name = "flate2"
-version = "1.0.24"
+version = "1.0.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
+checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
 dependencies = [
  "crc32fast",
- "miniz_oxide 0.5.3",
+ "miniz_oxide",
 ]
 
 [[package]]
@@ -595,7 +621,7 @@
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.79",
+ "syn 2.0.90",
 ]
 
 [[package]]
@@ -643,9 +669,9 @@
 
 [[package]]
 name = "getrandom"
-version = "0.2.4"
+version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
 dependencies = [
  "cfg-if",
  "libc",
@@ -654,9 +680,9 @@
 
 [[package]]
 name = "gimli"
-version = "0.26.1"
+version = "0.31.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
+checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
 
 [[package]]
 name = "gl_generator"
@@ -687,9 +713,9 @@
 
 [[package]]
 name = "glob"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
 
 [[package]]
 name = "glutin"
@@ -698,13 +724,13 @@
 checksum = "444c9ad294fdcaf20ccf6726b78f380b5450275540c9b68ab62f49726ad1c713"
 dependencies = [
  "cgl",
- "cocoa",
+ "cocoa 0.24.1",
  "core-foundation",
  "glutin_egl_sys",
  "glutin_gles2_sys",
  "glutin_glx_sys",
  "glutin_wgl_sys",
- "libloading",
+ "libloading 0.7.4",
  "log",
  "objc",
  "once_cell",
@@ -773,6 +799,12 @@
 checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
 
 [[package]]
+name = "hashbrown"
+version = "0.15.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
+
+[[package]]
 name = "heck"
 version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -800,14 +832,24 @@
 checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
 dependencies = [
  "autocfg",
- "hashbrown",
+ "hashbrown 0.12.3",
+]
+
+[[package]]
+name = "indexmap"
+version = "2.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
+dependencies = [
+ "equivalent",
+ "hashbrown 0.15.2",
 ]
 
 [[package]]
 name = "instant"
-version = "0.1.12"
+version = "0.1.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
 dependencies = [
  "cfg-if",
  "js-sys",
@@ -817,18 +859,18 @@
 
 [[package]]
 name = "itertools"
-version = "0.10.3"
+version = "0.10.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
 dependencies = [
  "either",
 ]
 
 [[package]]
 name = "itoa"
-version = "1.0.1"
+version = "1.0.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
+checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
 
 [[package]]
 name = "jni-sys"
@@ -838,10 +880,11 @@
 
 [[package]]
 name = "js-sys"
-version = "0.3.56"
+version = "0.3.76"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04"
+checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7"
 dependencies = [
+ "once_cell",
  "wasm-bindgen",
 ]
 
@@ -853,43 +896,61 @@
 
 [[package]]
 name = "lazy_static"
-version = "1.4.0"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
 
 [[package]]
 name = "libc"
-version = "0.2.159"
+version = "0.2.167"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
+checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc"
 
 [[package]]
 name = "libloading"
-version = "0.7.3"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
+checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
 dependencies = [
  "cfg-if",
  "winapi",
 ]
 
 [[package]]
-name = "lock_api"
-version = "0.4.6"
+name = "libloading"
+version = "0.8.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b"
+checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
 dependencies = [
+ "cfg-if",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "libredox"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
+dependencies = [
+ "bitflags 2.6.0",
+ "libc",
+]
+
+[[package]]
+name = "lock_api"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
+dependencies = [
+ "autocfg",
  "scopeguard",
 ]
 
 [[package]]
 name = "log"
-version = "0.4.14"
+version = "0.4.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
-dependencies = [
- "cfg-if",
-]
+checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
 
 [[package]]
 name = "malloc_buf"
@@ -902,9 +963,9 @@
 
 [[package]]
 name = "memchr"
-version = "2.4.1"
+version = "2.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
 
 [[package]]
 name = "memmap2"
@@ -925,41 +986,6 @@
 ]
 
 [[package]]
-name = "minimal-lexical"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
-
-[[package]]
-name = "miniz_oxide"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
-dependencies = [
- "adler",
- "autocfg",
-]
-
-[[package]]
-name = "miniz_oxide"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
-dependencies = [
- "adler",
-]
-
-[[package]]
-name = "miniz_oxide"
-version = "0.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
-dependencies = [
- "adler",
- "simd-adler32",
-]
-
-[[package]]
 name = "miniz_oxide"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -971,24 +997,14 @@
 
 [[package]]
 name = "mio"
-version = "0.8.0"
+version = "0.8.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2"
+checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
 dependencies = [
  "libc",
  "log",
- "miow",
- "ntapi",
- "winapi",
-]
-
-[[package]]
-name = "miow"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
-dependencies = [
- "winapi",
+ "wasi",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -1037,7 +1053,7 @@
  "proc-macro-crate",
  "proc-macro2",
  "quote",
- "syn 1.0.86",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -1051,19 +1067,6 @@
 
 [[package]]
 name = "nix"
-version = "0.22.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf"
-dependencies = [
- "bitflags 1.3.2",
- "cc",
- "cfg-if",
- "libc",
- "memoffset",
-]
-
-[[package]]
-name = "nix"
 version = "0.24.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069"
@@ -1071,6 +1074,7 @@
  "bitflags 1.3.2",
  "cfg-if",
  "libc",
+ "memoffset",
 ]
 
 [[package]]
@@ -1087,63 +1091,33 @@
 ]
 
 [[package]]
-name = "nom"
-version = "7.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109"
-dependencies = [
- "memchr",
- "minimal-lexical",
- "version_check",
-]
-
-[[package]]
-name = "ntapi"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
-dependencies = [
- "winapi",
-]
-
-[[package]]
 name = "num-traits"
-version = "0.2.14"
+version = "0.2.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
 dependencies = [
  "autocfg",
 ]
 
 [[package]]
-name = "num_cpus"
-version = "1.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
-dependencies = [
- "hermit-abi",
- "libc",
-]
-
-[[package]]
 name = "num_enum"
-version = "0.5.6"
+version = "0.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "720d3ea1055e4e4574c0c0b0f8c3fd4f24c4cdaf465948206dea090b57b526ad"
+checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9"
 dependencies = [
  "num_enum_derive",
 ]
 
 [[package]]
 name = "num_enum_derive"
-version = "0.5.6"
+version = "0.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d992b768490d7fe0d8586d9b5745f6c49f557da6d81dc982b1d167ad4edbb21"
+checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799"
 dependencies = [
  "proc-macro-crate",
  "proc-macro2",
  "quote",
- "syn 1.0.86",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -1157,24 +1131,24 @@
 
 [[package]]
 name = "object"
-version = "0.27.1"
+version = "0.36.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9"
+checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "once_cell"
-version = "1.19.0"
+version = "1.20.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
 
 [[package]]
 name = "oorandom"
-version = "11.1.3"
+version = "11.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
+checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
 
 [[package]]
 name = "os_str_bytes"
@@ -1209,28 +1183,28 @@
 dependencies = [
  "cfg-if",
  "libc",
- "redox_syscall 0.5.6",
+ "redox_syscall",
  "smallvec",
- "windows-targets",
+ "windows-targets 0.52.6",
 ]
 
 [[package]]
 name = "percent-encoding"
-version = "2.1.0"
+version = "2.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
 
 [[package]]
 name = "pkg-config"
-version = "0.3.24"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
+checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
 
 [[package]]
 name = "plotters"
-version = "0.3.1"
+version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a"
+checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747"
 dependencies = [
  "num-traits",
  "plotters-backend",
@@ -1241,36 +1215,37 @@
 
 [[package]]
 name = "plotters-backend"
-version = "0.3.2"
+version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c"
+checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a"
 
 [[package]]
 name = "plotters-svg"
-version = "0.3.1"
+version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9"
+checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670"
 dependencies = [
  "plotters-backend",
 ]
 
 [[package]]
 name = "png"
-version = "0.17.13"
+version = "0.17.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1"
+checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0"
 dependencies = [
  "bitflags 1.3.2",
  "crc32fast",
  "fdeflate",
  "flate2",
- "miniz_oxide 0.7.4",
+ "miniz_oxide",
 ]
 
 [[package]]
 name = "png"
-version = "0.17.14"
+version = "0.17.15"
 dependencies = [
+ "approx",
  "bitflags 1.3.2",
  "byteorder",
  "clap",
@@ -1281,25 +1256,28 @@
  "getopts",
  "glium",
  "glob",
- "miniz_oxide 0.8.0",
+ "miniz_oxide",
  "rand",
  "term",
 ]
 
 [[package]]
 name = "ppv-lite86"
-version = "0.2.16"
+version = "0.2.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+dependencies = [
+ "zerocopy",
+]
 
 [[package]]
 name = "proc-macro-crate"
-version = "1.1.3"
+version = "1.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
+checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
 dependencies = [
- "thiserror",
- "toml",
+ "once_cell",
+ "toml_edit",
 ]
 
 [[package]]
@@ -1311,7 +1289,7 @@
  "proc-macro-error-attr",
  "proc-macro2",
  "quote",
- "syn 1.0.86",
+ "syn 1.0.109",
  "version_check",
 ]
 
@@ -1328,9 +1306,9 @@
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.86"
+version = "1.0.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
+checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
 dependencies = [
  "unicode-ident",
 ]
@@ -1367,9 +1345,9 @@
 
 [[package]]
 name = "rand_core"
-version = "0.6.3"
+version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
 dependencies = [
  "getrandom",
 ]
@@ -1391,89 +1369,90 @@
 
 [[package]]
 name = "rayon"
-version = "1.5.1"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
+checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
 dependencies = [
- "autocfg",
- "crossbeam-deque",
  "either",
  "rayon-core",
 ]
 
 [[package]]
 name = "rayon-core"
-version = "1.9.1"
+version = "1.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
+checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
 dependencies = [
- "crossbeam-channel",
  "crossbeam-deque",
  "crossbeam-utils",
- "lazy_static",
- "num_cpus",
 ]
 
 [[package]]
 name = "redox_syscall"
-version = "0.2.10"
+version = "0.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
-dependencies = [
- "bitflags 1.3.2",
-]
-
-[[package]]
-name = "redox_syscall"
-version = "0.5.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "355ae415ccd3a04315d3f8246e86d67689ea74d88d915576e1589a351062a13b"
+checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
 dependencies = [
  "bitflags 2.6.0",
 ]
 
 [[package]]
 name = "redox_users"
-version = "0.4.0"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
+checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
 dependencies = [
  "getrandom",
- "redox_syscall 0.2.10",
+ "libredox",
+ "thiserror",
 ]
 
 [[package]]
 name = "regex"
-version = "1.5.4"
+version = "1.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
 dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+dependencies = [
+ "aho-corasick",
+ "memchr",
  "regex-syntax",
 ]
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.25"
+version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.21"
+version = "0.1.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
+checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
 
 [[package]]
 name = "rustversion"
-version = "1.0.6"
+version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
+checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
 
 [[package]]
 name = "ryu"
-version = "1.0.9"
+version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
+checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
 
 [[package]]
 name = "safe_arch"
@@ -1495,15 +1474,15 @@
 
 [[package]]
 name = "scoped-tls"
-version = "1.0.0"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
+checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
 
 [[package]]
 name = "scopeguard"
-version = "1.1.0"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
 
 [[package]]
 name = "sctk-adwaita"
@@ -1519,31 +1498,32 @@
 
 [[package]]
 name = "serde"
-version = "1.0.136"
+version = "1.0.215"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
+checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.136"
+version = "1.0.215"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
+checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.86",
+ "syn 2.0.90",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.79"
+version = "1.0.133"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
+checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
 dependencies = [
  "itoa",
+ "memchr",
  "ryu",
  "serde",
 ]
@@ -1602,9 +1582,9 @@
 
 [[package]]
 name = "smallvec"
-version = "1.8.0"
+version = "1.13.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
+checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
 
 [[package]]
 name = "smithay-client-toolkit"
@@ -1633,20 +1613,20 @@
 
 [[package]]
 name = "syn"
-version = "1.0.86"
+version = "1.0.109"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
 dependencies = [
  "proc-macro2",
  "quote",
- "unicode-xid",
+ "unicode-ident",
 ]
 
 [[package]]
 name = "syn"
-version = "2.0.79"
+version = "2.0.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
+checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1687,22 +1667,22 @@
 
 [[package]]
 name = "thiserror"
-version = "1.0.30"
+version = "1.0.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.30"
+version = "1.0.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.86",
+ "syn 2.0.90",
 ]
 
 [[package]]
@@ -1715,7 +1695,7 @@
  "arrayvec",
  "bytemuck",
  "cfg-if",
- "png 0.17.13",
+ "png 0.17.14",
  "safe_arch",
  "tiny-skia-path",
 ]
@@ -1741,31 +1721,33 @@
 ]
 
 [[package]]
-name = "toml"
-version = "0.5.8"
+name = "toml_datetime"
+version = "0.6.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
+checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
+
+[[package]]
+name = "toml_edit"
+version = "0.19.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
 dependencies = [
- "serde",
+ "indexmap 2.7.0",
+ "toml_datetime",
+ "winnow",
 ]
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.13"
+version = "1.0.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
+checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
 
 [[package]]
 name = "unicode-width"
-version = "0.1.9"
+version = "0.1.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
-
-[[package]]
-name = "unicode-xid"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
+checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
 
 [[package]]
 name = "vec_map"
@@ -1775,57 +1757,56 @@
 
 [[package]]
 name = "version_check"
-version = "0.9.4"
+version = "0.9.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
 
 [[package]]
 name = "walkdir"
-version = "2.3.2"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
 dependencies = [
  "same-file",
- "winapi",
  "winapi-util",
 ]
 
 [[package]]
 name = "wasi"
-version = "0.10.2+wasi-snapshot-preview1"
+version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.79"
+version = "0.2.99"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06"
+checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396"
 dependencies = [
  "cfg-if",
+ "once_cell",
  "wasm-bindgen-macro",
 ]
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.79"
+version = "0.2.99"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca"
+checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79"
 dependencies = [
  "bumpalo",
- "lazy_static",
  "log",
  "proc-macro2",
  "quote",
- "syn 1.0.86",
+ "syn 2.0.90",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.79"
+version = "0.2.99"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01"
+checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -1833,33 +1814,33 @@
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.79"
+version = "0.2.99"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc"
+checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.86",
+ "syn 2.0.90",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.79"
+version = "0.2.99"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2"
+checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6"
 
 [[package]]
 name = "wayland-client"
-version = "0.29.4"
+version = "0.29.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91223460e73257f697d9e23d401279123d36039a3f7a449e983f123292d4458f"
+checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715"
 dependencies = [
  "bitflags 1.3.2",
  "downcast-rs",
  "libc",
- "nix 0.22.3",
+ "nix 0.24.3",
  "scoped-tls",
  "wayland-commons",
  "wayland-scanner",
@@ -1868,11 +1849,11 @@
 
 [[package]]
 name = "wayland-commons"
-version = "0.29.4"
+version = "0.29.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94f6e5e340d7c13490eca867898c4cec5af56c27a5ffe5c80c6fc4708e22d33e"
+checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902"
 dependencies = [
- "nix 0.22.3",
+ "nix 0.24.3",
  "once_cell",
  "smallvec",
  "wayland-sys",
@@ -1880,20 +1861,20 @@
 
 [[package]]
 name = "wayland-cursor"
-version = "0.29.4"
+version = "0.29.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c52758f13d5e7861fc83d942d3d99bf270c83269575e52ac29e5b73cb956a6bd"
+checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661"
 dependencies = [
- "nix 0.22.3",
+ "nix 0.24.3",
  "wayland-client",
  "xcursor",
 ]
 
 [[package]]
 name = "wayland-egl"
-version = "0.29.4"
+version = "0.29.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83281d69ee162b59031c666385e93bde4039ec553b90c4191cdb128ceea29a3a"
+checksum = "402de949f81a012926d821a2d659f930694257e76dd92b6e0042ceb27be4107d"
 dependencies = [
  "wayland-client",
  "wayland-sys",
@@ -1901,9 +1882,9 @@
 
 [[package]]
 name = "wayland-protocols"
-version = "0.29.4"
+version = "0.29.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60147ae23303402e41fe034f74fb2c35ad0780ee88a1c40ac09a3be1e7465741"
+checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6"
 dependencies = [
  "bitflags 1.3.2",
  "wayland-client",
@@ -1913,9 +1894,9 @@
 
 [[package]]
 name = "wayland-scanner"
-version = "0.29.4"
+version = "0.29.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39a1ed3143f7a143187156a2ab52742e89dac33245ba505c17224df48939f9e0"
+checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1924,9 +1905,9 @@
 
 [[package]]
 name = "wayland-sys"
-version = "0.29.4"
+version = "0.29.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9341df79a8975679188e37dab3889bfa57c44ac2cb6da166f519a81cbe452d4"
+checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4"
 dependencies = [
  "dlib",
  "lazy_static",
@@ -1935,9 +1916,9 @@
 
 [[package]]
 name = "web-sys"
-version = "0.3.56"
+version = "0.3.76"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb"
+checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc"
 dependencies = [
  "js-sys",
  "wasm-bindgen",
@@ -1961,11 +1942,11 @@
 
 [[package]]
 name = "winapi-util"
-version = "0.1.5"
+version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
 dependencies = [
- "winapi",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
@@ -1988,23 +1969,62 @@
 ]
 
 [[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
+]
+
+[[package]]
 name = "windows-targets"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
 dependencies = [
- "windows_aarch64_gnullvm",
+ "windows_aarch64_gnullvm 0.52.6",
  "windows_aarch64_msvc 0.52.6",
  "windows_i686_gnu 0.52.6",
  "windows_i686_gnullvm",
  "windows_i686_msvc 0.52.6",
  "windows_x86_64_gnu 0.52.6",
- "windows_x86_64_gnullvm",
+ "windows_x86_64_gnullvm 0.52.6",
  "windows_x86_64_msvc 0.52.6",
 ]
 
 [[package]]
 name = "windows_aarch64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
@@ -2017,6 +2037,12 @@
 
 [[package]]
 name = "windows_aarch64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
@@ -2029,6 +2055,12 @@
 
 [[package]]
 name = "windows_i686_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+
+[[package]]
+name = "windows_i686_gnu"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
@@ -2047,6 +2079,12 @@
 
 [[package]]
 name = "windows_i686_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+
+[[package]]
+name = "windows_i686_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
@@ -2059,12 +2097,24 @@
 
 [[package]]
 name = "windows_x86_64_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+
+[[package]]
+name = "windows_x86_64_gnu"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
@@ -2077,6 +2127,12 @@
 
 [[package]]
 name = "windows_x86_64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
+[[package]]
+name = "windows_x86_64_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
@@ -2088,9 +2144,9 @@
 checksum = "bb796d6fbd86b2fd896c9471e6f04d39d750076ebe5680a3958f00f5ab97657c"
 dependencies = [
  "bitflags 1.3.2",
- "cocoa",
+ "cocoa 0.24.1",
  "core-foundation",
- "core-graphics",
+ "core-graphics 0.22.3",
  "dispatch",
  "instant",
  "libc",
@@ -2110,11 +2166,20 @@
  "wayland-client",
  "wayland-protocols",
  "web-sys",
- "windows-sys",
+ "windows-sys 0.36.1",
  "x11-dl",
 ]
 
 [[package]]
+name = "winnow"
+version = "0.5.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
 name = "wio"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2125,26 +2190,44 @@
 
 [[package]]
 name = "x11-dl"
-version = "2.19.1"
+version = "2.21.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59"
+checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f"
 dependencies = [
- "lazy_static",
  "libc",
+ "once_cell",
  "pkg-config",
 ]
 
 [[package]]
 name = "xcursor"
-version = "0.3.4"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7"
-dependencies = [
- "nom",
-]
+checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61"
 
 [[package]]
 name = "xml-rs"
-version = "0.8.4"
+version = "0.8.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"
+checksum = "ea8b391c9a790b496184c29f7f93b9ed5b16abb306c05415b68bcc16e4d06432"
+
+[[package]]
+name = "zerocopy"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+dependencies = [
+ "byteorder",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/Cargo.toml
similarity index 77%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/Cargo.toml
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/Cargo.toml
index d10d5c7..662ffa5 100644
--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/Cargo.toml
@@ -13,8 +13,9 @@
 edition = "2018"
 rust-version = "1.57"
 name = "png"
-version = "0.17.14"
+version = "0.17.15"
 authors = ["The image-rs Developers"]
+build = false
 include = [
     "/LICENSE-MIT",
     "/LICENSE-APACHE",
@@ -24,26 +25,55 @@
     "/examples/",
     "/benches/",
 ]
+autolib = false
+autobins = false
+autoexamples = false
+autotests = false
+autobenches = false
 description = "PNG decoding and encoding library in pure Rust"
 readme = "README.md"
 categories = ["multimedia::images"]
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/image-rs/image-png"
 
+[lib]
+name = "png"
+path = "src/lib.rs"
+
+[[example]]
+name = "change-png-info"
+path = "examples/change-png-info.rs"
+
+[[example]]
+name = "corpus-bench"
+path = "examples/corpus-bench.rs"
+
+[[example]]
+name = "png-generate"
+path = "examples/png-generate.rs"
+
+[[example]]
+name = "pngcheck"
+path = "examples/pngcheck.rs"
+
+[[example]]
+name = "show"
+path = "examples/show.rs"
+
 [[bench]]
 name = "decoder"
 path = "benches/decoder.rs"
 harness = false
 
 [[bench]]
-name = "unfilter"
-path = "benches/unfilter.rs"
+name = "expand_paletted"
+path = "benches/expand_paletted.rs"
 harness = false
 required-features = ["benchmarks"]
 
 [[bench]]
-name = "expand_paletted"
-path = "benches/expand_paletted.rs"
+name = "unfilter"
+path = "benches/unfilter.rs"
 harness = false
 required-features = ["benchmarks"]
 
@@ -63,6 +93,9 @@
 version = "0.8"
 features = ["simd"]
 
+[dev-dependencies.approx]
+version = "0.5.1"
+
 [dev-dependencies.byteorder]
 version = "1.5.0"
 
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/Cargo.toml.orig b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/Cargo.toml.orig
similarity index 96%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/Cargo.toml.orig
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/Cargo.toml.orig
index 08d475bc..ee38788 100644
--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/Cargo.toml.orig
+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "png"
-version = "0.17.14"
+version = "0.17.15"
 license = "MIT OR Apache-2.0"
 
 description = "PNG decoding and encoding library in pure Rust"
@@ -28,6 +28,7 @@
 miniz_oxide = { version = "0.8", features = ["simd"] }
 
 [dev-dependencies]
+approx = "0.5.1"
 byteorder = "1.5.0"
 clap = { version = "3.0", features = ["derive"] }
 criterion = "0.4.0"
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/LICENSE-APACHE b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/LICENSE-APACHE
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/LICENSE-APACHE
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/LICENSE-APACHE
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/LICENSE-MIT b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/LICENSE-MIT
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/LICENSE-MIT
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/LICENSE-MIT
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.15/README.md b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/README.md
new file mode 100644
index 0000000..58283fd
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/README.md
@@ -0,0 +1,32 @@
+# PNG Decoder/Encoder
+[![Build Status](https://github.com/image-rs/image-png/workflows/Rust%20CI/badge.svg)](https://github.com/image-rs/image-png/actions)
+[![Documentation](https://docs.rs/png/badge.svg)](https://docs.rs/png)
+[![Crates.io](https://img.shields.io/crates/v/png.svg)](https://crates.io/crates/png)
+[![License](https://img.shields.io/crates/l/png.svg)](https://github.com/image-rs/image-png)
+
+Robust and performant PNG decoder/encoder in pure Rust. Also supports [APNG](https://en.wikipedia.org/wiki/APNG).
+
+No `unsafe` code, battle-tested, and fuzzed on [OSS-fuzz](https://github.com/google/oss-fuzz).
+
+## Performance
+
+Performance is typically on par with or better than libpng.
+
+Includes a fast encoding mode powered by [fdeflate](https://crates.io/crates/fdeflate) that is dramatically faster than the fastest mode of libpng while *simultaneously* providing better compression ratio.
+
+On nightly Rust compiler you can slightly speed up decoding of some images by enabling the `unstable` feature of this crate.
+
+## License
+
+Licensed under either of
+
+ * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
+additional terms or conditions.
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/benches/README.md b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/benches/README.md
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/benches/README.md
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/benches/README.md
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/benches/decoder.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/benches/decoder.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/benches/decoder.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/benches/decoder.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/benches/expand_paletted.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/benches/expand_paletted.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/benches/expand_paletted.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/benches/expand_paletted.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/benches/unfilter.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/benches/unfilter.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/benches/unfilter.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/benches/unfilter.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/examples/change-png-info.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/examples/change-png-info.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/examples/change-png-info.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/examples/change-png-info.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/examples/corpus-bench.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/examples/corpus-bench.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/examples/corpus-bench.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/examples/corpus-bench.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/examples/png-generate.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/examples/png-generate.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/examples/png-generate.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/examples/png-generate.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/examples/pngcheck.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/examples/pngcheck.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/examples/pngcheck.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/examples/pngcheck.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/examples/show.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/examples/show.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/examples/show.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/examples/show.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/adam7.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/adam7.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/adam7.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/adam7.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/benchable_apis.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/benchable_apis.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/benchable_apis.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/benchable_apis.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/chunk.rs
similarity index 94%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/chunk.rs
index b83ce54..3737cd4a1 100644
--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs
+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/chunk.rs
@@ -38,9 +38,9 @@
 /// Coding-independent code points for video signal type identification chunk
 pub const cICP: ChunkType = ChunkType(*b"cICP");
 /// Mastering Display Color Volume chunk
-pub const mDCv: ChunkType = ChunkType(*b"mDCv");
+pub const mDCV: ChunkType = ChunkType(*b"mDCV");
 /// Content Light Level Information chunk
-pub const cLLi: ChunkType = ChunkType(*b"cLLi");
+pub const cLLI: ChunkType = ChunkType(*b"cLLI");
 /// EXIF metadata chunk
 pub const eXIf: ChunkType = ChunkType(*b"eXIf");
 /// Latin-1 uncompressed textual data
@@ -49,6 +49,8 @@
 pub const zTXt: ChunkType = ChunkType(*b"zTXt");
 /// UTF-8 textual data
 pub const iTXt: ChunkType = ChunkType(*b"iTXt");
+// Significant bits
+pub const sBIT: ChunkType = ChunkType(*b"sBIT");
 
 // -- Extension chunks --
 
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/common.rs
similarity index 98%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/common.rs
index 3d9dc13..9a4e1876 100644
--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/common.rs
@@ -509,10 +509,10 @@
     pub is_video_full_range_image: bool,
 }
 
-/// Mastering Display Color Volume (mDCv) used at the point of content creation,
+/// Mastering Display Color Volume (mDCV) used at the point of content creation,
 /// as specified in [SMPTE-ST-2086](https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=8353899).
 ///
-/// See https://www.w3.org/TR/png-3/#mDCv-chunk for more details.
+/// See https://www.w3.org/TR/png-3/#mDCV-chunk for more details.
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub struct MasteringDisplayColorVolume {
     /// Mastering display chromaticities.
@@ -533,7 +533,7 @@
 
 /// Content light level information of HDR content.
 ///
-/// See https://www.w3.org/TR/png-3/#cLLi-chunk for more details.
+/// See https://www.w3.org/TR/png-3/#cLLI-chunk for more details.
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub struct ContentLightLevelInfo {
     /// Maximum Content Light Level indicates the maximum light level of any
@@ -569,6 +569,8 @@
     /// How colors are stored in the image.
     pub color_type: ColorType,
     pub interlaced: bool,
+    /// The image's `sBIT` chunk, if present; contains significant bits of the sample.
+    pub sbit: Option<Cow<'a, [u8]>>,
     /// The image's `tRNS` chunk, if present; contains the alpha channel of the image's palette, 1 byte per entry.
     pub trns: Option<Cow<'a, [u8]>>,
     pub pixel_dims: Option<PixelDimensions>,
@@ -580,6 +582,8 @@
     /// The contents of the image's `cHRM` chunk, if present.
     /// Prefer `source_chromaticities` to also get the derived replacements from sRGB chunks.
     pub chrm_chunk: Option<SourceChromaticities>,
+    /// The contents of the image's `bKGD` chunk, if present.
+    pub bkgd: Option<Cow<'a, [u8]>>,
 
     pub frame_control: Option<FrameControl>,
     pub animation_control: Option<AnimationControl>,
@@ -621,9 +625,11 @@
             color_type: ColorType::Grayscale,
             interlaced: false,
             palette: None,
+            sbit: None,
             trns: None,
             gama_chunk: None,
             chrm_chunk: None,
+            bkgd: None,
             pixel_dims: None,
             frame_control: None,
             animation_control: None,
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/interlace_info.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/interlace_info.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/interlace_info.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/interlace_info.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/mod.rs
similarity index 75%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/mod.rs
index 9127252..7c0759c3 100644
--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/mod.rs
@@ -1,21 +1,22 @@
 mod interlace_info;
-mod stream;
+mod read_decoder;
+pub(crate) mod stream;
 pub(crate) mod transform;
+mod unfiltering_buffer;
 mod zlib;
 
-pub use self::stream::{DecodeOptions, Decoded, DecodingError, StreamingDecoder};
-use self::stream::{FormatErrorInner, CHUNK_BUFFER_SIZE};
+use self::read_decoder::{ImageDataCompletionStatus, ReadDecoder};
+use self::stream::{DecodeOptions, DecodingError, FormatErrorInner, CHUNK_BUFFER_SIZE};
 use self::transform::{create_transform_fn, TransformFn};
+use self::unfiltering_buffer::UnfilteringBuffer;
 
-use std::io::{BufRead, BufReader, ErrorKind, Read};
+use std::io::Read;
 use std::mem;
 
 use crate::adam7::{self, Adam7Info};
-use crate::chunk;
 use crate::common::{
     BitDepth, BytesPerPixel, ColorType, Info, ParameterErrorKind, Transformations,
 };
-use crate::filter::{unfilter, FilterType};
 use crate::FrameControl;
 
 pub use interlace_info::InterlaceInfo;
@@ -128,30 +129,22 @@
 
     /// Create a new decoder configuration with custom limits.
     pub fn new_with_limits(r: R, limits: Limits) -> Decoder<R> {
-        let mut decoder = StreamingDecoder::new();
-        decoder.limits = limits;
+        let mut read_decoder = ReadDecoder::new(r);
+        read_decoder.set_limits(limits);
 
         Decoder {
-            read_decoder: ReadDecoder {
-                reader: BufReader::with_capacity(CHUNK_BUFFER_SIZE, r),
-                decoder,
-                at_eof: false,
-            },
+            read_decoder,
             transform: Transformations::IDENTITY,
         }
     }
 
     /// Create a new decoder configuration with custom `DecodeOptions`.
     pub fn new_with_options(r: R, decode_options: DecodeOptions) -> Decoder<R> {
-        let mut decoder = StreamingDecoder::new_with_options(decode_options);
-        decoder.limits = Limits::default();
+        let mut read_decoder = ReadDecoder::with_options(r, decode_options);
+        read_decoder.set_limits(Limits::default());
 
         Decoder {
-            read_decoder: ReadDecoder {
-                reader: BufReader::with_capacity(CHUNK_BUFFER_SIZE, r),
-                decoder,
-                at_eof: false,
-            },
+            read_decoder,
             transform: Transformations::IDENTITY,
         }
     }
@@ -180,7 +173,7 @@
     /// assert!(decoder.read_info().is_ok());
     /// ```
     pub fn set_limits(&mut self, limits: Limits) {
-        self.read_decoder.decoder.limits = limits;
+        self.read_decoder.set_limits(limits);
     }
 
     /// Read the PNG header and return the information contained within.
@@ -188,14 +181,7 @@
     /// Most image metadata will not be read until `read_info` is called, so those fields will be
     /// None or empty.
     pub fn read_header_info(&mut self) -> Result<&Info<'static>, DecodingError> {
-        let mut buf = Vec::new();
-        while self.read_decoder.info().is_none() {
-            buf.clear();
-            if self.read_decoder.decode_next(&mut buf)?.is_none() {
-                return Err(DecodingError::IoError(ErrorKind::UnexpectedEof.into()));
-            }
-        }
-        Ok(self.read_decoder.info().unwrap())
+        self.read_decoder.read_header_info()
     }
 
     /// Reads all meta data until the first IDAT chunk
@@ -207,12 +193,11 @@
             bpp: BytesPerPixel::One,
             subframe: SubframeInfo::not_yet_init(),
             remaining_frames: 0, // Temporary value - fixed below after reading `acTL` and `fcTL`.
-            data_stream: Vec::new(),
-            prev_start: 0,
-            current_start: 0,
+            unfiltering_buffer: UnfilteringBuffer::new(),
             transform: self.transform,
             transform_fn: None,
             scratch_buffer: Vec::new(),
+            finished: false,
         };
 
         // Check if the decoding buffer of a single raw line has a valid size.
@@ -269,9 +254,7 @@
     /// assert!(decoder.read_info().is_ok());
     /// ```
     pub fn set_ignore_text_chunk(&mut self, ignore_text_chunk: bool) {
-        self.read_decoder
-            .decoder
-            .set_ignore_text_chunk(ignore_text_chunk);
+        self.read_decoder.set_ignore_text_chunk(ignore_text_chunk);
     }
 
     /// Set the decoder to ignore iccp chunks while parsing.
@@ -285,73 +268,13 @@
     /// assert!(decoder.read_info().is_ok());
     /// ```
     pub fn set_ignore_iccp_chunk(&mut self, ignore_iccp_chunk: bool) {
-        self.read_decoder
-            .decoder
-            .set_ignore_iccp_chunk(ignore_iccp_chunk);
+        self.read_decoder.set_ignore_iccp_chunk(ignore_iccp_chunk);
     }
 
     /// Set the decoder to ignore and not verify the Adler-32 checksum
     /// and CRC code.
     pub fn ignore_checksums(&mut self, ignore_checksums: bool) {
-        self.read_decoder
-            .decoder
-            .set_ignore_adler32(ignore_checksums);
-        self.read_decoder.decoder.set_ignore_crc(ignore_checksums);
-    }
-}
-
-struct ReadDecoder<R: Read> {
-    reader: BufReader<R>,
-    decoder: StreamingDecoder,
-    at_eof: bool,
-}
-
-impl<R: Read> ReadDecoder<R> {
-    /// Returns the next decoded chunk. If the chunk is an ImageData chunk, its contents are written
-    /// into image_data.
-    fn decode_next(&mut self, image_data: &mut Vec<u8>) -> Result<Option<Decoded>, DecodingError> {
-        while !self.at_eof {
-            let (consumed, result) = {
-                let buf = self.reader.fill_buf()?;
-                if buf.is_empty() {
-                    return Err(DecodingError::IoError(ErrorKind::UnexpectedEof.into()));
-                }
-                self.decoder.update(buf, image_data)?
-            };
-            self.reader.consume(consumed);
-            match result {
-                Decoded::Nothing => (),
-                Decoded::ImageEnd => self.at_eof = true,
-                result => return Ok(Some(result)),
-            }
-        }
-        Ok(None)
-    }
-
-    fn finish_decoding(&mut self) -> Result<(), DecodingError> {
-        while !self.at_eof {
-            let buf = self.reader.fill_buf()?;
-            if buf.is_empty() {
-                return Err(DecodingError::IoError(ErrorKind::UnexpectedEof.into()));
-            }
-            let (consumed, event) = self.decoder.update(buf, &mut vec![])?;
-            self.reader.consume(consumed);
-            match event {
-                Decoded::Nothing => (),
-                Decoded::ImageEnd => self.at_eof = true,
-                // ignore more data
-                Decoded::ChunkComplete(_, _) | Decoded::ChunkBegin(_, _) | Decoded::ImageData => {}
-                Decoded::ImageDataFlushed => return Ok(()),
-                Decoded::PartialChunk(_) => {}
-                new => unreachable!("{:?}", new),
-            }
-        }
-
-        Err(DecodingError::IoError(ErrorKind::UnexpectedEof.into()))
-    }
-
-    fn info(&self) -> Option<&Info<'static>> {
-        self.decoder.info.as_ref()
+        self.read_decoder.ignore_checksums(ignore_checksums);
     }
 }
 
@@ -364,12 +287,8 @@
     subframe: SubframeInfo,
     /// How many frames remain to be decoded.  Decremented after each `IDAT` or `fdAT` sequence.
     remaining_frames: usize,
-    /// Vec containing the uncompressed image data currently being processed.
-    data_stream: Vec<u8>,
-    /// Index in `data_stream` where the previous row starts.
-    prev_start: usize,
-    /// Index in `data_stream` where the current row starts.
-    current_start: usize,
+    /// Buffer with not-yet-`unfilter`-ed image rows
+    unfiltering_buffer: UnfilteringBuffer,
     /// Output transformations
     transform: Transformations,
     /// Function that can transform decompressed, unfiltered rows into final output.
@@ -379,6 +298,8 @@
     /// to a byte slice. In a future version of this library, this buffer will be removed and
     /// `next_row` and `next_interlaced_row` will write directly into a user provided output buffer.
     scratch_buffer: Vec<u8>,
+    /// Whether `ImageEnd` was already reached by `fn finish`.
+    finished: bool,
 }
 
 /// The subframe specific information.
@@ -432,43 +353,15 @@
     /// Reads all meta data until the next frame data starts.
     /// Requires IHDR before the IDAT and fcTL before fdAT.
     fn read_until_image_data(&mut self) -> Result<(), DecodingError> {
-        loop {
-            // This is somewhat ugly. The API requires us to pass a buffer to decode_next but we
-            // know that we will stop before reading any image data from the stream. Thus pass an
-            // empty buffer and assert that remains empty.
-            let mut buf = Vec::new();
-            let state = self.decoder.decode_next(&mut buf)?;
-            assert!(buf.is_empty());
+        self.decoder.read_until_image_data()?;
 
-            match state {
-                Some(Decoded::ChunkBegin(_, chunk::IDAT))
-                | Some(Decoded::ChunkBegin(_, chunk::fdAT)) => break,
-                None => {
-                    return Err(DecodingError::Format(
-                        FormatErrorInner::MissingImageData.into(),
-                    ))
-                }
-                // Ignore all other chunk events. Any other chunk may be between IDAT chunks, fdAT
-                // chunks and their control chunks.
-                _ => {}
-            }
-        }
-
-        let info = self
-            .decoder
-            .info()
-            .ok_or(DecodingError::Format(FormatErrorInner::MissingIhdr.into()))?;
-        self.bpp = info.bpp_in_prediction();
-        self.subframe = SubframeInfo::new(info);
-        self.data_stream.clear();
-        self.current_start = 0;
-        self.prev_start = 0;
+        self.subframe = SubframeInfo::new(self.info());
+        self.bpp = self.info().bpp_in_prediction();
+        self.unfiltering_buffer = UnfilteringBuffer::new();
 
         // Allocate output buffer.
         let buflen = self.output_line_size(self.subframe.width);
-        self.decoder.decoder.limits.reserve_bytes(buflen)?;
-
-        self.prev_start = self.current_start;
+        self.decoder.reserve_bytes(buflen)?;
 
         Ok(())
     }
@@ -574,7 +467,7 @@
 
         // Discard the remaining data in the current sequence of `IDAT` or `fdAT` chunks.
         if !self.subframe.consumed_and_flushed {
-            self.decoder.finish_decoding()?;
+            self.decoder.finish_decoding_image_data()?;
             self.mark_subframe_as_consumed_and_flushed();
         }
 
@@ -597,7 +490,7 @@
             Some(interlace) => *interlace,
         };
         if interlace.line_number() == 0 {
-            self.prev_start = self.current_start;
+            self.unfiltering_buffer.reset_prev_row();
         }
         let rowlen = match interlace {
             InterlaceInfo::Null(_) => self.subframe.rowlen,
@@ -628,19 +521,17 @@
     /// Read the rest of the image and chunks and finish up, including text chunks or others
     /// This will discard the rest of the image if the image is not read already with [`Reader::next_frame`], [`Reader::next_row`] or [`Reader::next_interlaced_row`]
     pub fn finish(&mut self) -> Result<(), DecodingError> {
-        self.remaining_frames = 0;
-        self.data_stream.clear();
-        self.current_start = 0;
-        self.prev_start = 0;
-        loop {
-            let mut buf = Vec::new();
-            let state = self.decoder.decode_next(&mut buf)?;
-
-            if state.is_none() {
-                break;
-            }
+        if self.finished {
+            return Err(DecodingError::Parameter(
+                ParameterErrorKind::PolledAfterEndOfImage.into(),
+            ));
         }
 
+        self.remaining_frames = 0;
+        self.unfiltering_buffer = UnfilteringBuffer::new();
+        self.decoder.read_until_end_of_input()?;
+
+        self.finished = true;
         Ok(())
     }
 
@@ -651,8 +542,8 @@
         output_buffer: &mut [u8],
     ) -> Result<(), DecodingError> {
         self.next_raw_interlaced_row(rowlen)?;
-        assert_eq!(self.current_start - self.prev_start, rowlen - 1);
-        let row = &self.data_stream[self.prev_start..self.current_start];
+        let row = self.unfiltering_buffer.prev_row();
+        assert_eq!(row.len(), rowlen - 1);
 
         // Apply transformations and write resulting data to buffer.
         let transform_fn = {
@@ -717,52 +608,26 @@
         color.raw_row_length_from_width(depth, width) - 1
     }
 
-    /// Write the next raw interlaced row into `self.prev`.
-    ///
-    /// The scanline is filtered against the previous scanline according to the specification.
+    /// Unfilter the next raw interlaced row into `self.unfiltering_buffer`.
     fn next_raw_interlaced_row(&mut self, rowlen: usize) -> Result<(), DecodingError> {
         // Read image data until we have at least one full row (but possibly more than one).
-        while self.data_stream.len() - self.current_start < rowlen {
+        while self.unfiltering_buffer.curr_row_len() < rowlen {
             if self.subframe.consumed_and_flushed {
                 return Err(DecodingError::Format(
                     FormatErrorInner::NoMoreImageData.into(),
                 ));
             }
 
-            // Clear the current buffer before appending more data.
-            if self.prev_start > 0 {
-                self.data_stream.copy_within(self.prev_start.., 0);
-                self.data_stream
-                    .truncate(self.data_stream.len() - self.prev_start);
-                self.current_start -= self.prev_start;
-                self.prev_start = 0;
-            }
-
-            match self.decoder.decode_next(&mut self.data_stream)? {
-                Some(Decoded::ImageData) => (),
-                Some(Decoded::ImageDataFlushed) => self.mark_subframe_as_consumed_and_flushed(),
-                _ => (),
+            match self
+                .decoder
+                .decode_image_data(self.unfiltering_buffer.as_mut_vec())?
+            {
+                ImageDataCompletionStatus::ExpectingMoreData => (),
+                ImageDataCompletionStatus::Done => self.mark_subframe_as_consumed_and_flushed(),
             }
         }
 
-        // Get a reference to the current row and point scan_start to the next one.
-        let (prev, row) = self.data_stream.split_at_mut(self.current_start);
-
-        // Unfilter the row.
-        let filter = FilterType::from_u8(row[0]).ok_or(DecodingError::Format(
-            FormatErrorInner::UnknownFilterMethod(row[0]).into(),
-        ))?;
-        unfilter(
-            filter,
-            self.bpp,
-            &prev[self.prev_start..],
-            &mut row[1..rowlen],
-        );
-
-        self.prev_start = self.current_start + 1;
-        self.current_start += rowlen;
-
-        Ok(())
+        self.unfiltering_buffer.unfilter_curr_row(rowlen, self.bpp)
     }
 }
 
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/read_decoder.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/read_decoder.rs
new file mode 100644
index 0000000..44bcb48
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/read_decoder.rs
@@ -0,0 +1,179 @@
+use super::stream::{
+    DecodeOptions, Decoded, DecodingError, FormatErrorInner, StreamingDecoder, CHUNK_BUFFER_SIZE,
+};
+use super::Limits;
+
+use std::io::{BufRead, BufReader, ErrorKind, Read};
+
+use crate::chunk;
+use crate::common::Info;
+
+/// Helper for encapsulating reading input from `Read` and feeding it into a `StreamingDecoder`
+/// while hiding low-level `Decoded` events and only exposing a few high-level reading operations
+/// like:
+///
+/// * `read_header_info` - reading until `IHDR` chunk
+/// * `read_until_image_data` - reading until `IDAT` / `fdAT` sequence
+/// * `decode_image_data` - reading from `IDAT` / `fdAT` sequence into `Vec<u8>`
+/// * `finish_decoding_image_data()` - discarding remaining data from `IDAT` / `fdAT` sequence
+/// * `read_until_end_of_input()` - reading until `IEND` chunk
+pub(crate) struct ReadDecoder<R: Read> {
+    reader: BufReader<R>,
+    decoder: StreamingDecoder,
+}
+
+impl<R: Read> ReadDecoder<R> {
+    pub fn new(r: R) -> Self {
+        Self {
+            reader: BufReader::with_capacity(CHUNK_BUFFER_SIZE, r),
+            decoder: StreamingDecoder::new(),
+        }
+    }
+
+    pub fn with_options(r: R, options: DecodeOptions) -> Self {
+        let mut decoder = StreamingDecoder::new_with_options(options);
+        decoder.limits = Limits::default();
+
+        Self {
+            reader: BufReader::with_capacity(CHUNK_BUFFER_SIZE, r),
+            decoder,
+        }
+    }
+
+    pub fn set_limits(&mut self, limits: Limits) {
+        self.decoder.limits = limits;
+    }
+
+    pub fn reserve_bytes(&mut self, bytes: usize) -> Result<(), DecodingError> {
+        self.decoder.limits.reserve_bytes(bytes)
+    }
+
+    pub fn set_ignore_text_chunk(&mut self, ignore_text_chunk: bool) {
+        self.decoder.set_ignore_text_chunk(ignore_text_chunk);
+    }
+
+    pub fn set_ignore_iccp_chunk(&mut self, ignore_iccp_chunk: bool) {
+        self.decoder.set_ignore_iccp_chunk(ignore_iccp_chunk);
+    }
+
+    pub fn ignore_checksums(&mut self, ignore_checksums: bool) {
+        self.decoder.set_ignore_adler32(ignore_checksums);
+        self.decoder.set_ignore_crc(ignore_checksums);
+    }
+
+    /// Returns the next decoded chunk. If the chunk is an ImageData chunk, its contents are written
+    /// into image_data.
+    fn decode_next(&mut self, image_data: &mut Vec<u8>) -> Result<Decoded, DecodingError> {
+        let (consumed, result) = {
+            let buf = self.reader.fill_buf()?;
+            if buf.is_empty() {
+                return Err(DecodingError::IoError(ErrorKind::UnexpectedEof.into()));
+            }
+            self.decoder.update(buf, image_data)?
+        };
+        self.reader.consume(consumed);
+        Ok(result)
+    }
+
+    fn decode_next_without_image_data(&mut self) -> Result<Decoded, DecodingError> {
+        // This is somewhat ugly. The API requires us to pass a buffer to decode_next but we
+        // know that we will stop before reading any image data from the stream. Thus pass an
+        // empty buffer and assert that remains empty.
+        let mut buf = Vec::new();
+        let state = self.decode_next(&mut buf)?;
+        assert!(buf.is_empty());
+        Ok(state)
+    }
+
+    fn decode_next_and_discard_image_data(&mut self) -> Result<Decoded, DecodingError> {
+        let mut to_be_discarded = Vec::new();
+        self.decode_next(&mut to_be_discarded)
+    }
+
+    /// Reads until the end of `IHDR` chunk.
+    ///
+    /// Prerequisite: None (idempotent).
+    pub fn read_header_info(&mut self) -> Result<&Info<'static>, DecodingError> {
+        while self.info().is_none() {
+            if let Decoded::ImageEnd = self.decode_next_without_image_data()? {
+                unreachable!()
+            }
+        }
+        Ok(self.info().unwrap())
+    }
+
+    /// Reads until the start of the next `IDAT` or `fdAT` chunk.
+    ///
+    /// Prerequisite: **Not** within `IDAT` / `fdAT` chunk sequence.
+    pub fn read_until_image_data(&mut self) -> Result<(), DecodingError> {
+        loop {
+            match self.decode_next_without_image_data()? {
+                Decoded::ChunkBegin(_, chunk::IDAT) | Decoded::ChunkBegin(_, chunk::fdAT) => break,
+                Decoded::ImageEnd => {
+                    return Err(DecodingError::Format(
+                        FormatErrorInner::MissingImageData.into(),
+                    ))
+                }
+                // Ignore all other chunk events. Any other chunk may be between IDAT chunks, fdAT
+                // chunks and their control chunks.
+                _ => {}
+            }
+        }
+        Ok(())
+    }
+
+    /// Reads `image_data` and reports whether there may be additional data afterwards (i.e. if it
+    /// is okay to call `decode_image_data` and/or `finish_decoding_image_data` again)..
+    ///
+    /// Prerequisite: Input is currently positioned within `IDAT` / `fdAT` chunk sequence.
+    pub fn decode_image_data(
+        &mut self,
+        image_data: &mut Vec<u8>,
+    ) -> Result<ImageDataCompletionStatus, DecodingError> {
+        match self.decode_next(image_data)? {
+            Decoded::ImageData => Ok(ImageDataCompletionStatus::ExpectingMoreData),
+            Decoded::ImageDataFlushed => Ok(ImageDataCompletionStatus::Done),
+            // Ignore other events that may happen within an `IDAT` / `fdAT` chunks sequence.
+            Decoded::Nothing
+            | Decoded::ChunkComplete(_, _)
+            | Decoded::ChunkBegin(_, _)
+            | Decoded::PartialChunk(_) => Ok(ImageDataCompletionStatus::ExpectingMoreData),
+            // Other kinds of events shouldn't happen, unless we have been (incorrectly) called
+            // when outside of a sequence of `IDAT` / `fdAT` chunks.
+            unexpected => unreachable!("{:?}", unexpected),
+        }
+    }
+
+    /// Consumes and discards the rest of an `IDAT` / `fdAT` chunk sequence.
+    ///
+    /// Prerequisite: Input is currently positioned within `IDAT` / `fdAT` chunk sequence.
+    pub fn finish_decoding_image_data(&mut self) -> Result<(), DecodingError> {
+        loop {
+            let mut to_be_discarded = vec![];
+            if let ImageDataCompletionStatus::Done = self.decode_image_data(&mut to_be_discarded)? {
+                return Ok(());
+            }
+        }
+    }
+
+    /// Reads until the `IEND` chunk.
+    ///
+    /// Prerequisite: `IEND` chunk hasn't been reached yet.
+    pub fn read_until_end_of_input(&mut self) -> Result<(), DecodingError> {
+        while !matches!(
+            self.decode_next_and_discard_image_data()?,
+            Decoded::ImageEnd
+        ) {}
+        Ok(())
+    }
+
+    pub fn info(&self) -> Option<&Info<'static>> {
+        self.decoder.info.as_ref()
+    }
+}
+
+#[derive(Debug, Eq, PartialEq)]
+pub(crate) enum ImageDataCompletionStatus {
+    ExpectingMoreData,
+    Done,
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/stream.rs
similarity index 91%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/stream.rs
index aca2c15..7d5de33 100644
--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/stream.rs
@@ -167,8 +167,6 @@
     /// Not a PNG, the magic signature is missing.
     InvalidSignature,
     // Errors of chunk level ordering, missing etc.
-    /// Ihdr must occur.
-    MissingIhdr,
     /// Fctl must occur if an animated chunk occurs.
     MissingFctl,
     /// Image data that was indicated in IHDR or acTL is missing.
@@ -181,6 +179,10 @@
     AfterIdat {
         kind: ChunkType,
     },
+    // 4.3., Some chunks must be after PLTE.
+    BeforePlte {
+        kind: ChunkType,
+    },
     /// 4.3., some chunks must be before PLTE.
     AfterPlte {
         kind: ChunkType,
@@ -206,6 +208,16 @@
         expected: usize,
         len: usize,
     },
+    /// sBIT chunk size based on color type.
+    InvalidSbitChunkSize {
+        color_type: ColorType,
+        expected: usize,
+        len: usize,
+    },
+    InvalidSbit {
+        sample_depth: BitDepth,
+        sbit: u8,
+    },
     /// A palletized image did not have a palette.
     PaletteRequired,
     /// The color-depth combination is not valid according to Table 11.1.
@@ -292,11 +304,11 @@
                 "CRC error: expected 0x{:x} have 0x{:x} while decoding {:?} chunk.",
                 crc_val, crc_sum, chunk
             ),
-            MissingIhdr => write!(fmt, "IHDR chunk missing"),
             MissingFctl => write!(fmt, "fcTL chunk missing before fdAT chunk."),
             MissingImageData => write!(fmt, "IDAT or fdAT chunk is missing."),
             ChunkBeforeIhdr { kind } => write!(fmt, "{:?} chunk appeared before IHDR chunk", kind),
             AfterIdat { kind } => write!(fmt, "Chunk {:?} is invalid after IDAT chunk.", kind),
+            BeforePlte { kind } => write!(fmt, "Chunk {:?} is invalid before PLTE chunk.", kind),
             AfterPlte { kind } => write!(fmt, "Chunk {:?} is invalid after PLTE chunk.", kind),
             OutsidePlteIdat { kind } => write!(
                 fmt,
@@ -314,6 +326,16 @@
                 "Not enough palette entries, expect {} got {}.",
                 expected, len
             ),
+            InvalidSbitChunkSize {color_type, expected, len} => write!(
+                fmt,
+                "The size of the sBIT chunk should be {} byte(s), but {} byte(s) were provided for the {:?} color type.",
+                expected, len, color_type
+            ),
+            InvalidSbit {sample_depth, sbit} => write!(
+                fmt,
+                "Invalid sBIT value {}. It must be greater than zero and less than the sample depth {:?}.",
+                sbit, sample_depth
+            ),
             PaletteRequired => write!(fmt, "Missing palette of indexed image."),
             InvalidDimensions => write!(fmt, "Invalid image dimensions"),
             InvalidColorBitDepth {
@@ -876,10 +898,11 @@
                 };
 
                 if val == sum || CHECKSUM_DISABLED {
-                    self.state = Some(State::new_u32(U32ValueKind::Length));
                     if type_str == IEND {
+                        debug_assert!(self.state.is_none());
                         Ok(Decoded::ImageEnd)
                     } else {
+                        self.state = Some(State::new_u32(U32ValueKind::Length));
                         Ok(Decoded::ChunkComplete(val, type_str))
                     }
                 } else if self.decode_options.skip_ancillary_crc_failures
@@ -953,6 +976,7 @@
         self.state = Some(State::new_u32(U32ValueKind::Crc(type_str)));
         let parse_result = match type_str {
             IHDR => self.parse_ihdr(),
+            chunk::sBIT => self.parse_sbit(),
             chunk::PLTE => self.parse_plte(),
             chunk::tRNS => self.parse_trns(),
             chunk::pHYs => self.parse_phys(),
@@ -962,8 +986,9 @@
             chunk::cHRM => self.parse_chrm(),
             chunk::sRGB => self.parse_srgb(),
             chunk::cICP => Ok(self.parse_cicp()),
-            chunk::mDCv => Ok(self.parse_mdcv()),
-            chunk::cLLi => Ok(self.parse_clli()),
+            chunk::mDCV => Ok(self.parse_mdcv()),
+            chunk::cLLI => Ok(self.parse_clli()),
+            chunk::bKGD => Ok(self.parse_bkgd()),
             chunk::iCCP if !self.decode_options.ignore_iccp_chunk => self.parse_iccp(),
             chunk::tEXt if !self.decode_options.ignore_text_chunk => self.parse_text(),
             chunk::zTXt if !self.decode_options.ignore_text_chunk => self.parse_ztxt(),
@@ -1085,6 +1110,78 @@
         }
     }
 
+    fn parse_sbit(&mut self) -> Result<Decoded, DecodingError> {
+        let mut parse = || {
+            let info = self.info.as_mut().unwrap();
+            if info.palette.is_some() {
+                return Err(DecodingError::Format(
+                    FormatErrorInner::AfterPlte { kind: chunk::sBIT }.into(),
+                ));
+            }
+
+            if self.have_idat {
+                return Err(DecodingError::Format(
+                    FormatErrorInner::AfterIdat { kind: chunk::sBIT }.into(),
+                ));
+            }
+
+            if info.sbit.is_some() {
+                return Err(DecodingError::Format(
+                    FormatErrorInner::DuplicateChunk { kind: chunk::sBIT }.into(),
+                ));
+            }
+
+            let (color_type, bit_depth) = { (info.color_type, info.bit_depth) };
+            // The sample depth for color type 3 is fixed at eight bits.
+            let sample_depth = if color_type == ColorType::Indexed {
+                BitDepth::Eight
+            } else {
+                bit_depth
+            };
+            self.limits
+                .reserve_bytes(self.current_chunk.raw_bytes.len())?;
+            let vec = self.current_chunk.raw_bytes.clone();
+            let len = vec.len();
+
+            // expected lenth of the chunk
+            let expected = match color_type {
+                ColorType::Grayscale => 1,
+                ColorType::Rgb | ColorType::Indexed => 3,
+                ColorType::GrayscaleAlpha => 2,
+                ColorType::Rgba => 4,
+            };
+
+            // Check if the sbit chunk size is valid.
+            if expected != len {
+                return Err(DecodingError::Format(
+                    FormatErrorInner::InvalidSbitChunkSize {
+                        color_type,
+                        expected,
+                        len,
+                    }
+                    .into(),
+                ));
+            }
+
+            for sbit in &vec {
+                if *sbit < 1 || *sbit > sample_depth as u8 {
+                    return Err(DecodingError::Format(
+                        FormatErrorInner::InvalidSbit {
+                            sample_depth,
+                            sbit: *sbit,
+                        }
+                        .into(),
+                    ));
+                }
+            }
+            info.sbit = Some(Cow::Owned(vec));
+            Ok(Decoded::Nothing)
+        };
+
+        parse().ok();
+        Ok(Decoded::Nothing)
+    }
+
     fn parse_trns(&mut self) -> Result<Decoded, DecodingError> {
         let info = self.info.as_mut().unwrap();
         if info.trns.is_some() {
@@ -1131,7 +1228,7 @@
                 // before the data chunk.
                 if info.palette.is_none() {
                     return Err(DecodingError::Format(
-                        FormatErrorInner::AfterPlte { kind: chunk::tRNS }.into(),
+                        FormatErrorInner::BeforePlte { kind: chunk::tRNS }.into(),
                     ));
                 } else if self.have_idat {
                     return Err(DecodingError::Format(
@@ -1342,7 +1439,7 @@
                 // `ScaledFloat::SCALING` is hardcoded to 100_000, which works
                 // well for the `cHRM` chunk where the spec says that "a value
                 // of 0.3127 would be stored as the integer 31270".  In the
-                // `mDCv` chunk the spec says that "0.708, 0.292)" is stored as
+                // `mDCV` chunk the spec says that "0.708, 0.292)" is stored as
                 // "{ 35400, 14600 }", using a scaling factor of 50_000, so we
                 // multiply by 2 before converting.
                 ScaledFloat::from_scaled((chunk as u32) * 2)
@@ -1365,8 +1462,8 @@
             })
         }
 
-        // The spec requires that the mDCv chunk MUST come before the PLTE and IDAT chunks.
-        // Additionally, we ignore a second, duplicated mDCv chunk (if any).
+        // The spec requires that the mDCV chunk MUST come before the PLTE and IDAT chunks.
+        // Additionally, we ignore a second, duplicated mDCV chunk (if any).
         let info = self.info.as_mut().unwrap();
         let is_before_plte_and_idat = !self.have_idat && info.palette.is_none();
         if is_before_plte_and_idat && info.mastering_display_color_volume.is_none() {
@@ -1392,7 +1489,7 @@
             })
         }
 
-        // We ignore a second, duplicated cLLi chunk (if any).
+        // We ignore a second, duplicated cLLI chunk (if any).
         let info = self.info.as_mut().unwrap();
         if info.content_light_level.is_none() {
             info.content_light_level = parse(&self.current_chunk.raw_bytes[..]).ok();
@@ -1658,6 +1755,32 @@
 
         Ok(Decoded::Nothing)
     }
+
+    // NOTE: This function cannot return `DecodingError` and handles parsing
+    // errors or spec violations as-if the chunk was missing.  See
+    // https://github.com/image-rs/image-png/issues/525 for more discussion.
+    fn parse_bkgd(&mut self) -> Decoded {
+        let info = self.info.as_mut().unwrap();
+        if info.bkgd.is_none() && !self.have_idat {
+            let expected = match info.color_type {
+                ColorType::Indexed => {
+                    if info.palette.is_none() {
+                        return Decoded::Nothing;
+                    };
+                    1
+                }
+                ColorType::Grayscale | ColorType::GrayscaleAlpha => 2,
+                ColorType::Rgb | ColorType::Rgba => 6,
+            };
+            let vec = self.current_chunk.raw_bytes.clone();
+            let len = vec.len();
+            if len == expected {
+                info.bkgd = Some(Cow::Owned(vec));
+            }
+        }
+
+        Decoded::Nothing
+    }
 }
 
 impl Info<'_> {
@@ -1707,7 +1830,9 @@
     use super::SourceChromaticities;
     use crate::test_utils::*;
     use crate::{Decoder, DecodingError, Reader};
+    use approx::assert_relative_eq;
     use byteorder::WriteBytesExt;
+    use std::borrow::Cow;
     use std::cell::RefCell;
     use std::collections::VecDeque;
     use std::fs::File;
@@ -1942,6 +2067,28 @@
         Ok(())
     }
 
+    #[test]
+    fn image_source_sbit() {
+        fn trial(path: &str, expected: Option<Cow<[u8]>>) {
+            let decoder = crate::Decoder::new(File::open(path).unwrap());
+            let reader = decoder.read_info().unwrap();
+            let actual: Option<Cow<[u8]>> = reader.info().sbit.clone();
+            assert!(actual == expected);
+        }
+
+        trial("tests/sbit/g.png", Some(Cow::Owned(vec![5u8])));
+        trial("tests/sbit/ga.png", Some(Cow::Owned(vec![5u8, 3u8])));
+        trial(
+            "tests/sbit/indexed.png",
+            Some(Cow::Owned(vec![5u8, 6u8, 5u8])),
+        );
+        trial("tests/sbit/rgb.png", Some(Cow::Owned(vec![5u8, 6u8, 5u8])));
+        trial(
+            "tests/sbit/rgba.png",
+            Some(Cow::Owned(vec![5u8, 6u8, 5u8, 8u8])),
+        );
+    }
+
     /// Test handling of a PNG file that contains *two* iCCP chunks.
     /// This is a regression test for https://github.com/image-rs/image/issues/1825.
     #[test]
@@ -1970,6 +2117,53 @@
         assert!(decoder.read_info().is_ok());
     }
 
+    /// Test handling of `mDCV` and `cLLI` chunks.`
+    #[test]
+    fn test_mdcv_and_clli_chunks() {
+        let decoder = crate::Decoder::new(File::open("tests/bugfixes/cicp_pq.png").unwrap());
+        let reader = decoder.read_info().unwrap();
+        let info = reader.info();
+
+        let cicp = info.coding_independent_code_points.unwrap();
+        assert_eq!(cicp.color_primaries, 9);
+        assert_eq!(cicp.transfer_function, 16);
+        assert_eq!(cicp.matrix_coefficients, 0);
+        assert!(cicp.is_video_full_range_image);
+
+        let mdcv = info.mastering_display_color_volume.unwrap();
+        assert_relative_eq!(mdcv.chromaticities.red.0.into_value(), 0.680);
+        assert_relative_eq!(mdcv.chromaticities.red.1.into_value(), 0.320);
+        assert_relative_eq!(mdcv.chromaticities.green.0.into_value(), 0.265);
+        assert_relative_eq!(mdcv.chromaticities.green.1.into_value(), 0.690);
+        assert_relative_eq!(mdcv.chromaticities.blue.0.into_value(), 0.150);
+        assert_relative_eq!(mdcv.chromaticities.blue.1.into_value(), 0.060);
+        assert_relative_eq!(mdcv.chromaticities.white.0.into_value(), 0.3127);
+        assert_relative_eq!(mdcv.chromaticities.white.1.into_value(), 0.3290);
+        assert_relative_eq!(mdcv.min_luminance as f32 / 10_000.0, 0.01);
+        assert_relative_eq!(mdcv.max_luminance as f32 / 10_000.0, 5000.0);
+
+        let clli = info.content_light_level.unwrap();
+        assert_relative_eq!(clli.max_content_light_level as f32 / 10_000.0, 4000.0);
+        assert_relative_eq!(clli.max_frame_average_light_level as f32 / 10_000.0, 2627.0);
+    }
+
+    /// Tests what happens then [`Reader.finish`] is called twice.
+    #[test]
+    fn test_finishing_twice() {
+        let mut png = Vec::new();
+        write_noncompressed_png(&mut png, 16, 1024);
+        let decoder = Decoder::new(png.as_slice());
+        let mut reader = decoder.read_info().unwrap();
+
+        // First call to `finish` - expecting success.
+        reader.finish().unwrap();
+
+        // Second call to `finish` - expecting an error.
+        let err = reader.finish().unwrap_err();
+        assert!(matches!(&err, DecodingError::Parameter(_)));
+        assert_eq!("End of image has been reached", format!("{err}"));
+    }
+
     /// Writes an acTL chunk.
     /// See https://wiki.mozilla.org/APNG_Specification#.60acTL.60:_The_Animation_Control_Chunk
     fn write_actl(w: &mut impl Write, animation: &crate::AnimationControl) {
@@ -2185,6 +2379,30 @@
         assert_eq!(3093270825, crc32fast::hash(&buf));
     }
 
+    #[test]
+    fn test_only_idat_chunk_in_input_stream() {
+        let png = {
+            let mut png = Vec::new();
+            write_png_sig(&mut png);
+            write_chunk(&mut png, b"IDAT", &[]);
+            png
+        };
+        let decoder = Decoder::new(png.as_slice());
+        let Err(err) = decoder.read_info() else {
+            panic!("Expected an error")
+        };
+        assert!(matches!(&err, DecodingError::Format(_)));
+        assert_eq!(
+            "ChunkType { type: IDAT, \
+                         critical: true, \
+                         private: false, \
+                         reserved: false, \
+                         safecopy: false \
+             } chunk appeared before IHDR chunk",
+            format!("{err}"),
+        );
+    }
+
     /// `StreamingInput` can be used by tests to simulate a streaming input
     /// (e.g. a slow http response, where all bytes are not immediately available).
     #[derive(Clone)]
@@ -2366,17 +2584,16 @@
     /// Creates a ready-to-test [`Reader`] which decodes an animated PNG that contains:
     /// IHDR, acTL, fcTL, IDAT, fcTL, fdAT, IEND.  (i.e. IDAT is part of the animation)
     fn create_reader_of_ihdr_actl_fctl_idat_fctl_fdat() -> Reader<VecDeque<u8>> {
-        let width = 16;
-        let frame_data = generate_rgba8_with_width_and_height(width, width);
+        let idat_width = 16;
         let mut fctl = crate::FrameControl {
-            width,
-            height: width,
+            width: idat_width,
+            height: idat_width, // same height and width
             ..Default::default()
         };
 
         let mut png = VecDeque::new();
         write_png_sig(&mut png);
-        write_rgba8_ihdr_with_width(&mut png, width);
+        write_rgba8_ihdr_with_width(&mut png, idat_width);
         write_actl(
             &mut png,
             &crate::AnimationControl {
@@ -2386,10 +2603,21 @@
         );
         fctl.sequence_number = 0;
         write_fctl(&mut png, &fctl);
-        write_chunk(&mut png, b"IDAT", &frame_data);
+        // Using `fctl.height + 1` means that the `IDAT` will have "left-over" data after
+        // processing.  This helps to verify that `Reader.read_until_image_data` discards the
+        // left-over data when resetting `UnfilteredRowsBuffer`.
+        let idat_data = generate_rgba8_with_width_and_height(fctl.width, fctl.height + 1);
+        write_chunk(&mut png, b"IDAT", &idat_data);
+
+        let fdat_width = 10;
         fctl.sequence_number = 1;
+        // Using different width in `IDAT` and `fDAT` frames helps to catch problems that
+        // may arise when `Reader.read_until_image_data` doesn't properly reset
+        // `UnfilteredRowsBuffer`.
+        fctl.width = fdat_width;
         write_fctl(&mut png, &fctl);
-        write_fdat(&mut png, 2, &frame_data);
+        let fdat_data = generate_rgba8_with_width_and_height(fctl.width, fctl.height);
+        write_fdat(&mut png, 2, &fdat_data);
         write_iend(&mut png);
 
         Decoder::new(png).read_info().unwrap()
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/transform.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/transform.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/transform.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/transform.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/transform/palette.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/transform/palette.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/transform/palette.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/transform/palette.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/unfiltering_buffer.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/unfiltering_buffer.rs
new file mode 100644
index 0000000..417f8f0
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/unfiltering_buffer.rs
@@ -0,0 +1,112 @@
+use super::stream::{DecodingError, FormatErrorInner};
+use crate::common::BytesPerPixel;
+use crate::filter::{unfilter, FilterType};
+
+// Buffer for temporarily holding decompressed, not-yet-`unfilter`-ed rows.
+pub(crate) struct UnfilteringBuffer {
+    /// Vec containing the uncompressed image data currently being processed.
+    data_stream: Vec<u8>,
+    /// Index in `data_stream` where the previous row starts.
+    /// This excludes the filter type byte - it points at the first byte of actual pixel data.
+    /// The pixel data is already-`unfilter`-ed.
+    /// If `prev_start == current_start` then it means that there is no previous row.
+    prev_start: usize,
+    /// Index in `data_stream` where the current row starts.
+    /// This points at the filter type byte of the current row (i.e. the actual pixel data starts at `current_start + 1`)
+    /// The pixel data is not-yet-`unfilter`-ed.
+    current_start: usize,
+}
+
+impl UnfilteringBuffer {
+    /// Asserts in debug builds that all the invariants hold.  No-op in release
+    /// builds.  Intended to be called after creating or mutating `self` to
+    /// ensure that the final state preserves the invariants.
+    fn debug_assert_invariants(&self) {
+        debug_assert!(self.prev_start <= self.current_start);
+        debug_assert!(self.prev_start <= self.data_stream.len());
+        debug_assert!(self.current_start <= self.data_stream.len());
+    }
+
+    pub fn new() -> Self {
+        let result = Self {
+            data_stream: Vec::new(),
+            prev_start: 0,
+            current_start: 0,
+        };
+        result.debug_assert_invariants();
+        result
+    }
+
+    /// Called to indicate that there is no previous row (e.g. when the current
+    /// row is the first scanline of a given Adam7 pass).
+    pub fn reset_prev_row(&mut self) {
+        self.prev_start = self.current_start;
+        self.debug_assert_invariants();
+    }
+
+    /// Returns the previous (already `unfilter`-ed) row.
+    pub fn prev_row(&self) -> &[u8] {
+        // No point calling this if there is no previous row.
+        debug_assert!(self.prev_start < self.current_start);
+
+        &self.data_stream[self.prev_start..self.current_start]
+    }
+
+    /// Returns how many bytes of the current row are present in the buffer.
+    pub fn curr_row_len(&self) -> usize {
+        self.data_stream.len() - self.current_start
+    }
+
+    /// Returns a `&mut Vec<u8>` suitable for passing to
+    /// `ReadDecoder.decode_image_data` or `StreamingDecoder.update`.
+    ///
+    /// Invariants of `self` depend on the assumption that the caller will only
+    /// append new bytes to the returned vector (which is indeed the behavior of
+    /// `ReadDecoder` and `StreamingDecoder`).  TODO: Consider protecting the
+    /// invariants by returning an append-only view of the vector
+    /// (`FnMut(&[u8])`??? or maybe `std::io::Write`???).
+    pub fn as_mut_vec(&mut self) -> &mut Vec<u8> {
+        // Opportunistically compact the current buffer by discarding bytes
+        // before `prev_start`.
+        if self.prev_start > 0 {
+            self.data_stream.copy_within(self.prev_start.., 0);
+            self.data_stream
+                .truncate(self.data_stream.len() - self.prev_start);
+            self.current_start -= self.prev_start;
+            self.prev_start = 0;
+            self.debug_assert_invariants();
+        }
+
+        &mut self.data_stream
+    }
+
+    /// Runs `unfilter` on the current row, and then shifts rows so that the current row becomes the previous row.
+    ///
+    /// Will panic if `self.curr_row_len() < rowlen`.
+    pub fn unfilter_curr_row(
+        &mut self,
+        rowlen: usize,
+        bpp: BytesPerPixel,
+    ) -> Result<(), DecodingError> {
+        debug_assert!(rowlen >= 2); // 1 byte for `FilterType` and at least 1 byte of pixel data.
+
+        let (prev, row) = self.data_stream.split_at_mut(self.current_start);
+        let prev: &[u8] = prev; // `prev` is immutable
+        let prev = &prev[self.prev_start..];
+        debug_assert!(prev.is_empty() || prev.len() == (rowlen - 1));
+
+        // Get the filter type.
+        let filter = FilterType::from_u8(row[0]).ok_or(DecodingError::Format(
+            FormatErrorInner::UnknownFilterMethod(row[0]).into(),
+        ))?;
+        let row = &mut row[1..rowlen];
+
+        unfilter(filter, bpp, prev, row);
+
+        self.prev_start = self.current_start + 1;
+        self.current_start += rowlen;
+        self.debug_assert_invariants();
+
+        Ok(())
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/zlib.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/zlib.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/zlib.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/zlib.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/encoder.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/encoder.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/encoder.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/encoder.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/filter.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/filter.rs
similarity index 79%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/filter.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/filter.rs
index 9290a04..da1e296 100644
--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/filter.rs
+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/filter.rs
@@ -7,23 +7,27 @@
 /// TODO(https://github.com/rust-lang/rust/issues/86656): Stop gating this module behind the
 /// "unstable" feature of the `png` crate.  This should be possible once the "portable_simd"
 /// feature of Rust gets stabilized.
-#[cfg(feature = "unstable")]
+///
+/// This is only known to help on x86, with no change measured on most benchmarks on ARM,
+/// and even severely regressing some of them.
+/// So despite the code being portable, we only enable this for x86.
+/// We can add more platforms once this code is proven to be beneficial for them.
+#[cfg(all(feature = "unstable", target_arch = "x86_64"))]
 mod simd {
-    use std::simd::cmp::{SimdOrd, SimdPartialEq, SimdPartialOrd};
     use std::simd::num::{SimdInt, SimdUint};
     use std::simd::{u8x4, u8x8, LaneCount, Simd, SimdElement, SupportedLaneCount};
 
-    /// This is an equivalent of the `PaethPredictor` function from
-    /// [the spec](http://www.libpng.org/pub/png/spec/1.2/PNG-Filters.html#Filter-type-4-Paeth)
-    /// except that it simultaneously calculates the predictor for all SIMD lanes.
-    /// Mapping between parameter names and pixel positions can be found in
-    /// [a diagram here](https://www.w3.org/TR/png/#filter-byte-positions).
+    /// Scalar Paeth function wrapped in SIMD scaffolding.
     ///
-    /// Examples of how different pixel types may be represented as multiple SIMD lanes:
-    /// - RGBA => 4 lanes of `i16x4` contain R, G, B, A
-    /// - RGB  => 4 lanes of `i16x4` contain R, G, B, and a ignored 4th value
+    /// This is needed because simply running the function on the inputs
+    /// makes the compiler think our inputs are too short
+    /// to benefit from vectorization.
+    /// Putting it in SIMD scaffolding fixes that.
+    /// https://github.com/image-rs/image-png/issues/511
     ///
-    /// The SIMD algorithm below is based on [`libpng`](https://github.com/glennrp/libpng/blob/f8e5fa92b0e37ab597616f554bee254157998227/intel/filter_sse2_intrinsics.c#L261-L280).
+    /// Funnily, the autovectorizer does a better job here
+    /// than a handwritten algorithm using std::simd!
+    /// We used to have a handwritten one but this is just faster.
     fn paeth_predictor<const N: usize>(
         a: Simd<i16, N>,
         b: Simd<i16, N>,
@@ -32,28 +36,14 @@
     where
         LaneCount<N>: SupportedLaneCount,
     {
-        let pa = b - c; // (p-a) == (a+b-c - a) == (b-c)
-        let pb = a - c; // (p-b) == (a+b-c - b) == (a-c)
-        let pc = pa + pb; // (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c)
-
-        let pa = pa.abs();
-        let pb = pb.abs();
-        let pc = pc.abs();
-
-        let smallest = pc.simd_min(pa.simd_min(pb));
-
-        // Paeth algorithm breaks ties favoring a over b over c, so we execute the following
-        // lane-wise selection:
-        //
-        //     if smalest == pa
-        //         then select a
-        //         else select (if smallest == pb then select b else select c)
-        smallest
-            .simd_eq(pa)
-            .select(a, smallest.simd_eq(pb).select(b, c))
+        let mut out = [0; N];
+        for i in 0..N {
+            out[i] = super::filter_paeth_stbi_i16(a[i].into(), b[i].into(), c[i].into());
+        }
+        out.into()
     }
 
-    /// Equivalent to `simd::paeth_predictor` but does not temporarily convert
+    /// Functionally equivalent to `simd::paeth_predictor` but does not temporarily convert
     /// the SIMD elements to `i16`.
     fn paeth_predictor_u8<const N: usize>(
         a: Simd<u8, N>,
@@ -63,44 +53,11 @@
     where
         LaneCount<N>: SupportedLaneCount,
     {
-        // Calculates the absolute difference between `a` and `b`.
-        fn abs_diff_simd<const N: usize>(a: Simd<u8, N>, b: Simd<u8, N>) -> Simd<u8, N>
-        where
-            LaneCount<N>: SupportedLaneCount,
-        {
-            a.simd_max(b) - b.simd_min(a)
+        let mut out = [0; N];
+        for i in 0..N {
+            out[i] = super::filter_paeth_stbi(a[i].into(), b[i].into(), c[i].into());
         }
-
-        // Uses logic from `filter::filter_paeth` to calculate absolute values
-        // entirely in `Simd<u8, N>`. This method avoids unpacking and packing
-        // penalties resulting from conversion to and from `Simd<i16, N>`.
-        // ```
-        //     let pa = b.max(c) - c.min(b);
-        //     let pb = a.max(c) - c.min(a);
-        //     let pc = if (a < c) == (c < b) {
-        //         pa.max(pb) - pa.min(pb)
-        //     } else {
-        //         255
-        //     };
-        // ```
-        let pa = abs_diff_simd(b, c);
-        let pb = abs_diff_simd(a, c);
-        let pc = a
-            .simd_lt(c)
-            .simd_eq(c.simd_lt(b))
-            .select(abs_diff_simd(pa, pb), Simd::splat(255));
-
-        let smallest = pc.simd_min(pa.simd_min(pb));
-
-        // Paeth algorithm breaks ties favoring a over b over c, so we execute the following
-        // lane-wise selection:
-        //
-        //     if smalest == pa
-        //         then select a
-        //         else select (if smallest == pb then select b else select c)
-        smallest
-            .simd_eq(pa)
-            .select(a, smallest.simd_eq(pb).select(b, c))
+        out.into()
     }
 
     /// Memory of previous pixels (as needed to unfilter `FilterType::Paeth`).
@@ -320,8 +277,10 @@
     }
 }
 
-fn filter_paeth_decode(a: u8, b: u8, c: u8) -> u8 {
-    // Decoding seems to optimize better with this algorithm
+fn filter_paeth(a: u8, b: u8, c: u8) -> u8 {
+    // On ARM this algorithm performs much better than the one above adapted from stb,
+    // and this is the better-studied algorithm we've always used here,
+    // so we default to it on all non-x86 platforms.
     let pa = (i16::from(b) - i16::from(c)).abs();
     let pb = (i16::from(a) - i16::from(c)).abs();
     let pc = ((i16::from(a) - i16::from(c)) + (i16::from(b) - i16::from(c))).abs();
@@ -340,7 +299,36 @@
     out
 }
 
-fn filter_paeth(a: u8, b: u8, c: u8) -> u8 {
+fn filter_paeth_stbi(a: u8, b: u8, c: u8) -> u8 {
+    // Decoding optimizes better with this algorithm than with `filter_paeth`
+    //
+    // This formulation looks very different from the reference in the PNG spec, but is
+    // actually equivalent and has favorable data dependencies and admits straightforward
+    // generation of branch-free code, which helps performance significantly.
+    //
+    // Adapted from public domain PNG implementation:
+    // https://github.com/nothings/stb/blob/5c205738c191bcb0abc65c4febfa9bd25ff35234/stb_image.h#L4657-L4668
+    let thresh = i16::from(c) * 3 - (i16::from(a) + i16::from(b));
+    let lo = a.min(b);
+    let hi = a.max(b);
+    let t0 = if hi as i16 <= thresh { lo } else { c };
+    let t1 = if thresh <= lo as i16 { hi } else { t0 };
+    return t1;
+}
+
+#[cfg(any(test, all(feature = "unstable", target_arch = "x86_64")))]
+fn filter_paeth_stbi_i16(a: i16, b: i16, c: i16) -> i16 {
+    // Like `filter_paeth_stbi` but vectorizes better when wrapped in SIMD types.
+    // Used for bpp=3 and bpp=6
+    let thresh = c * 3 - (a + b);
+    let lo = a.min(b);
+    let hi = a.max(b);
+    let t0 = if hi <= thresh { lo } else { c };
+    let t1 = if thresh <= lo { hi } else { t0 };
+    return t1;
+}
+
+fn filter_paeth_fpnge(a: u8, b: u8, c: u8) -> u8 {
     // This is an optimized version of the paeth filter from the PNG specification, proposed by
     // Luca Versari for [FPNGE](https://www.lucaversari.it/FJXL_and_FPNGE.pdf). It operates
     // entirely on unsigned 8-bit quantities, making it more conducive to vectorization.
@@ -716,7 +704,15 @@
                 }
             }
         },
+        #[allow(unreachable_code)]
         Paeth => {
+            // Select the fastest Paeth filter implementation based on the target architecture.
+            let filter_paeth_decode = if cfg!(target_arch = "x86_64") {
+                filter_paeth_stbi
+            } else {
+                filter_paeth
+            };
+
             // Paeth filter pixels:
             // C B D
             // A X
@@ -750,142 +746,118 @@
                     }
                 }
                 BytesPerPixel::Three => {
-                    #[cfg(feature = "unstable")]
-                    simd::unfilter_paeth3(previous, current);
-
-                    #[cfg(not(feature = "unstable"))]
+                    // Do not enable this algorithm on ARM, that would be a big performance hit
+                    #[cfg(all(feature = "unstable", target_arch = "x86_64"))]
                     {
-                        let mut a_bpp = [0; 3];
-                        let mut c_bpp = [0; 3];
-                        for (chunk, b_bpp) in
-                            current.chunks_exact_mut(3).zip(previous.chunks_exact(3))
-                        {
-                            let new_chunk = [
-                                chunk[0].wrapping_add(filter_paeth_decode(
-                                    a_bpp[0], b_bpp[0], c_bpp[0],
-                                )),
-                                chunk[1].wrapping_add(filter_paeth_decode(
-                                    a_bpp[1], b_bpp[1], c_bpp[1],
-                                )),
-                                chunk[2].wrapping_add(filter_paeth_decode(
-                                    a_bpp[2], b_bpp[2], c_bpp[2],
-                                )),
-                            ];
-                            *TryInto::<&mut [u8; 3]>::try_into(chunk).unwrap() = new_chunk;
-                            a_bpp = new_chunk;
-                            c_bpp = b_bpp.try_into().unwrap();
-                        }
+                        simd::unfilter_paeth3(previous, current);
+                        return;
+                    }
+
+                    let mut a_bpp = [0; 3];
+                    let mut c_bpp = [0; 3];
+                    for (chunk, b_bpp) in current.chunks_exact_mut(3).zip(previous.chunks_exact(3))
+                    {
+                        let new_chunk = [
+                            chunk[0]
+                                .wrapping_add(filter_paeth_decode(a_bpp[0], b_bpp[0], c_bpp[0])),
+                            chunk[1]
+                                .wrapping_add(filter_paeth_decode(a_bpp[1], b_bpp[1], c_bpp[1])),
+                            chunk[2]
+                                .wrapping_add(filter_paeth_decode(a_bpp[2], b_bpp[2], c_bpp[2])),
+                        ];
+                        *TryInto::<&mut [u8; 3]>::try_into(chunk).unwrap() = new_chunk;
+                        a_bpp = new_chunk;
+                        c_bpp = b_bpp.try_into().unwrap();
                     }
                 }
                 BytesPerPixel::Four => {
-                    #[cfg(feature = "unstable")]
-                    simd::unfilter_paeth_u8::<4>(previous, current);
-
-                    #[cfg(not(feature = "unstable"))]
+                    #[cfg(all(feature = "unstable", target_arch = "x86_64"))]
                     {
-                        let mut a_bpp = [0; 4];
-                        let mut c_bpp = [0; 4];
-                        for (chunk, b_bpp) in
-                            current.chunks_exact_mut(4).zip(previous.chunks_exact(4))
-                        {
-                            let new_chunk = [
-                                chunk[0].wrapping_add(filter_paeth_decode(
-                                    a_bpp[0], b_bpp[0], c_bpp[0],
-                                )),
-                                chunk[1].wrapping_add(filter_paeth_decode(
-                                    a_bpp[1], b_bpp[1], c_bpp[1],
-                                )),
-                                chunk[2].wrapping_add(filter_paeth_decode(
-                                    a_bpp[2], b_bpp[2], c_bpp[2],
-                                )),
-                                chunk[3].wrapping_add(filter_paeth_decode(
-                                    a_bpp[3], b_bpp[3], c_bpp[3],
-                                )),
-                            ];
-                            *TryInto::<&mut [u8; 4]>::try_into(chunk).unwrap() = new_chunk;
-                            a_bpp = new_chunk;
-                            c_bpp = b_bpp.try_into().unwrap();
-                        }
+                        simd::unfilter_paeth_u8::<4>(previous, current);
+                        return;
+                    }
+
+                    let mut a_bpp = [0; 4];
+                    let mut c_bpp = [0; 4];
+                    for (chunk, b_bpp) in current.chunks_exact_mut(4).zip(previous.chunks_exact(4))
+                    {
+                        let new_chunk = [
+                            chunk[0]
+                                .wrapping_add(filter_paeth_decode(a_bpp[0], b_bpp[0], c_bpp[0])),
+                            chunk[1]
+                                .wrapping_add(filter_paeth_decode(a_bpp[1], b_bpp[1], c_bpp[1])),
+                            chunk[2]
+                                .wrapping_add(filter_paeth_decode(a_bpp[2], b_bpp[2], c_bpp[2])),
+                            chunk[3]
+                                .wrapping_add(filter_paeth_decode(a_bpp[3], b_bpp[3], c_bpp[3])),
+                        ];
+                        *TryInto::<&mut [u8; 4]>::try_into(chunk).unwrap() = new_chunk;
+                        a_bpp = new_chunk;
+                        c_bpp = b_bpp.try_into().unwrap();
                     }
                 }
                 BytesPerPixel::Six => {
-                    #[cfg(feature = "unstable")]
-                    simd::unfilter_paeth6(previous, current);
-
-                    #[cfg(not(feature = "unstable"))]
+                    #[cfg(all(feature = "unstable", target_arch = "x86_64"))]
                     {
-                        let mut a_bpp = [0; 6];
-                        let mut c_bpp = [0; 6];
-                        for (chunk, b_bpp) in
-                            current.chunks_exact_mut(6).zip(previous.chunks_exact(6))
-                        {
-                            let new_chunk = [
-                                chunk[0].wrapping_add(filter_paeth_decode(
-                                    a_bpp[0], b_bpp[0], c_bpp[0],
-                                )),
-                                chunk[1].wrapping_add(filter_paeth_decode(
-                                    a_bpp[1], b_bpp[1], c_bpp[1],
-                                )),
-                                chunk[2].wrapping_add(filter_paeth_decode(
-                                    a_bpp[2], b_bpp[2], c_bpp[2],
-                                )),
-                                chunk[3].wrapping_add(filter_paeth_decode(
-                                    a_bpp[3], b_bpp[3], c_bpp[3],
-                                )),
-                                chunk[4].wrapping_add(filter_paeth_decode(
-                                    a_bpp[4], b_bpp[4], c_bpp[4],
-                                )),
-                                chunk[5].wrapping_add(filter_paeth_decode(
-                                    a_bpp[5], b_bpp[5], c_bpp[5],
-                                )),
-                            ];
-                            *TryInto::<&mut [u8; 6]>::try_into(chunk).unwrap() = new_chunk;
-                            a_bpp = new_chunk;
-                            c_bpp = b_bpp.try_into().unwrap();
-                        }
+                        simd::unfilter_paeth6(previous, current);
+                        return;
+                    }
+
+                    let mut a_bpp = [0; 6];
+                    let mut c_bpp = [0; 6];
+                    for (chunk, b_bpp) in current.chunks_exact_mut(6).zip(previous.chunks_exact(6))
+                    {
+                        let new_chunk = [
+                            chunk[0]
+                                .wrapping_add(filter_paeth_decode(a_bpp[0], b_bpp[0], c_bpp[0])),
+                            chunk[1]
+                                .wrapping_add(filter_paeth_decode(a_bpp[1], b_bpp[1], c_bpp[1])),
+                            chunk[2]
+                                .wrapping_add(filter_paeth_decode(a_bpp[2], b_bpp[2], c_bpp[2])),
+                            chunk[3]
+                                .wrapping_add(filter_paeth_decode(a_bpp[3], b_bpp[3], c_bpp[3])),
+                            chunk[4]
+                                .wrapping_add(filter_paeth_decode(a_bpp[4], b_bpp[4], c_bpp[4])),
+                            chunk[5]
+                                .wrapping_add(filter_paeth_decode(a_bpp[5], b_bpp[5], c_bpp[5])),
+                        ];
+                        *TryInto::<&mut [u8; 6]>::try_into(chunk).unwrap() = new_chunk;
+                        a_bpp = new_chunk;
+                        c_bpp = b_bpp.try_into().unwrap();
                     }
                 }
                 BytesPerPixel::Eight => {
-                    #[cfg(feature = "unstable")]
-                    simd::unfilter_paeth_u8::<8>(previous, current);
-
-                    #[cfg(not(feature = "unstable"))]
+                    #[cfg(all(feature = "unstable", target_arch = "x86_64"))]
                     {
-                        let mut a_bpp = [0; 8];
-                        let mut c_bpp = [0; 8];
-                        for (chunk, b_bpp) in
-                            current.chunks_exact_mut(8).zip(previous.chunks_exact(8))
-                        {
-                            let new_chunk = [
-                                chunk[0].wrapping_add(filter_paeth_decode(
-                                    a_bpp[0], b_bpp[0], c_bpp[0],
-                                )),
-                                chunk[1].wrapping_add(filter_paeth_decode(
-                                    a_bpp[1], b_bpp[1], c_bpp[1],
-                                )),
-                                chunk[2].wrapping_add(filter_paeth_decode(
-                                    a_bpp[2], b_bpp[2], c_bpp[2],
-                                )),
-                                chunk[3].wrapping_add(filter_paeth_decode(
-                                    a_bpp[3], b_bpp[3], c_bpp[3],
-                                )),
-                                chunk[4].wrapping_add(filter_paeth_decode(
-                                    a_bpp[4], b_bpp[4], c_bpp[4],
-                                )),
-                                chunk[5].wrapping_add(filter_paeth_decode(
-                                    a_bpp[5], b_bpp[5], c_bpp[5],
-                                )),
-                                chunk[6].wrapping_add(filter_paeth_decode(
-                                    a_bpp[6], b_bpp[6], c_bpp[6],
-                                )),
-                                chunk[7].wrapping_add(filter_paeth_decode(
-                                    a_bpp[7], b_bpp[7], c_bpp[7],
-                                )),
-                            ];
-                            *TryInto::<&mut [u8; 8]>::try_into(chunk).unwrap() = new_chunk;
-                            a_bpp = new_chunk;
-                            c_bpp = b_bpp.try_into().unwrap();
-                        }
+                        simd::unfilter_paeth_u8::<8>(previous, current);
+                        return;
+                    }
+
+                    let mut a_bpp = [0; 8];
+                    let mut c_bpp = [0; 8];
+                    for (chunk, b_bpp) in current.chunks_exact_mut(8).zip(previous.chunks_exact(8))
+                    {
+                        let new_chunk = [
+                            chunk[0]
+                                .wrapping_add(filter_paeth_decode(a_bpp[0], b_bpp[0], c_bpp[0])),
+                            chunk[1]
+                                .wrapping_add(filter_paeth_decode(a_bpp[1], b_bpp[1], c_bpp[1])),
+                            chunk[2]
+                                .wrapping_add(filter_paeth_decode(a_bpp[2], b_bpp[2], c_bpp[2])),
+                            chunk[3]
+                                .wrapping_add(filter_paeth_decode(a_bpp[3], b_bpp[3], c_bpp[3])),
+                            chunk[4]
+                                .wrapping_add(filter_paeth_decode(a_bpp[4], b_bpp[4], c_bpp[4])),
+                            chunk[5]
+                                .wrapping_add(filter_paeth_decode(a_bpp[5], b_bpp[5], c_bpp[5])),
+                            chunk[6]
+                                .wrapping_add(filter_paeth_decode(a_bpp[6], b_bpp[6], c_bpp[6])),
+                            chunk[7]
+                                .wrapping_add(filter_paeth_decode(a_bpp[7], b_bpp[7], c_bpp[7])),
+                        ];
+                        *TryInto::<&mut [u8; 8]>::try_into(chunk).unwrap() = new_chunk;
+                        a_bpp = new_chunk;
+                        c_bpp = b_bpp.try_into().unwrap();
                     }
                 }
             }
@@ -1009,7 +981,7 @@
                 .zip(&mut c_chunks)
             {
                 for i in 0..CHUNK_SIZE {
-                    out[i] = cur[i].wrapping_sub(filter_paeth(a[i], b[i], c[i]));
+                    out[i] = cur[i].wrapping_sub(filter_paeth_fpnge(a[i], b[i], c[i]));
                 }
             }
 
@@ -1021,11 +993,11 @@
                 .zip(b_chunks.remainder())
                 .zip(c_chunks.remainder())
             {
-                *out = cur.wrapping_sub(filter_paeth(a, b, c));
+                *out = cur.wrapping_sub(filter_paeth_fpnge(a, b, c));
             }
 
             for i in 0..bpp {
-                output[i] = current[i].wrapping_sub(filter_paeth(0, previous[i], 0));
+                output[i] = current[i].wrapping_sub(filter_paeth_fpnge(0, previous[i], 0));
             }
             Paeth
         }
@@ -1094,7 +1066,7 @@
 
 #[cfg(test)]
 mod test {
-    use super::{filter, unfilter, AdaptiveFilterType, BytesPerPixel, FilterType};
+    use super::*;
     use core::iter;
 
     #[test]
@@ -1142,6 +1114,25 @@
     }
 
     #[test]
+    #[ignore] // takes ~20s without optimizations
+    fn paeth_impls_are_equivalent() {
+        for a in 0..=255 {
+            for b in 0..=255 {
+                for c in 0..=255 {
+                    let baseline = filter_paeth(a, b, c);
+                    let fpnge = filter_paeth_fpnge(a, b, c);
+                    let stbi = filter_paeth_stbi(a, b, c);
+                    let stbi_i16 = filter_paeth_stbi_i16(a as i16, b as i16, c as i16);
+
+                    assert_eq!(baseline, fpnge);
+                    assert_eq!(baseline, stbi);
+                    assert_eq!(baseline as i16, stbi_i16);
+                }
+            }
+        }
+    }
+
+    #[test]
     fn roundtrip_ascending_previous_line() {
         // A multiple of 8, 6, 4, 3, 2, 1
         const LEN: u8 = 240;
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/lib.rs
similarity index 94%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/lib.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/lib.rs
index 9e8a211..54a789c 100644
--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/lib.rs
@@ -74,10 +74,8 @@
 pub use crate::adam7::expand_pass as expand_interlaced_row;
 pub use crate::adam7::Adam7Info;
 pub use crate::common::*;
-pub use crate::decoder::{
-    DecodeOptions, Decoded, Decoder, DecodingError, InterlaceInfo, InterlacedRow, Limits,
-    OutputInfo, Reader, StreamingDecoder,
-};
+pub use crate::decoder::stream::{DecodeOptions, Decoded, DecodingError, StreamingDecoder};
+pub use crate::decoder::{Decoder, InterlaceInfo, InterlacedRow, Limits, OutputInfo, Reader};
 pub use crate::encoder::{Encoder, EncodingError, StreamWriter, Writer};
 pub use crate::filter::{AdaptiveFilterType, FilterType};
 
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/srgb.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/srgb.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/srgb.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/srgb.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/test_utils.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/test_utils.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/test_utils.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/test_utils.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/text_metadata.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/text_metadata.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/text_metadata.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/text_metadata.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/traits.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/traits.rs
similarity index 100%
rename from third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/traits.rs
rename to third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/traits.rs
diff --git a/third_party/rust/fdeflate/v0_3/BUILD.gn b/third_party/rust/fdeflate/v0_3/BUILD.gn
index 44b8d41..e0ad598 100644
--- a/third_party/rust/fdeflate/v0_3/BUILD.gn
+++ b/third_party/rust/fdeflate/v0_3/BUILD.gn
@@ -13,20 +13,20 @@
   epoch = "0.3"
   crate_type = "rlib"
   crate_root =
-      "//third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/lib.rs"
+      "//third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/lib.rs"
   sources = [
-    "//third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/compress.rs",
-    "//third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/decompress.rs",
-    "//third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/decompress/tests/test_utils.rs",
-    "//third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/huffman.rs",
-    "//third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/lib.rs",
-    "//third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/src/tables.rs",
+    "//third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/compress.rs",
+    "//third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/decompress.rs",
+    "//third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/decompress/tests/test_utils.rs",
+    "//third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/huffman.rs",
+    "//third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/lib.rs",
+    "//third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/src/tables.rs",
   ]
   inputs = []
 
   build_native_rust_unit_tests = false
   edition = "2021"
-  cargo_pkg_version = "0.3.6"
+  cargo_pkg_version = "0.3.7"
   cargo_pkg_authors = "The image-rs Developers"
   cargo_pkg_name = "fdeflate"
   cargo_pkg_description = "Fast specialized deflate implementation"
diff --git a/third_party/rust/fdeflate/v0_3/README.chromium b/third_party/rust/fdeflate/v0_3/README.chromium
index 1168cd4..408d8d4 100644
--- a/third_party/rust/fdeflate/v0_3/README.chromium
+++ b/third_party/rust/fdeflate/v0_3/README.chromium
@@ -1,9 +1,9 @@
 Name: fdeflate
 URL: https://crates.io/crates/fdeflate
-Version: 0.3.6
-Revision: 4610c916ae1000c9b5839059340598a7c55130e8
+Version: 0.3.7
+Revision: c365c7e6ffa81feb2e1fb762eed7299f05c9b0ca
 License: Apache 2.0
-License File: //third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.6/LICENSE-APACHE
+License File: //third_party/rust/chromium_crates_io/vendor/fdeflate-0.3.7/LICENSE-APACHE
 Shipped: yes
 Security Critical: yes
 
diff --git a/third_party/rust/png/v0_17/BUILD.gn b/third_party/rust/png/v0_17/BUILD.gn
index 06afdefb..dac9857 100644
--- a/third_party/rust/png/v0_17/BUILD.gn
+++ b/third_party/rust/png/v0_17/BUILD.gn
@@ -13,31 +13,33 @@
   epoch = "0.17"
   crate_type = "rlib"
   crate_root =
-      "//third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/lib.rs"
+      "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/lib.rs"
   sources = [
-    "//third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/adam7.rs",
-    "//third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/benchable_apis.rs",
-    "//third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs",
-    "//third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs",
-    "//third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/interlace_info.rs",
-    "//third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs",
-    "//third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs",
-    "//third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/transform.rs",
-    "//third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/transform/palette.rs",
-    "//third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/zlib.rs",
-    "//third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/encoder.rs",
-    "//third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/filter.rs",
-    "//third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/lib.rs",
-    "//third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/srgb.rs",
-    "//third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/test_utils.rs",
-    "//third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/text_metadata.rs",
-    "//third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/traits.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/adam7.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/benchable_apis.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/chunk.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/common.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/interlace_info.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/mod.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/read_decoder.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/stream.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/transform.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/transform/palette.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/unfiltering_buffer.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/decoder/zlib.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/encoder.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/filter.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/lib.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/srgb.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/test_utils.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/text_metadata.rs",
+    "//third_party/rust/chromium_crates_io/vendor/png-0.17.15/src/traits.rs",
   ]
   inputs = []
 
   build_native_rust_unit_tests = false
   edition = "2018"
-  cargo_pkg_version = "0.17.14"
+  cargo_pkg_version = "0.17.15"
   cargo_pkg_authors = "The image-rs Developers"
   cargo_pkg_name = "png"
   cargo_pkg_description = "PNG decoding and encoding library in pure Rust"
diff --git a/third_party/rust/png/v0_17/README.chromium b/third_party/rust/png/v0_17/README.chromium
index 449849f..6644c98b 100644
--- a/third_party/rust/png/v0_17/README.chromium
+++ b/third_party/rust/png/v0_17/README.chromium
@@ -1,9 +1,9 @@
 Name: png
 URL: https://crates.io/crates/png
-Version: 0.17.14
-Revision: 347dc5dd3ddee8d2d3ef77a2f03a7d59b6c6fe80
+Version: 0.17.15
+Revision: 10644dbff4d5b5614199cbc81145838abdafd98c
 License: Apache 2.0
-License File: //third_party/rust/chromium_crates_io/vendor/png-0.17.14/LICENSE-APACHE
+License File: //third_party/rust/chromium_crates_io/vendor/png-0.17.15/LICENSE-APACHE
 Shipped: yes
 Security Critical: yes
 
diff --git a/third_party/skia b/third_party/skia
index 477c83c..7752438 160000
--- a/third_party/skia
+++ b/third_party/skia
@@ -1 +1 @@
-Subproject commit 477c83cf10f8323dcedbab72185db74d8292e505
+Subproject commit 77524387094192e4639253eeabca6ed3fb46dfc0
diff --git a/third_party/webrtc b/third_party/webrtc
index 2ca8f15..93f5f9e 160000
--- a/third_party/webrtc
+++ b/third_party/webrtc
@@ -1 +1 @@
-Subproject commit 2ca8f15991ba593509aae828d8ab28cb763ee1a1
+Subproject commit 93f5f9e8677d61eff3e8669ade6224195a421ebf
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index f2adac0..ee1623e1 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -46820,8 +46820,6 @@
       label="For AutofillDisabledVirtualCardSuggestion feature."/>
   <suffix name="AutofillExternalAccountProfileSuggestion"
       label="For AutofillExternalAccountProfileSuggestion feature."/>
-  <suffix name="AutofillManualFallback"
-      label="For AutofillManualFallback feature."/>
   <suffix name="AutofillPredictionImprovements"
       label="For AutofillPredictionImprovements feature."/>
   <suffix name="AutofillPredictionImprovementsBootstrapping"
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index afc16a0..33592f22 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -92,6 +92,14 @@
   <int value="1" label="Tab switcher UI shown and used to switch tabs"/>
 </enum>
 
+<enum name="AccessibilityHighContrastColorScheme">
+  <summary>Tracks the color scheme used when high contrast is enabled.</summary>
+  <int value="0" label="None"/>
+  <int value="1" label="Dark"/>
+  <int value="2" label="Light"/>
+  <int value="3" label="Custom"/>
+</enum>
+
 <enum name="AccessibilityId">
   <int value="1" label="SpokenFeedback"/>
   <int value="2" label="SelectToSpeak"/>
@@ -7277,7 +7285,7 @@
   <int value="1828" label="DocumentOrigin"/>
   <int value="1829" label="SubtleCryptoOnlyStrictSecureContextCheckFailed"/>
   <int value="1830" label="Canvas2DFilter"/>
-  <int value="1831" label="Canvas2DImageSmoothingQuality"/>
+  <int value="1831" label="OBSOLETE_Canvas2DImageSmoothingQuality"/>
   <int value="1832" label="CanvasToBlob"/>
   <int value="1833" label="CanvasToDataURL"/>
   <int value="1834" label="OffscreenCanvasConvertToBlob"/>
@@ -10921,6 +10929,7 @@
   <int value="5214"
       label="V8AuthenticatorAttestationResponse_GetPublicKey_Method"/>
   <int value="5215" label="CloseWatcherScriptConstructor"/>
+  <int value="5216" label="Canvas2DImageSmoothingQuality2"/>
 </enum>
 
 <!-- LINT.ThenChange(//third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom:WebFeature) -->
@@ -15611,7 +15620,6 @@
       label="AutofillReplaceCachedWebElementsByRendererIds:enabled"/>
   <int value="-1911153473" label="enable-easy-signin"/>
   <int value="-1910984835" label="CCTPreventTouches:enabled"/>
-  <int value="-1910725149" label="kFastPairHID:enabled"/>
   <int value="-1910438159" label="ShowNtpAtStartupAndroid:enabled"/>
   <int value="-1910427915" label="HttpsOnlyMode:enabled"/>
   <int value="-1910305102" label="EnhancedDeskAnimations:enabled"/>
@@ -18203,6 +18211,7 @@
   <int value="-866097797"
       label="ExperimentalAccessibilityDictationOffline:disabled"/>
   <int value="-865066703" label="CSSTextBoxTrim:disabled"/>
+  <int value="-864835103" label="FeedbackIncludeVariations:disabled"/>
   <int value="-864481314" label="FeedVideoInlinePlayback:disabled"/>
   <int value="-864266073" label="cros-regions-mode"/>
   <int value="-864234985" label="UseDdljsonApi:enabled"/>
@@ -24010,6 +24019,7 @@
   <int value="1458041527" label="ShowScrollableMVTOnNTPAndroid:enabled"/>
   <int value="1458085218" label="MultiDisplayOverviewAndSplitView:disabled"/>
   <int value="1458255488" label="BlinkGenPropertyTrees:enabled"/>
+  <int value="1458301097" label="FeedbackIncludeVariations:enabled"/>
   <int value="1458475849" label="D3D11VideoDecoder:disabled"/>
   <int value="1458583431" label="arc-use-auth-endpoint"/>
   <int value="1459529277" label="disable-text-input-focus-manager"/>
@@ -24791,7 +24801,6 @@
       label="WebAuthenticationFilterGooglePasskeys:disabled"/>
   <int value="1774991770" label="SafetyCheckPermissions:enabled"/>
   <int value="1775264688" label="SystemShortcutBehavior:disabled"/>
-  <int value="1775397180" label="kFastPairHID:disabled"/>
   <int value="1775475563" label="malware-interstitial-v3"/>
   <int value="1775652804" label="OmniboxBookmarkPaths:disabled"/>
   <int value="1775730290" label="OmniboxKeywordSearchButton:enabled"/>
@@ -30475,6 +30484,7 @@
       label="IDC_CONTENT_CONTEXT_AUTOFILL_PREDICTION_IMPROVEMENTS"/>
   <int value="152"
       label="IDC_CONTENT_CONTEXT_AUTOFILL_FALLBACK_PASSWORDS_USE_PASSKEY_FROM_ANOTHER_DEVICE"/>
+  <int value="153" label="IDC_CONTENT_CONTEXT_USE_PASSKEY_FROM_ANOTHER_DEVICE"/>
 </enum>
 
 <enum name="ReportProcessingResult">
diff --git a/tools/metrics/histograms/metadata/accessibility/histograms.xml b/tools/metrics/histograms/metadata/accessibility/histograms.xml
index 4e2139a..65e9f57 100644
--- a/tools/metrics/histograms/metadata/accessibility/histograms.xml
+++ b/tools/metrics/histograms/metadata/accessibility/histograms.xml
@@ -3089,6 +3089,17 @@
   </summary>
 </histogram>
 
+<histogram name="Accessibility.WinHighContrastTheme"
+    enum="AccessibilityHighContrastColorScheme" expires_after="2025-08-30">
+  <owner>aleventhal@chromium.org</owner>
+  <owner>almaher@microsoft.com</owner>
+  <summary>
+    Tracks which Windows high contrast theme is set in system settings (logged
+    once 45 secs after startup). AccessibilityHighContrastColorScheme::None
+    indicates that high contrast mode is not enabled.
+  </summary>
+</histogram>
+
 <histogram name="Accessibility.WinStickyKeys" enum="BooleanEnabled"
     expires_after="never">
 <!-- expires-never: usage drives a11y prioritization in browser and content. -->
diff --git a/tools/metrics/histograms/metadata/feature_engagement/histograms.xml b/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
index f02cc027..38506dcc6 100644
--- a/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
+++ b/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
@@ -71,9 +71,6 @@
   <variant name="IPH_AutofillExternalAccountProfileSuggestion"
       summary="message shown along with the externally created (e.g. in
                Google Pay) profile suggestion option in the Autofill dropdown"/>
-  <variant name="IPH_AutofillManualFallback"
-      summary="message educating users about the possibility of triggering
-               autofill on any field from the context menu"/>
   <variant name="IPH_AutofillPredictionImprovements"
       summary="snooze educating users about the possibility of turning on the
                prediction improvements feature from the settings page"/>
diff --git a/tools/metrics/histograms/metadata/gpu/enums.xml b/tools/metrics/histograms/metadata/gpu/enums.xml
index b5c1631b1..1a9cdbe 100644
--- a/tools/metrics/histograms/metadata/gpu/enums.xml
+++ b/tools/metrics/histograms/metadata/gpu/enums.xml
@@ -1237,8 +1237,7 @@
       label="Insufficient remaining bytes in Read(PaintShader) for
              color_bytes"/>
   <int value="7"
-      label="Insufficient remaining bytes in Read(PaintShader) for color_size
-             (obsolete)"/>
+      label="Insufficient remaining bytes in Read(PaintShader) for color_size"/>
   <int value="8"
       label="Insufficient remaining bytes in Read(PaintShader) for positions"/>
   <int value="9" label="Insufficient remaining bytes in Read(SkData)"/>
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml
index a8b38b1..1dcddb4c 100644
--- a/tools/metrics/histograms/metadata/page/histograms.xml
+++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -2836,8 +2836,8 @@
 </histogram>
 
 <histogram name="PageLoad.Experimental.PageVisitFinalStatus"
-    enum="PageVisitFinalStatus" expires_after="2024-12-22">
-  <owner>iclelland@chromium.org</owner>
+    enum="PageVisitFinalStatus" expires_after="2025-12-22">
+  <owner>sullivan@chromium.org</owner>
   <owner>speed-metrics-dev@chromium.org</owner>
   <summary>
     Determines the final status for this page load. That is, records whether the
diff --git a/tools/metrics/histograms/metadata/tab/enums.xml b/tools/metrics/histograms/metadata/tab/enums.xml
index 7f6c037..49f1081 100644
--- a/tools/metrics/histograms/metadata/tab/enums.xml
+++ b/tools/metrics/histograms/metadata/tab/enums.xml
@@ -26,6 +26,15 @@
 
 <enums>
 
+<!-- LINT.IfChange(AccidentalClickType) -->
+
+<enum name="AccidentalClickType">
+  <int value="0" label="Click"/>
+  <int value="1" label="Accidental Click"/>
+</enum>
+
+<!-- LINT.ThenChange(//chrome/browser/ui/views/tabs/tab_strip_combo_button.cc:AccidentalClickType) -->
+
 <enum name="BooleanFocusedTab">
   <int value="0" label="Not Focused"/>
   <int value="1" label="Focused"/>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml
index 3c12a6b..d2d0780 100644
--- a/tools/metrics/histograms/metadata/tab/histograms.xml
+++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -2078,6 +2078,20 @@
   </summary>
 </histogram>
 
+<histogram name="Tabs.NewTabButton.AccidentalClicks" enum="AccidentalClickType"
+    expires_after="2025-05-04">
+  <owner>emshack@chromium.org</owner>
+  <owner>shibalik@chromium.org</owner>
+  <owner>chrome-desktop-ui-sea@google.com</owner>
+  <summary>
+    Records the total number of new tab button clicks, and the number of
+    accidental clicks as measured by less than a second passing between clicking
+    the new tab button and clicking tab search. Percentage of accidental clicks
+    can be determined by accidental clicks / total clicks. This metric only logs
+    for clicks within the tab strip combo button.
+  </summary>
+</histogram>
+
 <histogram name="Tabs.NTPCountAtResume" units="tabs" expires_after="2025-04-13">
   <owner>thegreenfrog@chromium.org</owner>
   <owner>sugoi@chromium.org</owner>
@@ -2790,6 +2804,20 @@
   </summary>
 </histogram>
 
+<histogram name="Tabs.TabSearch.AccidentalClicks" enum="AccidentalClickType"
+    expires_after="2025-05-04">
+  <owner>emshack@chromium.org</owner>
+  <owner>shibalik@chromium.org</owner>
+  <owner>chrome-desktop-ui-sea@google.com</owner>
+  <summary>
+    Records the total number of tab search clicks, and the number of accidental
+    clicks as measured by less than a second passing between clicking tab search
+    and clicking the new tab button. Percentage of accidental clicks can be
+    determined by accidental clicks / total clicks. This metric only logs for
+    clicks within the tab strip combo button.
+  </summary>
+</histogram>
+
 <histogram name="Tabs.TabSearch.BubbleWidgetInitializationTime" units="ms"
     expires_after="2025-07-08">
   <owner>temao@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/variations/enums.xml b/tools/metrics/histograms/metadata/variations/enums.xml
index f587ca0a..f211ab9d0 100644
--- a/tools/metrics/histograms/metadata/variations/enums.xml
+++ b/tools/metrics/histograms/metadata/variations/enums.xml
@@ -285,6 +285,17 @@
   <int value="12" label="Null seed used">No seed used</int>
 </enum>
 
+<!-- LINT.IfChange(VariationsStateEncryptionStatus) -->
+
+<enum name="VariationsStateEncryptionStatus">
+  <int value="0" label="Success"/>
+  <int value="1" label="Input empty"/>
+  <int value="2" label="Hpke setup failure"/>
+  <int value="3" label="Hpke seal failure"/>
+</enum>
+
+<!-- LINT.ThenChange(//components/variations/net/variations_command_line.h:VariationsStateEncryptionStatus) -->
+
 </enums>
 
 </histogram-configuration>
diff --git a/tools/metrics/histograms/metadata/variations/histograms.xml b/tools/metrics/histograms/metadata/variations/histograms.xml
index 70cd6f9c..1a28dbab 100644
--- a/tools/metrics/histograms/metadata/variations/histograms.xml
+++ b/tools/metrics/histograms/metadata/variations/histograms.xml
@@ -766,6 +766,15 @@
   </summary>
 </histogram>
 
+<histogram name="Variations.VariationsStateEncryptionStatus"
+    enum="VariationsStateEncryptionStatus" expires_after="2025-12-01">
+  <owner>svenzheng@google.com</owner>
+  <owner>vivianz@google.com</owner>
+  <summary>
+    Capture the status of variations state encryption in Chrome feedback report.
+  </summary>
+</histogram>
+
 <histogram name="Variations.WebViewDownloadJobInterval" units="minutes"
     expires_after="2025-05-25">
   <owner>ntfschr@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/webauthn/enums.xml b/tools/metrics/histograms/metadata/webauthn/enums.xml
index 3ef6ae65..c7786eb1 100644
--- a/tools/metrics/histograms/metadata/webauthn/enums.xml
+++ b/tools/metrics/histograms/metadata/webauthn/enums.xml
@@ -74,6 +74,15 @@
   <int value="4" label="prepareGetCredential request failed."/>
 </enum>
 
+<enum name="OnboardingEvents">
+  <int value="0" label="Started (Create GPM passkey dialog shown)"/>
+  <int value="1" label="Succeeded (GPM passkey created)"/>
+  <int value="2" label="Cancelled - Passkey creation - Cancel"/>
+  <int value="3" label="Cancelled - Passkey creation - Save another way"/>
+  <int value="4" label="Cancelled - PIN create modal"/>
+  <int value="5" label="Failure dialog shown"/>
+</enum>
+
 <enum name="SignalAllAcceptedCredentialsResult">
   <int value="0" label="No passkeys were removed"/>
   <int value="1" label="A passkey was removed"/>
diff --git a/tools/metrics/histograms/metadata/webauthn/histograms.xml b/tools/metrics/histograms/metadata/webauthn/histograms.xml
index c1029c5e..2c2b8d2 100644
--- a/tools/metrics/histograms/metadata/webauthn/histograms.xml
+++ b/tools/metrics/histograms/metadata/webauthn/histograms.xml
@@ -357,6 +357,15 @@
   </summary>
 </histogram>
 
+<histogram name="WebAuthentication.OnboardingEvents" enum="OnboardingEvents"
+    expires_after="2024-12-31">
+  <owner>natiahlyi@google.com</owner>
+  <owner>chrome-webauthn@google.com</owner>
+  <summary>
+    Recorded when the user interacts with modals in the GPM onboarding flow.
+  </summary>
+</histogram>
+
 <histogram
     name="WebAuthentication.SignalAllAcceptedCredentialsRemovedGPMPasskey"
     enum="SignalAllAcceptedCredentialsResult" expires_after="2025-09-17">
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 0aea96dd..c39246dd 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -21730,253 +21730,6 @@
   </metric>
 </event>
 
-<event name="TabManager.LifecycleStateChange">
-  <owner>chrisha@chromium.org</owner>
-  <owner>fdoray@chromium.org</owner>
-  <summary>
-    Collects information about when and why a lifecycle state change was
-    attempted, and information about the outcome of the attempt.
-  </summary>
-  <metric name="FailureGlobalDisallowlist" enum="Boolean">
-    <summary>
-      Boolean indicating that the tab was explicitly opted out of the
-      intervention via the global disallowlist.
-    </summary>
-  </metric>
-  <metric name="FailureHeuristicAudio" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the origin
-      has historically been observed emitting audio while in the background.
-    </summary>
-  </metric>
-  <metric name="FailureHeuristicFavicon" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the origin
-      has historically been observed updating its favicon while in the
-      background.
-    </summary>
-  </metric>
-  <metric name="FailureHeuristicInsufficientObservation" enum="Boolean">
-    <summary>
-      Boolean indicating that the site is still being observed locally in order
-      to determine which features are in use. In the meantime, it is protected
-      from this intervention.
-    </summary>
-  </metric>
-  <metric name="FailureHeuristicNotifications" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the origin
-      has historically been observed making use of notifications while in the
-      background.
-    </summary>
-  </metric>
-  <metric name="FailureHeuristicTitle" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the origin
-      has historically been observed updating its tab title while in the
-      background.
-    </summary>
-  </metric>
-  <metric name="FailureLifecyclesEnterprisePolicyOptOut" enum="Boolean">
-    <summary>
-      Boolean indicating that the browser was explicitly opted out of the
-      intervention via enterprise policy.
-    </summary>
-  </metric>
-  <metric name="FailureLivePictureInPicture" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the tab is
-      displaying content in picture-in-picture.
-    </summary>
-  </metric>
-  <metric name="FailureLiveStateCapturing" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the tab is
-      currently capturing user media (making use of webcam or microphone, for
-      example).
-    </summary>
-  </metric>
-  <metric name="FailureLiveStateDesktopCapture" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the tab is
-      currently capturing a window or screen.
-    </summary>
-  </metric>
-  <metric name="FailureLiveStateDevToolsOpen" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the tab is
-      currently using DevTools.
-    </summary>
-  </metric>
-  <metric name="FailureLiveStateExtensionDisallowed" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed by an extension.
-    </summary>
-  </metric>
-  <metric name="FailureLiveStateFormEntry" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the tab
-      currently contains text form entry.
-    </summary>
-  </metric>
-  <metric name="FailureLiveStateHasNotificationsPermission" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the tab
-      has the permission to use notifications.
-    </summary>
-  </metric>
-  <metric name="FailureLiveStateIsPDF" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the tab is
-      currently hosting a PDF.
-    </summary>
-  </metric>
-  <metric name="FailureLiveStateMirroring" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the tab is
-      currently being mirrored (casting its contents, for example).
-    </summary>
-  </metric>
-  <metric name="FailureLiveStatePlayingAudio" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the tab is
-      currently playing audio.
-    </summary>
-  </metric>
-  <metric name="FailureLiveStateSharingBrowsingInstance" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the tab is
-      sharing its BrowsingInstance with at least one other tab.
-    </summary>
-  </metric>
-  <metric name="FailureLiveStateUsingBluetooth" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the tab is
-      currently connected to at least one bluetooth device.
-    </summary>
-  </metric>
-  <metric name="FailureLiveStateUsingIndexedDBLock" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the tab is
-      currently holding at least one IndexedDB lock.
-    </summary>
-  </metric>
-  <metric name="FailureLiveStateUsingWebLock" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the tab is
-      currently holding at least one WebLock.
-    </summary>
-  </metric>
-  <metric name="FailureLiveStateUsingWebSockets" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the tab is
-      currently using WebSockets.
-    </summary>
-  </metric>
-  <metric name="FailureLiveStateUsingWebUSB" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the tab is
-      currently using WebUSB.
-    </summary>
-  </metric>
-  <metric name="FailureLiveStateVisible" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the tab is
-      currently visible.
-    </summary>
-  </metric>
-  <metric name="FailureLiveWebApp" enum="Boolean">
-    <summary>
-      Boolean indicating that the intervention was disallowed because the tab is
-      a web application window.
-    </summary>
-  </metric>
-  <metric name="FailureOriginTrialOptOut" enum="Boolean">
-    <summary>
-      Boolean indicating that the tab explicitly opted out of the intervention
-      via origin trial.
-    </summary>
-  </metric>
-  <metric name="FailureOriginTrialUnknown" enum="Boolean">
-    <summary>
-      Boolean indicating that the tab did not report its origin trial
-      opt-in/opt-out yet.
-    </summary>
-  </metric>
-  <metric name="LifecycleStateChangeReason">
-    <summary>
-      The reason the lifecycle state change was attempted. This corresponds to
-      the LifecycleStateChangeReason enumeration in lifecycle_unit_state.mojom.
-    </summary>
-  </metric>
-  <metric name="NewLifecycleState">
-    <summary>
-      The lifecycle state the tab will be in after the state change. Corresponds
-      to a value from the LifecycleUnitState enum defined in
-      lifecycle_unit_state.mojom.
-    </summary>
-  </metric>
-  <metric name="OldLifecycleState">
-    <summary>
-      The lifecycle state the tab was in prior to the state change. Corresponds
-      to a value from the LifecycleUnitState enum defined in
-      lifecycle_unit_state.mojom.
-    </summary>
-  </metric>
-  <metric name="Outcome" enum="Boolean">
-    <summary>
-      Whether or not the state change was successful. The various Failure and
-      Success booleans encode the actual reasons for this outcome. Note that
-      multiple success and failure reasons may be encoded for a single decision.
-      The presence of any failure bit indicates a negative outcome. If only
-      success bits are present the outcome is positive.
-    </summary>
-  </metric>
-  <metric name="SuccessGlobalAllowlist" enum="Boolean">
-    <summary>
-      Boolean indicating that the tab was explicitly opted in to the
-      intervention via the global allowlist.
-    </summary>
-  </metric>
-  <metric name="SuccessHeuristic" enum="Boolean">
-    <summary>
-      Boolean indicating that the tab was deemed safe for the intervention via
-      local observations and heuristics.
-    </summary>
-  </metric>
-  <metric name="SuccessOriginTrialOptIn" enum="Boolean">
-    <summary>
-      Boolean indicating that the tab explicitly opted in to the intervention
-      via origin trial.
-    </summary>
-  </metric>
-  <metric name="TimeSinceNavigationMs">
-    <summary>
-      The time elapsed (in milliseconds) since the top-level navigation was
-      committed that loaded this tab's content.
-    </summary>
-  </metric>
-  <metric name="TimeSinceVisibilityStateChangeMs">
-    <summary>
-      The amount of time that has passed (in milliseconds) since the last
-      visibility state change.
-    </summary>
-  </metric>
-  <metric name="TransitionForced" enum="Boolean">
-    <summary>
-      This is set if the transition to the new lifecycle state was forced by the
-      browser because the content took too long to respond to the lifecycle
-      event.
-    </summary>
-  </metric>
-  <metric name="VisibilityState">
-    <summary>
-      The current visibility state. This is an integer value corresponding to
-      the enumeration in content/public/browser/visibility.h.
-    </summary>
-  </metric>
-</event>
-
 <event
     name="TabManager.SessionRestore.ForegroundTab.ExpectedTaskQueueingDurationInfo">
   <owner>zhenw@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 e738eb52..3e2b4da 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,8 +5,8 @@
             "full_remote_path": "perfetto-luci-artifacts/65d6491a008cb4d626effb25f72219dc179188d8/linux-arm64/trace_processor_shell"
         },
         "win": {
-            "hash": "575940837ca3c6fd6277a581d9e4cf62ccfea4cf",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/d3990a1c9d27761d8de4290aeadb879a60ecbc90/trace_processor_shell.exe"
+            "hash": "6156db445eb1a50089813ae155bc5bf0ba037265",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/3e438dc27a871f3c74f592101c5fa7b3cfe1f85b/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "8d23f6f07e4b3472196a878035fc304903813da3",
diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc
index 6f34a88e..ca9ba77e 100644
--- a/ui/accessibility/ax_tree.cc
+++ b/ui/accessibility/ax_tree.cc
@@ -1098,7 +1098,7 @@
 }
 
 bool AXTree::Unserialize(const AXTreeUpdate& update) {
-#if AX_FAIL_FAST_BUILD()
+#if AX_FAIL_FAST_BUILD() && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
   for (const auto& new_data : update.nodes)
     CHECK(new_data.id != kInvalidAXNodeID)
         << "AXTreeUpdate contains invalid node: " << update.ToString();
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc
index a70efc53..69b7533b 100644
--- a/ui/base/ui_base_features.cc
+++ b/ui/base/ui_base_features.cc
@@ -165,11 +165,6 @@
              "StylusSpecificTapSlop",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
-// Allows system caption style for WebVTT Captions.
-BASE_FEATURE(kSystemCaptionStyle,
-             "SystemCaptionStyle",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 // When enabled, the feature will query the OS for a default cursor size,
 // to be used in determining the concrete object size of a custom cursor in
 // blink. Currently enabled by default on Windows only.
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h
index d14f5d0..90c73ab 100644
--- a/ui/base/ui_base_features.h
+++ b/ui/base/ui_base_features.h
@@ -22,7 +22,6 @@
 #endif  // BUILDFLAG(IS_CHROMEOS)
 COMPONENT_EXPORT(UI_BASE_FEATURES)
 BASE_DECLARE_FEATURE(kInputMethodSettingsUiUpdate);
-COMPONENT_EXPORT(UI_BASE_FEATURES) BASE_DECLARE_FEATURE(kSystemCaptionStyle);
 COMPONENT_EXPORT(UI_BASE_FEATURES) BASE_DECLARE_FEATURE(kSystemKeyboardLock);
 COMPONENT_EXPORT(UI_BASE_FEATURES)
 BASE_DECLARE_FEATURE(kUiCompositorScrollWithLayers);
diff --git a/ui/chromeos/translations/ui_chromeos_strings_el.xtb b/ui/chromeos/translations/ui_chromeos_strings_el.xtb
index e485a08..e2dbfd0 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_el.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_el.xtb
@@ -637,7 +637,7 @@
 <translation id="5760252553414789727">Επιλέχθηκαν <ph name="SELECTED_FILES_COUNT" /> στοιχεία</translation>
 <translation id="5763377084591234761">Γερμανικά (Ελβετία)</translation>
 <translation id="5769519078756170258">Κεντρικός υπολογιστής ή τομέας προς εξαίρεση</translation>
-<translation id="5775750595919327203">Ουρντού</translation>
+<translation id="5775750595919327203">Ούρντου</translation>
 <translation id="5776325638577448643">Διαγραφή και διαμόρφωση</translation>
 <translation id="57838592816432529">Σίγαση</translation>
 <translation id="5788127256798019331">Αρχεία Play</translation>
diff --git a/ui/gl/features.gni b/ui/gl/features.gni
index a548a4d..78cd481 100644
--- a/ui/gl/features.gni
+++ b/ui/gl/features.gni
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/config/cast.gni")
+import("//build/config/chrome_build.gni")
 import("//chrome/version.gni")
 
 declare_args() {
@@ -12,7 +13,8 @@
   # Should Dawn support be compiled to back the WebGPU implementation?
   # Also controls linking Dawn dependencies in such as SPIRV-Tools/SPIRV-Cross.
   use_dawn = is_apple || is_win || is_chromeos || (is_linux && !is_castos) ||
-             (is_android && target_cpu != "x86" && target_cpu != "x64")
+             (is_android && target_cpu != "x86" && target_cpu != "x64") ||
+             is_desktop_android
 
   # Should Dawn test binaries (unittests, end2end_tests, perf_tests) be built?
   # Independent of use_dawn, which controls whether Dawn is used in Chromium.
diff --git a/ui/gl/gl_switches.cc b/ui/gl/gl_switches.cc
index 300645d7..fa950e1 100644
--- a/ui/gl/gl_switches.cc
+++ b/ui/gl/gl_switches.cc
@@ -330,6 +330,22 @@
   if (active_gpu.driverId == VK_DRIVER_ID_IMAGINATION_PROPRIETARY) {
     return false;
   }
+
+  // Exclude old ARM drivers due to crashes related to creating
+  // AHB-based Video images in Vulkan.  http://anglebug.com/382676807.
+  if (active_gpu.driverId == VK_DRIVER_ID_ARM_PROPRIETARY &&
+      active_gpu.detailedDriverVersion.major <= 32) {
+    return false;
+  }
+
+  // Exclude old Qualcomm drivers due to inefficient (and buggy) fallback
+  // to CPU path in glCopyTextureCHROMIUM with multi-plane images.
+  // http://anglebug.com/383056998.
+  if (active_gpu.driverId == VK_DRIVER_ID_QUALCOMM_PROPRIETARY &&
+      (active_gpu.detailedDriverVersion.major != 512 ||
+       active_gpu.detailedDriverVersion.minor <= 530)) {
+    return false;
+  }
 #endif  // BUILDFLAG(IS_ANDROID)
 
 #if BUILDFLAG(IS_LINUX)
diff --git a/ui/native_theme/caption_style_mac.mm b/ui/native_theme/caption_style_mac.mm
index 322868f4..4c95304b 100644
--- a/ui/native_theme/caption_style_mac.mm
+++ b/ui/native_theme/caption_style_mac.mm
@@ -11,7 +11,6 @@
 #include "base/strings/sys_string_conversions.h"
 #include "skia/ext/skia_utils_mac.h"
 #include "third_party/skia/include/core/SkColor.h"
-#include "ui/base/ui_base_features.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/native_theme/caption_style.h"
 
@@ -170,9 +169,6 @@
 
 // static
 std::optional<CaptionStyle> CaptionStyle::FromSystemSettings() {
-  if (!base::FeatureList::IsEnabled(features::kSystemCaptionStyle))
-    return std::nullopt;
-
   CaptionStyle style;
 
   style.text_color = GetMAForegroundColorAndOpacityAsCSSColor();
diff --git a/ui/native_theme/caption_style_win.cc b/ui/native_theme/caption_style_win.cc
index f34769e..8d248c3 100644
--- a/ui/native_theme/caption_style_win.cc
+++ b/ui/native_theme/caption_style_win.cc
@@ -167,7 +167,6 @@
 
 std::optional<CaptionStyle> InitializeFromSystemSettings() {
   TRACE_EVENT0("ui", "InitializeFromSystemSettings");
-  DCHECK(base::FeatureList::IsEnabled(features::kSystemCaptionStyle));
 
   base::win::ScopedHString closed_caption_properties_string =
       base::win::ScopedHString::Create(
@@ -265,11 +264,7 @@
 }  // namespace
 
 std::optional<CaptionStyle> CaptionStyle::FromSystemSettings() {
-  if (base::FeatureList::IsEnabled(features::kSystemCaptionStyle)) {
-    return InitializeFromSystemSettings();
-  }
-  // Return default CaptionStyle if kSystemCaptionStyle is not enabled.
-  return std::nullopt;
+  return InitializeFromSystemSettings();
 }
 
 }  // namespace ui
diff --git a/ui/native_theme/caption_style_win_unittest.cc b/ui/native_theme/caption_style_win_unittest.cc
index 12a49ef..eadfb60 100644
--- a/ui/native_theme/caption_style_win_unittest.cc
+++ b/ui/native_theme/caption_style_win_unittest.cc
@@ -15,7 +15,6 @@
 // (we obtain a CaptionStyle).
 TEST(CaptionStyleWinTest, TestWinCaptionStyle) {
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(features::kSystemCaptionStyle);
 
   base::win::ScopedCOMInitializer com_initializer;
   ASSERT_TRUE(com_initializer.Succeeded());
diff --git a/ui/native_theme/native_theme.h b/ui/native_theme/native_theme.h
index b2a7455c..12aba4a 100644
--- a/ui/native_theme/native_theme.h
+++ b/ui/native_theme/native_theme.h
@@ -146,6 +146,10 @@
     kMaxValue = kCustom,
   };
 
+  // IMPORTANT!
+  // This enum is reported in metrics. Do not reorder; add additional values at
+  // the end.
+  //
   // This represents the OS-level high contrast theme. kNone unless the default
   // system color scheme is kPlatformHighContrast.
   enum class PlatformHighContrastColorScheme {
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc b/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc
index a5dff082..783c9a8 100644
--- a/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc
+++ b/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc
@@ -315,12 +315,16 @@
 bool DrmOverlayManager::CanHandleCandidate(
     const OverlaySurfaceCandidate& candidate,
     gfx::AcceleratedWidget widget) const {
-  if (candidate.buffer_size.IsEmpty())
+  if (candidate.buffer_size.IsEmpty()) {
+    VLOG(3) << "Overlay Rejected: buffer_size="
+            << candidate.buffer_size.ToString();
     return false;
+  }
 
   if (!absl::holds_alternative<gfx::OverlayTransform>(candidate.transform) ||
       absl::get<gfx::OverlayTransform>(candidate.transform) ==
           gfx::OVERLAY_TRANSFORM_INVALID) {
+    VLOG(3) << "Overlay Rejected: invalid transform";
     return false;
   }
 
diff --git a/v8 b/v8
index d1e6b9b..77ca46a 160000
--- a/v8
+++ b/v8
@@ -1 +1 @@
-Subproject commit d1e6b9bb90ea666c31170f6e6688d7d5fc3690e2
+Subproject commit 77ca46aba3bd91f1cc8d43051ab651747b10242c